net/qede/base: add APIs for dscp priority map configuration
[dpdk.git] / drivers / net / qede / base / ecore_dcbx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (c) 2016 - 2018 Cavium Inc.
3  * All rights reserved.
4  * www.cavium.com
5  */
6
7 #include "bcm_osal.h"
8 #include "ecore.h"
9 #include "ecore_sp_commands.h"
10 #include "ecore_dcbx.h"
11 #include "ecore_cxt.h"
12 #include "ecore_gtt_reg_addr.h"
13 #include "ecore_iro.h"
14 #include "ecore_iov_api.h"
15
16 #define ECORE_DCBX_MAX_MIB_READ_TRY     (100)
17 #define ECORE_ETH_TYPE_DEFAULT          (0)
18
19 #define ECORE_DCBX_INVALID_PRIORITY     0xFF
20
21 /* Get Traffic Class from priority traffic class table, 4 bits represent
22  * the traffic class corresponding to the priority.
23  */
24 #define ECORE_DCBX_PRIO2TC(prio_tc_tbl, prio) \
25                 ((u32)(prio_tc_tbl >> ((7 - prio) * 4)) & 0x7)
26
27 static bool ecore_dcbx_app_ethtype(u32 app_info_bitmap)
28 {
29         return !!(GET_MFW_FIELD(app_info_bitmap, DCBX_APP_SF) ==
30                   DCBX_APP_SF_ETHTYPE);
31 }
32
33 static bool ecore_dcbx_ieee_app_ethtype(u32 app_info_bitmap)
34 {
35         u8 mfw_val = GET_MFW_FIELD(app_info_bitmap, DCBX_APP_SF_IEEE);
36
37         /* Old MFW */
38         if (mfw_val == DCBX_APP_SF_IEEE_RESERVED)
39                 return ecore_dcbx_app_ethtype(app_info_bitmap);
40
41         return !!(mfw_val == DCBX_APP_SF_IEEE_ETHTYPE);
42 }
43
44 static bool ecore_dcbx_app_port(u32 app_info_bitmap)
45 {
46         return !!(GET_MFW_FIELD(app_info_bitmap, DCBX_APP_SF) ==
47                   DCBX_APP_SF_PORT);
48 }
49
50 static bool ecore_dcbx_ieee_app_port(u32 app_info_bitmap, u8 type)
51 {
52         u8 mfw_val = GET_MFW_FIELD(app_info_bitmap, DCBX_APP_SF_IEEE);
53
54         /* Old MFW */
55         if (mfw_val == DCBX_APP_SF_IEEE_RESERVED)
56                 return ecore_dcbx_app_port(app_info_bitmap);
57
58         return !!(mfw_val == type || mfw_val == DCBX_APP_SF_IEEE_TCP_UDP_PORT);
59 }
60
61 static bool ecore_dcbx_default_tlv(u32 app_info_bitmap, u16 proto_id, bool ieee)
62 {
63         bool ethtype;
64
65         if (ieee)
66                 ethtype = ecore_dcbx_ieee_app_ethtype(app_info_bitmap);
67         else
68                 ethtype = ecore_dcbx_app_ethtype(app_info_bitmap);
69
70         return !!(ethtype && (proto_id == ECORE_ETH_TYPE_DEFAULT));
71 }
72
73 static bool ecore_dcbx_iwarp_tlv(struct ecore_hwfn *p_hwfn, u32 app_info_bitmap,
74                                  u16 proto_id, bool ieee)
75 {
76         bool port;
77
78         if (!p_hwfn->p_dcbx_info->iwarp_port)
79                 return false;
80
81         if (ieee)
82                 port = ecore_dcbx_ieee_app_port(app_info_bitmap,
83                                                 DCBX_APP_SF_IEEE_TCP_PORT);
84         else
85                 port = ecore_dcbx_app_port(app_info_bitmap);
86
87         return !!(port && (proto_id == p_hwfn->p_dcbx_info->iwarp_port));
88 }
89
90 static void
91 ecore_dcbx_dp_protocol(struct ecore_hwfn *p_hwfn,
92                        struct ecore_dcbx_results *p_data)
93 {
94         enum dcbx_protocol_type id;
95         int i;
96
97         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "DCBX negotiated: %d\n",
98                    p_data->dcbx_enabled);
99
100         for (i = 0; i < OSAL_ARRAY_SIZE(ecore_dcbx_app_update); i++) {
101                 id = ecore_dcbx_app_update[i].id;
102
103                 DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
104                            "%s info: update %d, enable %d, prio %d, tc %d,"
105                            " num_active_tc %d dscp_enable = %d dscp_val = %d\n",
106                            ecore_dcbx_app_update[i].name,
107                            p_data->arr[id].update,
108                            p_data->arr[id].enable, p_data->arr[id].priority,
109                            p_data->arr[id].tc, p_hwfn->hw_info.num_active_tc,
110                            p_data->arr[id].dscp_enable,
111                            p_data->arr[id].dscp_val);
112         }
113 }
114
115 u8 ecore_dcbx_get_dscp_value(struct ecore_hwfn *p_hwfn, u8 pri)
116 {
117         struct ecore_dcbx_dscp_params *dscp = &p_hwfn->p_dcbx_info->get.dscp;
118         u8 i;
119
120         if (!dscp->enabled)
121                 return ECORE_DCBX_DSCP_DISABLED;
122
123         for (i = 0; i < ECORE_DCBX_DSCP_SIZE; i++)
124                 if (pri == dscp->dscp_pri_map[i])
125                         return i;
126
127         return ECORE_DCBX_DSCP_DISABLED;
128 }
129
130 static void
131 ecore_dcbx_set_params(struct ecore_dcbx_results *p_data,
132                       struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
133                       bool enable, u8 prio, u8 tc,
134                       enum dcbx_protocol_type type,
135                       enum ecore_pci_personality personality)
136 {
137         /* PF update ramrod data */
138         p_data->arr[type].enable = enable;
139         p_data->arr[type].priority = prio;
140         p_data->arr[type].tc = tc;
141         p_data->arr[type].dscp_val = ecore_dcbx_get_dscp_value(p_hwfn, prio);
142         if (p_data->arr[type].dscp_val == ECORE_DCBX_DSCP_DISABLED) {
143                 p_data->arr[type].dscp_enable = false;
144                 p_data->arr[type].dscp_val = 0;
145         } else {
146                 p_data->arr[type].dscp_enable = true;
147         }
148         p_data->arr[type].update = UPDATE_DCB_DSCP;
149
150         /* Do not add valn tag 0 when DCB is enabled and port is in UFP mode */
151         if (OSAL_TEST_BIT(ECORE_MF_UFP_SPECIFIC, &p_hwfn->p_dev->mf_bits))
152                 p_data->arr[type].dont_add_vlan0 = true;
153
154         /* QM reconf data */
155         if (p_hwfn->hw_info.personality == personality)
156                 p_hwfn->hw_info.offload_tc = tc;
157
158         /* Configure dcbx vlan priority in doorbell block for roce EDPM */
159         if (OSAL_TEST_BIT(ECORE_MF_UFP_SPECIFIC, &p_hwfn->p_dev->mf_bits) &&
160             (type == DCBX_PROTOCOL_ROCE)) {
161                 ecore_wr(p_hwfn, p_ptt, DORQ_REG_TAG1_OVRD_MODE, 1);
162                 ecore_wr(p_hwfn, p_ptt, DORQ_REG_PF_PCP_BB_K2, prio << 1);
163         }
164 }
165
166 /* Update app protocol data and hw_info fields with the TLV info */
167 static void
168 ecore_dcbx_update_app_info(struct ecore_dcbx_results *p_data,
169                            struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
170                            bool enable, u8 prio, u8 tc,
171                            enum dcbx_protocol_type type)
172 {
173         enum ecore_pci_personality personality;
174         enum dcbx_protocol_type id;
175         int i;
176
177         for (i = 0; i < OSAL_ARRAY_SIZE(ecore_dcbx_app_update); i++) {
178                 id = ecore_dcbx_app_update[i].id;
179
180                 if (type != id)
181                         continue;
182
183                 personality = ecore_dcbx_app_update[i].personality;
184
185                 ecore_dcbx_set_params(p_data, p_hwfn, p_ptt, enable,
186                                       prio, tc, type, personality);
187         }
188 }
189
190 static enum _ecore_status_t
191 ecore_dcbx_get_app_priority(u8 pri_bitmap, u8 *priority)
192 {
193         u32 pri_mask, pri = ECORE_MAX_PFC_PRIORITIES;
194         u32 index = ECORE_MAX_PFC_PRIORITIES - 1;
195         enum _ecore_status_t rc = ECORE_SUCCESS;
196
197         /* Bitmap 1 corresponds to priority 0, return priority 0 */
198         if (pri_bitmap == 1) {
199                 *priority = 0;
200                 return rc;
201         }
202
203         /* Choose the highest priority */
204         while ((pri == ECORE_MAX_PFC_PRIORITIES) && index) {
205                 pri_mask = 1 << index;
206                 if (pri_bitmap & pri_mask)
207                         pri = index;
208                 index--;
209         }
210
211         if (pri < ECORE_MAX_PFC_PRIORITIES)
212                 *priority = (u8)pri;
213         else
214                 rc = ECORE_INVAL;
215
216         return rc;
217 }
218
219 static bool
220 ecore_dcbx_get_app_protocol_type(struct ecore_hwfn *p_hwfn,
221                                  u32 app_prio_bitmap, u16 id,
222                                  enum dcbx_protocol_type *type, bool ieee)
223 {
224         if (ecore_dcbx_default_tlv(app_prio_bitmap, id, ieee)) {
225                 *type = DCBX_PROTOCOL_ETH;
226         } else {
227                 *type = DCBX_MAX_PROTOCOL_TYPE;
228                 DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
229                             "No action required, App TLV entry = 0x%x\n",
230                            app_prio_bitmap);
231                 return false;
232         }
233
234         return true;
235 }
236
237 /* Parse app TLV's to update TC information in hw_info structure for
238  * reconfiguring QM. Get protocol specific data for PF update ramrod command.
239  */
240 static enum _ecore_status_t
241 ecore_dcbx_process_tlv(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
242                        struct ecore_dcbx_results *p_data,
243                        struct dcbx_app_priority_entry *p_tbl, u32 pri_tc_tbl,
244                        int count, u8 dcbx_version)
245 {
246         enum dcbx_protocol_type type;
247         bool enable, ieee, eth_tlv;
248         u8 tc, priority_map;
249         u16 protocol_id;
250         u8 priority;
251         enum _ecore_status_t rc = ECORE_SUCCESS;
252         int i;
253
254         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
255                    "Num APP entries = %d pri_tc_tbl = 0x%x dcbx_version = %u\n",
256                    count, pri_tc_tbl, dcbx_version);
257
258         ieee = (dcbx_version == DCBX_CONFIG_VERSION_IEEE);
259         eth_tlv = false;
260         /* Parse APP TLV */
261         for (i = 0; i < count; i++) {
262                 protocol_id = GET_MFW_FIELD(p_tbl[i].entry,
263                                             DCBX_APP_PROTOCOL_ID);
264                 priority_map = GET_MFW_FIELD(p_tbl[i].entry, DCBX_APP_PRI_MAP);
265                 DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "Id = 0x%x pri_map = %u\n",
266                            protocol_id, priority_map);
267                 rc = ecore_dcbx_get_app_priority(priority_map, &priority);
268                 if (rc == ECORE_INVAL) {
269                         DP_ERR(p_hwfn, "Invalid priority\n");
270                         return ECORE_INVAL;
271                 }
272
273                 tc = ECORE_DCBX_PRIO2TC(pri_tc_tbl, priority);
274                 if (ecore_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry,
275                                                      protocol_id, &type,
276                                                      ieee)) {
277                         /* ETH always have the enable bit reset, as it gets
278                          * vlan information per packet. For other protocols,
279                          * should be set according to the dcbx_enabled
280                          * indication, but we only got here if there was an
281                          * app tlv for the protocol, so dcbx must be enabled.
282                          */
283                         if (type == DCBX_PROTOCOL_ETH) {
284                                 enable = false;
285                                 eth_tlv = true;
286                         } else {
287                                 enable = true;
288                         }
289
290                         ecore_dcbx_update_app_info(p_data, p_hwfn, p_ptt,
291                                                    enable, priority, tc, type);
292                 }
293         }
294
295         /* If Eth TLV is not detected, use UFP TC as default TC */
296         if (OSAL_TEST_BIT(ECORE_MF_UFP_SPECIFIC,
297                           &p_hwfn->p_dev->mf_bits) && !eth_tlv)
298                 p_data->arr[DCBX_PROTOCOL_ETH].tc = p_hwfn->ufp_info.tc;
299
300         /* Update ramrod protocol data and hw_info fields
301          * with default info when corresponding APP TLV's are not detected.
302          * The enabled field has a different logic for ethernet as only for
303          * ethernet dcb should disabled by default, as the information arrives
304          * from the OS (unless an explicit app tlv was present).
305          */
306         tc = p_data->arr[DCBX_PROTOCOL_ETH].tc;
307         priority = p_data->arr[DCBX_PROTOCOL_ETH].priority;
308         for (type = 0; type < DCBX_MAX_PROTOCOL_TYPE; type++) {
309                 if (p_data->arr[type].update)
310                         continue;
311
312                 /* if no app tlv was present, don't override in FW */
313                 ecore_dcbx_update_app_info(p_data, p_hwfn, p_ptt, false,
314                                            priority, tc, type);
315         }
316
317         return ECORE_SUCCESS;
318 }
319
320 /* Parse app TLV's to update TC information in hw_info structure for
321  * reconfiguring QM. Get protocol specific data for PF update ramrod command.
322  */
323 static enum _ecore_status_t
324 ecore_dcbx_process_mib_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
325 {
326         struct dcbx_app_priority_feature *p_app;
327         struct dcbx_app_priority_entry *p_tbl;
328         struct ecore_dcbx_results data = { 0 };
329         struct dcbx_ets_feature *p_ets;
330         struct ecore_hw_info *p_info;
331         u32 pri_tc_tbl, flags;
332         u8 dcbx_version;
333         int num_entries;
334         enum _ecore_status_t rc = ECORE_SUCCESS;
335
336         flags = p_hwfn->p_dcbx_info->operational.flags;
337         dcbx_version = GET_MFW_FIELD(flags, DCBX_CONFIG_VERSION);
338
339         p_app = &p_hwfn->p_dcbx_info->operational.features.app;
340         p_tbl = p_app->app_pri_tbl;
341
342         p_ets = &p_hwfn->p_dcbx_info->operational.features.ets;
343         pri_tc_tbl = p_ets->pri_tc_tbl[0];
344
345         p_info = &p_hwfn->hw_info;
346         num_entries = GET_MFW_FIELD(p_app->flags, DCBX_APP_NUM_ENTRIES);
347
348         rc = ecore_dcbx_process_tlv(p_hwfn, p_ptt, &data, p_tbl, pri_tc_tbl,
349                                     num_entries, dcbx_version);
350         if (rc != ECORE_SUCCESS)
351                 return rc;
352
353         p_info->num_active_tc = GET_MFW_FIELD(p_ets->flags, DCBX_ETS_MAX_TCS);
354         p_hwfn->qm_info.ooo_tc = GET_MFW_FIELD(p_ets->flags, DCBX_OOO_TC);
355         data.pf_id = p_hwfn->rel_pf_id;
356         data.dcbx_enabled = !!dcbx_version;
357
358         ecore_dcbx_dp_protocol(p_hwfn, &data);
359
360         OSAL_MEMCPY(&p_hwfn->p_dcbx_info->results, &data,
361                     sizeof(struct ecore_dcbx_results));
362
363         return ECORE_SUCCESS;
364 }
365
366 static enum _ecore_status_t
367 ecore_dcbx_copy_mib(struct ecore_hwfn *p_hwfn,
368                     struct ecore_ptt *p_ptt,
369                     struct ecore_dcbx_mib_meta_data *p_data,
370                     enum ecore_mib_read_type type)
371 {
372         u32 prefix_seq_num, suffix_seq_num;
373         int read_count = 0;
374         enum _ecore_status_t rc = ECORE_SUCCESS;
375
376         /* The data is considered to be valid only if both sequence numbers are
377          * the same.
378          */
379         do {
380                 if (type == ECORE_DCBX_REMOTE_LLDP_MIB) {
381                         ecore_memcpy_from(p_hwfn, p_ptt, p_data->lldp_remote,
382                                           p_data->addr, p_data->size);
383                         prefix_seq_num = p_data->lldp_remote->prefix_seq_num;
384                         suffix_seq_num = p_data->lldp_remote->suffix_seq_num;
385                 } else if (type == ECORE_DCBX_LLDP_TLVS) {
386                         ecore_memcpy_from(p_hwfn, p_ptt, p_data->lldp_tlvs,
387                                           p_data->addr, p_data->size);
388                         prefix_seq_num = p_data->lldp_tlvs->prefix_seq_num;
389                         suffix_seq_num = p_data->lldp_tlvs->suffix_seq_num;
390
391                 } else {
392                         ecore_memcpy_from(p_hwfn, p_ptt, p_data->mib,
393                                           p_data->addr, p_data->size);
394                         prefix_seq_num = p_data->mib->prefix_seq_num;
395                         suffix_seq_num = p_data->mib->suffix_seq_num;
396                 }
397                 read_count++;
398
399                 DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
400                            "mib type = %d, try count = %d prefix seq num  ="
401                            " %d suffix seq num = %d\n",
402                            type, read_count, prefix_seq_num, suffix_seq_num);
403         } while ((prefix_seq_num != suffix_seq_num) &&
404                  (read_count < ECORE_DCBX_MAX_MIB_READ_TRY));
405
406         if (read_count >= ECORE_DCBX_MAX_MIB_READ_TRY) {
407                 DP_ERR(p_hwfn,
408                        "MIB read err, mib type = %d, try count ="
409                        " %d prefix seq num = %d suffix seq num = %d\n",
410                        type, read_count, prefix_seq_num, suffix_seq_num);
411                 rc = ECORE_IO;
412         }
413
414         return rc;
415 }
416
417 static void
418 ecore_dcbx_get_priority_info(struct ecore_hwfn *p_hwfn,
419                              struct ecore_dcbx_app_prio *p_prio,
420                              struct ecore_dcbx_results *p_results)
421 {
422         u8 val;
423
424         if (p_results->arr[DCBX_PROTOCOL_ETH].update &&
425             p_results->arr[DCBX_PROTOCOL_ETH].enable)
426                 p_prio->eth = p_results->arr[DCBX_PROTOCOL_ETH].priority;
427
428         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
429                    "Priorities: eth %d\n",
430                    p_prio->eth);
431 }
432
433 static void
434 ecore_dcbx_get_app_data(struct ecore_hwfn *p_hwfn,
435                         struct dcbx_app_priority_feature *p_app,
436                         struct dcbx_app_priority_entry *p_tbl,
437                         struct ecore_dcbx_params *p_params, bool ieee)
438 {
439         struct ecore_app_entry *entry;
440         u8 pri_map;
441         int i;
442
443         p_params->app_willing = GET_MFW_FIELD(p_app->flags, DCBX_APP_WILLING);
444         p_params->app_valid = GET_MFW_FIELD(p_app->flags, DCBX_APP_ENABLED);
445         p_params->app_error = GET_MFW_FIELD(p_app->flags, DCBX_APP_ERROR);
446         p_params->num_app_entries = GET_MFW_FIELD(p_app->flags,
447                                                   DCBX_APP_NUM_ENTRIES);
448         for (i = 0; i < p_params->num_app_entries; i++) {
449                 entry = &p_params->app_entry[i];
450                 if (ieee) {
451                         u8 sf_ieee;
452                         u32 val;
453
454                         sf_ieee = GET_MFW_FIELD(p_tbl[i].entry,
455                                                 DCBX_APP_SF_IEEE);
456                         switch (sf_ieee) {
457                         case DCBX_APP_SF_IEEE_RESERVED:
458                                 /* Old MFW */
459                                 val = GET_MFW_FIELD(p_tbl[i].entry,
460                                                     DCBX_APP_SF);
461                                 entry->sf_ieee = val ?
462                                         ECORE_DCBX_SF_IEEE_TCP_UDP_PORT :
463                                         ECORE_DCBX_SF_IEEE_ETHTYPE;
464                                 break;
465                         case DCBX_APP_SF_IEEE_ETHTYPE:
466                                 entry->sf_ieee = ECORE_DCBX_SF_IEEE_ETHTYPE;
467                                 break;
468                         case DCBX_APP_SF_IEEE_TCP_PORT:
469                                 entry->sf_ieee = ECORE_DCBX_SF_IEEE_TCP_PORT;
470                                 break;
471                         case DCBX_APP_SF_IEEE_UDP_PORT:
472                                 entry->sf_ieee = ECORE_DCBX_SF_IEEE_UDP_PORT;
473                                 break;
474                         case DCBX_APP_SF_IEEE_TCP_UDP_PORT:
475                                 entry->sf_ieee =
476                                                 ECORE_DCBX_SF_IEEE_TCP_UDP_PORT;
477                                 break;
478                         }
479                 } else {
480                         entry->ethtype = !(GET_MFW_FIELD(p_tbl[i].entry,
481                                                          DCBX_APP_SF));
482                 }
483
484                 pri_map = GET_MFW_FIELD(p_tbl[i].entry, DCBX_APP_PRI_MAP);
485                 ecore_dcbx_get_app_priority(pri_map, &entry->prio);
486                 entry->proto_id = GET_MFW_FIELD(p_tbl[i].entry,
487                                                 DCBX_APP_PROTOCOL_ID);
488                 ecore_dcbx_get_app_protocol_type(p_hwfn, p_tbl[i].entry,
489                                                  entry->proto_id,
490                                                  &entry->proto_type, ieee);
491         }
492
493         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
494                    "APP params: willing %d, valid %d error = %d\n",
495                    p_params->app_willing, p_params->app_valid,
496                    p_params->app_error);
497 }
498
499 static void
500 ecore_dcbx_get_pfc_data(struct ecore_hwfn *p_hwfn,
501                         u32 pfc, struct ecore_dcbx_params *p_params)
502 {
503         u8 pfc_map;
504
505         p_params->pfc.willing = GET_MFW_FIELD(pfc, DCBX_PFC_WILLING);
506         p_params->pfc.max_tc = GET_MFW_FIELD(pfc, DCBX_PFC_CAPS);
507         p_params->pfc.enabled = GET_MFW_FIELD(pfc, DCBX_PFC_ENABLED);
508         pfc_map = GET_MFW_FIELD(pfc, DCBX_PFC_PRI_EN_BITMAP);
509         p_params->pfc.prio[0] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_0);
510         p_params->pfc.prio[1] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_1);
511         p_params->pfc.prio[2] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_2);
512         p_params->pfc.prio[3] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_3);
513         p_params->pfc.prio[4] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_4);
514         p_params->pfc.prio[5] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_5);
515         p_params->pfc.prio[6] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_6);
516         p_params->pfc.prio[7] = !!(pfc_map & DCBX_PFC_PRI_EN_BITMAP_PRI_7);
517
518         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
519                    "PFC params: willing %d, pfc_bitmap %u max_tc = %u enabled = %d\n",
520                    p_params->pfc.willing, pfc_map, p_params->pfc.max_tc,
521                    p_params->pfc.enabled);
522 }
523
524 static void
525 ecore_dcbx_get_ets_data(struct ecore_hwfn *p_hwfn,
526                         struct dcbx_ets_feature *p_ets,
527                         struct ecore_dcbx_params *p_params)
528 {
529         u32 bw_map[2], tsa_map[2], pri_map;
530         int i;
531
532         p_params->ets_willing = GET_MFW_FIELD(p_ets->flags, DCBX_ETS_WILLING);
533         p_params->ets_enabled = GET_MFW_FIELD(p_ets->flags, DCBX_ETS_ENABLED);
534         p_params->ets_cbs = GET_MFW_FIELD(p_ets->flags, DCBX_ETS_CBS);
535         p_params->max_ets_tc = GET_MFW_FIELD(p_ets->flags, DCBX_ETS_MAX_TCS);
536         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
537                    "ETS params: willing %d, enabled = %d ets_cbs %d pri_tc_tbl_0 %x max_ets_tc %d\n",
538                    p_params->ets_willing, p_params->ets_enabled,
539                    p_params->ets_cbs, p_ets->pri_tc_tbl[0],
540                    p_params->max_ets_tc);
541
542         /* 8 bit tsa and bw data corresponding to each of the 8 TC's are
543          * encoded in a type u32 array of size 2.
544          */
545         bw_map[0] = OSAL_BE32_TO_CPU(p_ets->tc_bw_tbl[0]);
546         bw_map[1] = OSAL_BE32_TO_CPU(p_ets->tc_bw_tbl[1]);
547         tsa_map[0] = OSAL_BE32_TO_CPU(p_ets->tc_tsa_tbl[0]);
548         tsa_map[1] = OSAL_BE32_TO_CPU(p_ets->tc_tsa_tbl[1]);
549         pri_map = p_ets->pri_tc_tbl[0];
550         for (i = 0; i < ECORE_MAX_PFC_PRIORITIES; i++) {
551                 p_params->ets_tc_bw_tbl[i] = ((u8 *)bw_map)[i];
552                 p_params->ets_tc_tsa_tbl[i] = ((u8 *)tsa_map)[i];
553                 p_params->ets_pri_tc_tbl[i] = ECORE_DCBX_PRIO2TC(pri_map, i);
554                 DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
555                            "elem %d  bw_tbl %x tsa_tbl %x\n",
556                            i, p_params->ets_tc_bw_tbl[i],
557                            p_params->ets_tc_tsa_tbl[i]);
558         }
559 }
560
561 static void
562 ecore_dcbx_get_common_params(struct ecore_hwfn *p_hwfn,
563                              struct dcbx_app_priority_feature *p_app,
564                              struct dcbx_app_priority_entry *p_tbl,
565                              struct dcbx_ets_feature *p_ets,
566                              u32 pfc, struct ecore_dcbx_params *p_params,
567                              bool ieee)
568 {
569         ecore_dcbx_get_app_data(p_hwfn, p_app, p_tbl, p_params, ieee);
570         ecore_dcbx_get_ets_data(p_hwfn, p_ets, p_params);
571         ecore_dcbx_get_pfc_data(p_hwfn, pfc, p_params);
572 }
573
574 static void
575 ecore_dcbx_get_local_params(struct ecore_hwfn *p_hwfn,
576                             struct ecore_dcbx_get *params)
577 {
578         struct dcbx_features *p_feat;
579
580         p_feat = &p_hwfn->p_dcbx_info->local_admin.features;
581         ecore_dcbx_get_common_params(p_hwfn, &p_feat->app,
582                                      p_feat->app.app_pri_tbl, &p_feat->ets,
583                                      p_feat->pfc, &params->local.params, false);
584         params->local.valid = true;
585 }
586
587 static void
588 ecore_dcbx_get_remote_params(struct ecore_hwfn *p_hwfn,
589                              struct ecore_dcbx_get *params)
590 {
591         struct dcbx_features *p_feat;
592
593         p_feat = &p_hwfn->p_dcbx_info->remote.features;
594         ecore_dcbx_get_common_params(p_hwfn, &p_feat->app,
595                                      p_feat->app.app_pri_tbl, &p_feat->ets,
596                                      p_feat->pfc, &params->remote.params,
597                                      false);
598         params->remote.valid = true;
599 }
600
601 static void  ecore_dcbx_get_dscp_params(struct ecore_hwfn *p_hwfn,
602                                         struct ecore_dcbx_get *params)
603 {
604         struct ecore_dcbx_dscp_params *p_dscp;
605         struct dcb_dscp_map *p_dscp_map;
606         int i, j, entry;
607         u32 pri_map;
608
609         p_dscp = &params->dscp;
610         p_dscp_map = &p_hwfn->p_dcbx_info->dscp_map;
611         p_dscp->enabled = GET_MFW_FIELD(p_dscp_map->flags, DCB_DSCP_ENABLE);
612
613         /* MFW encodes 64 dscp entries into 8 element array of u32 entries,
614          * where each entry holds the 4bit priority map for 8 dscp entries.
615          */
616         for (i = 0, entry = 0; i < ECORE_DCBX_DSCP_SIZE / 8; i++) {
617                 pri_map = OSAL_BE32_TO_CPU(p_dscp_map->dscp_pri_map[i]);
618                 DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "elem %d pri_map 0x%x\n",
619                            entry, pri_map);
620                 for (j = 0; j < ECORE_DCBX_DSCP_SIZE / 8; j++, entry++)
621                         p_dscp->dscp_pri_map[entry] = (u32)(pri_map >>
622                                                            (j * 4)) & 0xf;
623         }
624 }
625
626 static void
627 ecore_dcbx_get_operational_params(struct ecore_hwfn *p_hwfn,
628                                   struct ecore_dcbx_get *params)
629 {
630         struct ecore_dcbx_operational_params *p_operational;
631         struct ecore_dcbx_results *p_results;
632         struct dcbx_features *p_feat;
633         bool enabled, err;
634         u32 flags;
635         bool val;
636
637         flags = p_hwfn->p_dcbx_info->operational.flags;
638
639         /* If DCBx version is non zero, then negotiation
640          * was successfuly performed
641          */
642         p_operational = &params->operational;
643         enabled = !!(GET_MFW_FIELD(flags, DCBX_CONFIG_VERSION) !=
644                      DCBX_CONFIG_VERSION_DISABLED);
645         if (!enabled) {
646                 p_operational->enabled = enabled;
647                 p_operational->valid = false;
648                 DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "Dcbx is disabled\n");
649                 return;
650         }
651
652         p_feat = &p_hwfn->p_dcbx_info->operational.features;
653         p_results = &p_hwfn->p_dcbx_info->results;
654
655         val = !!(GET_MFW_FIELD(flags, DCBX_CONFIG_VERSION) ==
656                  DCBX_CONFIG_VERSION_IEEE);
657         p_operational->ieee = val;
658
659         val = !!(GET_MFW_FIELD(flags, DCBX_CONFIG_VERSION) ==
660                  DCBX_CONFIG_VERSION_CEE);
661         p_operational->cee = val;
662
663         val = !!(GET_MFW_FIELD(flags, DCBX_CONFIG_VERSION) ==
664                  DCBX_CONFIG_VERSION_STATIC);
665         p_operational->local = val;
666
667         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
668                    "Version support: ieee %d, cee %d, static %d\n",
669                    p_operational->ieee, p_operational->cee,
670                    p_operational->local);
671
672         ecore_dcbx_get_common_params(p_hwfn, &p_feat->app,
673                                      p_feat->app.app_pri_tbl, &p_feat->ets,
674                                      p_feat->pfc, &params->operational.params,
675                                      p_operational->ieee);
676         ecore_dcbx_get_priority_info(p_hwfn, &p_operational->app_prio,
677                                      p_results);
678         err = GET_MFW_FIELD(p_feat->app.flags, DCBX_APP_ERROR);
679         p_operational->err = err;
680         p_operational->enabled = enabled;
681         p_operational->valid = true;
682 }
683
684 static void ecore_dcbx_get_local_lldp_params(struct ecore_hwfn *p_hwfn,
685                                              struct ecore_dcbx_get *params)
686 {
687         struct lldp_config_params_s *p_local;
688
689         p_local = &p_hwfn->p_dcbx_info->lldp_local[LLDP_NEAREST_BRIDGE];
690
691         OSAL_MEMCPY(params->lldp_local.local_chassis_id,
692                     p_local->local_chassis_id,
693                     sizeof(params->lldp_local.local_chassis_id));
694         OSAL_MEMCPY(params->lldp_local.local_port_id, p_local->local_port_id,
695                     sizeof(params->lldp_local.local_port_id));
696 }
697
698 static void ecore_dcbx_get_remote_lldp_params(struct ecore_hwfn *p_hwfn,
699                                               struct ecore_dcbx_get *params)
700 {
701         struct lldp_status_params_s *p_remote;
702
703         p_remote = &p_hwfn->p_dcbx_info->lldp_remote[LLDP_NEAREST_BRIDGE];
704
705         OSAL_MEMCPY(params->lldp_remote.peer_chassis_id,
706                     p_remote->peer_chassis_id,
707                     sizeof(params->lldp_remote.peer_chassis_id));
708         OSAL_MEMCPY(params->lldp_remote.peer_port_id, p_remote->peer_port_id,
709                     sizeof(params->lldp_remote.peer_port_id));
710 }
711
712 static enum _ecore_status_t
713 ecore_dcbx_get_params(struct ecore_hwfn *p_hwfn,
714                       struct ecore_dcbx_get *p_params,
715                       enum ecore_mib_read_type type)
716 {
717         switch (type) {
718         case ECORE_DCBX_REMOTE_MIB:
719                 ecore_dcbx_get_remote_params(p_hwfn, p_params);
720                 break;
721         case ECORE_DCBX_LOCAL_MIB:
722                 ecore_dcbx_get_local_params(p_hwfn, p_params);
723                 break;
724         case ECORE_DCBX_OPERATIONAL_MIB:
725                 ecore_dcbx_get_operational_params(p_hwfn, p_params);
726                 break;
727         case ECORE_DCBX_REMOTE_LLDP_MIB:
728                 ecore_dcbx_get_remote_lldp_params(p_hwfn, p_params);
729                 break;
730         case ECORE_DCBX_LOCAL_LLDP_MIB:
731                 ecore_dcbx_get_local_lldp_params(p_hwfn, p_params);
732                 break;
733         default:
734                 DP_ERR(p_hwfn, "MIB read err, unknown mib type %d\n", type);
735                 return ECORE_INVAL;
736         }
737
738         return ECORE_SUCCESS;
739 }
740
741 static enum _ecore_status_t
742 ecore_dcbx_read_local_lldp_mib(struct ecore_hwfn *p_hwfn,
743                                struct ecore_ptt *p_ptt)
744 {
745         struct ecore_dcbx_mib_meta_data data;
746         enum _ecore_status_t rc = ECORE_SUCCESS;
747
748         OSAL_MEM_ZERO(&data, sizeof(data));
749         data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port,
750                                                            lldp_config_params);
751         data.lldp_local = p_hwfn->p_dcbx_info->lldp_local;
752         data.size = sizeof(struct lldp_config_params_s);
753         ecore_memcpy_from(p_hwfn, p_ptt, data.lldp_local, data.addr, data.size);
754
755         return rc;
756 }
757
758 static enum _ecore_status_t
759 ecore_dcbx_read_remote_lldp_mib(struct ecore_hwfn *p_hwfn,
760                                 struct ecore_ptt *p_ptt,
761                                 enum ecore_mib_read_type type)
762 {
763         struct ecore_dcbx_mib_meta_data data;
764         enum _ecore_status_t rc = ECORE_SUCCESS;
765
766         OSAL_MEM_ZERO(&data, sizeof(data));
767         data.addr = p_hwfn->mcp_info->port_addr + offsetof(struct public_port,
768                                                            lldp_status_params);
769         data.lldp_remote = p_hwfn->p_dcbx_info->lldp_remote;
770         data.size = sizeof(struct lldp_status_params_s);
771         rc = ecore_dcbx_copy_mib(p_hwfn, p_ptt, &data, type);
772
773         return rc;
774 }
775
776 static enum _ecore_status_t
777 ecore_dcbx_read_operational_mib(struct ecore_hwfn *p_hwfn,
778                                 struct ecore_ptt *p_ptt,
779                                 enum ecore_mib_read_type type)
780 {
781         struct ecore_dcbx_mib_meta_data data;
782         enum _ecore_status_t rc = ECORE_SUCCESS;
783
784         OSAL_MEM_ZERO(&data, sizeof(data));
785         data.addr = p_hwfn->mcp_info->port_addr +
786             offsetof(struct public_port, operational_dcbx_mib);
787         data.mib = &p_hwfn->p_dcbx_info->operational;
788         data.size = sizeof(struct dcbx_mib);
789         rc = ecore_dcbx_copy_mib(p_hwfn, p_ptt, &data, type);
790
791         return rc;
792 }
793
794 static enum _ecore_status_t
795 ecore_dcbx_read_remote_mib(struct ecore_hwfn *p_hwfn,
796                            struct ecore_ptt *p_ptt,
797                            enum ecore_mib_read_type type)
798 {
799         struct ecore_dcbx_mib_meta_data data;
800         enum _ecore_status_t rc = ECORE_SUCCESS;
801
802         OSAL_MEM_ZERO(&data, sizeof(data));
803         data.addr = p_hwfn->mcp_info->port_addr +
804             offsetof(struct public_port, remote_dcbx_mib);
805         data.mib = &p_hwfn->p_dcbx_info->remote;
806         data.size = sizeof(struct dcbx_mib);
807         rc = ecore_dcbx_copy_mib(p_hwfn, p_ptt, &data, type);
808
809         return rc;
810 }
811
812 static enum _ecore_status_t
813 ecore_dcbx_read_local_mib(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
814 {
815         struct ecore_dcbx_mib_meta_data data;
816         enum _ecore_status_t rc = ECORE_SUCCESS;
817
818         OSAL_MEM_ZERO(&data, sizeof(data));
819         data.addr = p_hwfn->mcp_info->port_addr +
820             offsetof(struct public_port, local_admin_dcbx_mib);
821         data.local_admin = &p_hwfn->p_dcbx_info->local_admin;
822         data.size = sizeof(struct dcbx_local_params);
823         ecore_memcpy_from(p_hwfn, p_ptt, data.local_admin,
824                           data.addr, data.size);
825
826         return rc;
827 }
828
829 static void
830 ecore_dcbx_read_dscp_mib(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
831 {
832         struct ecore_dcbx_mib_meta_data data;
833
834         data.addr = p_hwfn->mcp_info->port_addr +
835                         offsetof(struct public_port, dcb_dscp_map);
836         data.dscp_map = &p_hwfn->p_dcbx_info->dscp_map;
837         data.size = sizeof(struct dcb_dscp_map);
838         ecore_memcpy_from(p_hwfn, p_ptt, data.dscp_map, data.addr, data.size);
839 }
840
841 static enum _ecore_status_t ecore_dcbx_read_mib(struct ecore_hwfn *p_hwfn,
842                                                 struct ecore_ptt *p_ptt,
843                                                 enum ecore_mib_read_type type)
844 {
845         enum _ecore_status_t rc = ECORE_INVAL;
846
847         switch (type) {
848         case ECORE_DCBX_OPERATIONAL_MIB:
849                 ecore_dcbx_read_dscp_mib(p_hwfn, p_ptt);
850                 rc = ecore_dcbx_read_operational_mib(p_hwfn, p_ptt, type);
851                 break;
852         case ECORE_DCBX_REMOTE_MIB:
853                 rc = ecore_dcbx_read_remote_mib(p_hwfn, p_ptt, type);
854                 break;
855         case ECORE_DCBX_LOCAL_MIB:
856                 rc = ecore_dcbx_read_local_mib(p_hwfn, p_ptt);
857                 break;
858         case ECORE_DCBX_REMOTE_LLDP_MIB:
859                 rc = ecore_dcbx_read_remote_lldp_mib(p_hwfn, p_ptt, type);
860                 break;
861         case ECORE_DCBX_LOCAL_LLDP_MIB:
862                 rc = ecore_dcbx_read_local_lldp_mib(p_hwfn, p_ptt);
863                 break;
864         default:
865                 DP_ERR(p_hwfn, "MIB read err, unknown mib type %d\n", type);
866         }
867
868         return ECORE_SUCCESS;
869 }
870
871 /*
872  * Read updated MIB.
873  * Reconfigure QM and invoke PF update ramrod command if operational MIB
874  * change is detected.
875  */
876 enum _ecore_status_t
877 ecore_dcbx_mib_update_event(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
878                             enum ecore_mib_read_type type)
879 {
880         enum _ecore_status_t rc = ECORE_SUCCESS;
881
882         rc = ecore_dcbx_read_mib(p_hwfn, p_ptt, type);
883         if (rc)
884                 return rc;
885
886         if (type == ECORE_DCBX_OPERATIONAL_MIB) {
887                 ecore_dcbx_get_dscp_params(p_hwfn, &p_hwfn->p_dcbx_info->get);
888
889                 rc = ecore_dcbx_process_mib_info(p_hwfn, p_ptt);
890                 if (!rc) {
891                         /* reconfigure tcs of QM queues according
892                          * to negotiation results
893                          */
894                         ecore_qm_reconf(p_hwfn, p_ptt);
895
896                         /* update storm FW with negotiation results */
897                         ecore_sp_pf_update_dcbx(p_hwfn);
898                 }
899         }
900
901         ecore_dcbx_get_params(p_hwfn, &p_hwfn->p_dcbx_info->get, type);
902
903         /* Update the DSCP to TC mapping enable bit if required */
904         if ((type == ECORE_DCBX_OPERATIONAL_MIB) &&
905             p_hwfn->p_dcbx_info->dscp_nig_update) {
906                 u8 val = !!p_hwfn->p_dcbx_info->get.dscp.enabled;
907                 u32 addr = NIG_REG_DSCP_TO_TC_MAP_ENABLE;
908
909                 rc = ecore_all_ppfids_wr(p_hwfn, p_ptt, addr, val);
910                 if (rc != ECORE_SUCCESS) {
911                         DP_NOTICE(p_hwfn, false,
912                                   "Failed to update the DSCP to TC mapping enable bit\n");
913                         return rc;
914                 }
915
916                 p_hwfn->p_dcbx_info->dscp_nig_update = false;
917         }
918
919         OSAL_DCBX_AEN(p_hwfn, type);
920
921         return rc;
922 }
923
924 enum _ecore_status_t ecore_dcbx_info_alloc(struct ecore_hwfn *p_hwfn)
925 {
926         p_hwfn->p_dcbx_info = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL,
927                                           sizeof(*p_hwfn->p_dcbx_info));
928         if (!p_hwfn->p_dcbx_info) {
929                 DP_NOTICE(p_hwfn, false,
930                           "Failed to allocate `struct ecore_dcbx_info'");
931                 return ECORE_NOMEM;
932         }
933
934         p_hwfn->p_dcbx_info->iwarp_port =
935                 p_hwfn->pf_params.rdma_pf_params.iwarp_port;
936
937         return ECORE_SUCCESS;
938 }
939
940 void ecore_dcbx_info_free(struct ecore_hwfn *p_hwfn)
941 {
942         OSAL_FREE(p_hwfn->p_dev, p_hwfn->p_dcbx_info);
943 }
944
945 static void ecore_dcbx_update_protocol_data(struct protocol_dcb_data *p_data,
946                                             struct ecore_dcbx_results *p_src,
947                                             enum dcbx_protocol_type type)
948 {
949         p_data->dcb_enable_flag = p_src->arr[type].enable;
950         p_data->dcb_priority = p_src->arr[type].priority;
951         p_data->dcb_tc = p_src->arr[type].tc;
952         p_data->dscp_enable_flag = p_src->arr[type].dscp_enable;
953         p_data->dscp_val = p_src->arr[type].dscp_val;
954         p_data->dcb_dont_add_vlan0 = p_src->arr[type].dont_add_vlan0;
955 }
956
957 /* Set pf update ramrod command params */
958 void ecore_dcbx_set_pf_update_params(struct ecore_dcbx_results *p_src,
959                                      struct pf_update_ramrod_data *p_dest)
960 {
961         struct protocol_dcb_data *p_dcb_data;
962         u8 update_flag;
963
964         update_flag = p_src->arr[DCBX_PROTOCOL_ETH].update;
965         p_dest->update_eth_dcb_data_mode = update_flag;
966         update_flag = p_src->arr[DCBX_PROTOCOL_IWARP].update;
967         p_dest->update_iwarp_dcb_data_mode = update_flag;
968
969         p_dcb_data = &p_dest->eth_dcb_data;
970         ecore_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_ETH);
971         p_dcb_data = &p_dest->iwarp_dcb_data;
972         ecore_dcbx_update_protocol_data(p_dcb_data, p_src, DCBX_PROTOCOL_IWARP);
973 }
974
975 enum _ecore_status_t ecore_dcbx_query_params(struct ecore_hwfn *p_hwfn,
976                                              struct ecore_dcbx_get *p_get,
977                                              enum ecore_mib_read_type type)
978 {
979         struct ecore_ptt *p_ptt;
980         enum _ecore_status_t rc;
981
982         if (IS_VF(p_hwfn->p_dev))
983                 return ECORE_INVAL;
984
985         p_ptt = ecore_ptt_acquire(p_hwfn);
986         if (!p_ptt)
987                 return ECORE_TIMEOUT;
988
989         rc = ecore_dcbx_read_mib(p_hwfn, p_ptt, type);
990         if (rc != ECORE_SUCCESS)
991                 goto out;
992
993         ecore_dcbx_get_dscp_params(p_hwfn, p_get);
994
995         rc = ecore_dcbx_get_params(p_hwfn, p_get, type);
996
997 out:
998         ecore_ptt_release(p_hwfn, p_ptt);
999         return rc;
1000 }
1001
1002 static void
1003 ecore_dcbx_set_pfc_data(struct ecore_hwfn *p_hwfn,
1004                         u32 *pfc, struct ecore_dcbx_params *p_params)
1005 {
1006         u8 pfc_map = 0;
1007         int i;
1008
1009         if (p_params->pfc.willing)
1010                 *pfc |= DCBX_PFC_WILLING_MASK;
1011         else
1012                 *pfc &= ~DCBX_PFC_WILLING_MASK;
1013
1014         if (p_params->pfc.enabled)
1015                 *pfc |= DCBX_PFC_ENABLED_MASK;
1016         else
1017                 *pfc &= ~DCBX_PFC_ENABLED_MASK;
1018
1019         *pfc &= ~DCBX_PFC_CAPS_MASK;
1020         *pfc |= (u32)p_params->pfc.max_tc << DCBX_PFC_CAPS_OFFSET;
1021
1022         for (i = 0; i < ECORE_MAX_PFC_PRIORITIES; i++)
1023                 if (p_params->pfc.prio[i])
1024                         pfc_map |= (1 << i);
1025         *pfc &= ~DCBX_PFC_PRI_EN_BITMAP_MASK;
1026         *pfc |= (pfc_map << DCBX_PFC_PRI_EN_BITMAP_OFFSET);
1027
1028         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "pfc = 0x%x\n", *pfc);
1029 }
1030
1031 static void
1032 ecore_dcbx_set_ets_data(struct ecore_hwfn *p_hwfn,
1033                         struct dcbx_ets_feature *p_ets,
1034                         struct ecore_dcbx_params *p_params)
1035 {
1036         u8 *bw_map, *tsa_map;
1037         u32 val;
1038         int i;
1039
1040         if (p_params->ets_willing)
1041                 p_ets->flags |= DCBX_ETS_WILLING_MASK;
1042         else
1043                 p_ets->flags &= ~DCBX_ETS_WILLING_MASK;
1044
1045         if (p_params->ets_cbs)
1046                 p_ets->flags |= DCBX_ETS_CBS_MASK;
1047         else
1048                 p_ets->flags &= ~DCBX_ETS_CBS_MASK;
1049
1050         if (p_params->ets_enabled)
1051                 p_ets->flags |= DCBX_ETS_ENABLED_MASK;
1052         else
1053                 p_ets->flags &= ~DCBX_ETS_ENABLED_MASK;
1054
1055         p_ets->flags &= ~DCBX_ETS_MAX_TCS_MASK;
1056         p_ets->flags |= (u32)p_params->max_ets_tc << DCBX_ETS_MAX_TCS_OFFSET;
1057
1058         bw_map = (u8 *)&p_ets->tc_bw_tbl[0];
1059         tsa_map = (u8 *)&p_ets->tc_tsa_tbl[0];
1060         p_ets->pri_tc_tbl[0] = 0;
1061         for (i = 0; i < ECORE_MAX_PFC_PRIORITIES; i++) {
1062                 bw_map[i] = p_params->ets_tc_bw_tbl[i];
1063                 tsa_map[i] = p_params->ets_tc_tsa_tbl[i];
1064                 /* Copy the priority value to the corresponding 4 bits in the
1065                  * traffic class table.
1066                  */
1067                 val = (((u32)p_params->ets_pri_tc_tbl[i]) << ((7 - i) * 4));
1068                 p_ets->pri_tc_tbl[0] |= val;
1069         }
1070         for (i = 0; i < 2; i++) {
1071                 p_ets->tc_bw_tbl[i] = OSAL_CPU_TO_BE32(p_ets->tc_bw_tbl[i]);
1072                 p_ets->tc_tsa_tbl[i] = OSAL_CPU_TO_BE32(p_ets->tc_tsa_tbl[i]);
1073         }
1074
1075         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
1076                    "flags = 0x%x pri_tc = 0x%x tc_bwl[] = {0x%x, 0x%x} tc_tsa = {0x%x, 0x%x}\n",
1077                    p_ets->flags, p_ets->pri_tc_tbl[0], p_ets->tc_bw_tbl[0],
1078                    p_ets->tc_bw_tbl[1], p_ets->tc_tsa_tbl[0],
1079                    p_ets->tc_tsa_tbl[1]);
1080 }
1081
1082 static void
1083 ecore_dcbx_set_app_data(struct ecore_hwfn *p_hwfn,
1084                         struct dcbx_app_priority_feature *p_app,
1085                         struct ecore_dcbx_params *p_params, bool ieee)
1086 {
1087         u32 *entry;
1088         int i;
1089
1090         if (p_params->app_willing)
1091                 p_app->flags |= DCBX_APP_WILLING_MASK;
1092         else
1093                 p_app->flags &= ~DCBX_APP_WILLING_MASK;
1094
1095         if (p_params->app_valid)
1096                 p_app->flags |= DCBX_APP_ENABLED_MASK;
1097         else
1098                 p_app->flags &= ~DCBX_APP_ENABLED_MASK;
1099
1100         p_app->flags &= ~DCBX_APP_NUM_ENTRIES_MASK;
1101         p_app->flags |= (u32)p_params->num_app_entries <<
1102                         DCBX_APP_NUM_ENTRIES_OFFSET;
1103
1104         for (i = 0; i < p_params->num_app_entries; i++) {
1105                 entry = &p_app->app_pri_tbl[i].entry;
1106                 *entry = 0;
1107                 if (ieee) {
1108                         *entry &= ~(DCBX_APP_SF_IEEE_MASK | DCBX_APP_SF_MASK);
1109                         switch (p_params->app_entry[i].sf_ieee) {
1110                         case ECORE_DCBX_SF_IEEE_ETHTYPE:
1111                                 *entry  |= ((u32)DCBX_APP_SF_IEEE_ETHTYPE <<
1112                                             DCBX_APP_SF_IEEE_OFFSET);
1113                                 *entry  |= ((u32)DCBX_APP_SF_ETHTYPE <<
1114                                             DCBX_APP_SF_OFFSET);
1115                                 break;
1116                         case ECORE_DCBX_SF_IEEE_TCP_PORT:
1117                                 *entry  |= ((u32)DCBX_APP_SF_IEEE_TCP_PORT <<
1118                                             DCBX_APP_SF_IEEE_OFFSET);
1119                                 *entry  |= ((u32)DCBX_APP_SF_PORT <<
1120                                             DCBX_APP_SF_OFFSET);
1121                                 break;
1122                         case ECORE_DCBX_SF_IEEE_UDP_PORT:
1123                                 *entry  |= ((u32)DCBX_APP_SF_IEEE_UDP_PORT <<
1124                                             DCBX_APP_SF_IEEE_OFFSET);
1125                                 *entry  |= ((u32)DCBX_APP_SF_PORT <<
1126                                             DCBX_APP_SF_OFFSET);
1127                                 break;
1128                         case ECORE_DCBX_SF_IEEE_TCP_UDP_PORT:
1129                                 *entry  |= (u32)DCBX_APP_SF_IEEE_TCP_UDP_PORT <<
1130                                             DCBX_APP_SF_IEEE_OFFSET;
1131                                 *entry  |= ((u32)DCBX_APP_SF_PORT <<
1132                                             DCBX_APP_SF_OFFSET);
1133                                 break;
1134                         }
1135                 } else {
1136                         *entry &= ~DCBX_APP_SF_MASK;
1137                         if (p_params->app_entry[i].ethtype)
1138                                 *entry  |= ((u32)DCBX_APP_SF_ETHTYPE <<
1139                                             DCBX_APP_SF_OFFSET);
1140                         else
1141                                 *entry  |= ((u32)DCBX_APP_SF_PORT <<
1142                                             DCBX_APP_SF_OFFSET);
1143                 }
1144                 *entry &= ~DCBX_APP_PROTOCOL_ID_MASK;
1145                 *entry |= ((u32)p_params->app_entry[i].proto_id <<
1146                            DCBX_APP_PROTOCOL_ID_OFFSET);
1147                 *entry &= ~DCBX_APP_PRI_MAP_MASK;
1148                 *entry |= ((u32)(p_params->app_entry[i].prio) <<
1149                            DCBX_APP_PRI_MAP_OFFSET);
1150         }
1151
1152         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "flags = 0x%x\n", p_app->flags);
1153 }
1154
1155 static void
1156 ecore_dcbx_set_local_params(struct ecore_hwfn *p_hwfn,
1157                             struct dcbx_local_params *local_admin,
1158                             struct ecore_dcbx_set *params)
1159 {
1160         bool ieee = false;
1161
1162         local_admin->flags = 0;
1163         OSAL_MEMCPY(&local_admin->features,
1164                     &p_hwfn->p_dcbx_info->operational.features,
1165                     sizeof(local_admin->features));
1166
1167         if (params->enabled) {
1168                 local_admin->config = params->ver_num;
1169                 ieee = !!(params->ver_num & DCBX_CONFIG_VERSION_IEEE);
1170         } else {
1171                 local_admin->config = DCBX_CONFIG_VERSION_DISABLED;
1172         }
1173
1174         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "Dcbx version = %d\n",
1175                    local_admin->config);
1176
1177         if (params->override_flags & ECORE_DCBX_OVERRIDE_PFC_CFG)
1178                 ecore_dcbx_set_pfc_data(p_hwfn, &local_admin->features.pfc,
1179                                         &params->config.params);
1180
1181         if (params->override_flags & ECORE_DCBX_OVERRIDE_ETS_CFG)
1182                 ecore_dcbx_set_ets_data(p_hwfn, &local_admin->features.ets,
1183                                         &params->config.params);
1184
1185         if (params->override_flags & ECORE_DCBX_OVERRIDE_APP_CFG)
1186                 ecore_dcbx_set_app_data(p_hwfn, &local_admin->features.app,
1187                                         &params->config.params, ieee);
1188 }
1189
1190 static enum _ecore_status_t
1191 ecore_dcbx_set_dscp_params(struct ecore_hwfn *p_hwfn,
1192                            struct dcb_dscp_map *p_dscp_map,
1193                            struct ecore_dcbx_set *p_params)
1194 {
1195         int entry, i, j;
1196         u32 val;
1197
1198         OSAL_MEMCPY(p_dscp_map, &p_hwfn->p_dcbx_info->dscp_map,
1199                     sizeof(*p_dscp_map));
1200
1201         p_dscp_map->flags &= ~DCB_DSCP_ENABLE_MASK;
1202         if (p_params->dscp.enabled)
1203                 p_dscp_map->flags |= DCB_DSCP_ENABLE_MASK;
1204
1205         for (i = 0, entry = 0; i < 8; i++) {
1206                 val = 0;
1207                 for (j = 0; j < 8; j++, entry++)
1208                         val |= (((u32)p_params->dscp.dscp_pri_map[entry]) <<
1209                                 (j * 4));
1210
1211                 p_dscp_map->dscp_pri_map[i] = OSAL_CPU_TO_BE32(val);
1212         }
1213
1214         p_hwfn->p_dcbx_info->dscp_nig_update = true;
1215
1216         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB, "flags = 0x%x\n", p_dscp_map->flags);
1217         DP_VERBOSE(p_hwfn, ECORE_MSG_DCB,
1218                    "pri_map[] = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
1219                    p_dscp_map->dscp_pri_map[0], p_dscp_map->dscp_pri_map[1],
1220                    p_dscp_map->dscp_pri_map[2], p_dscp_map->dscp_pri_map[3],
1221                    p_dscp_map->dscp_pri_map[4], p_dscp_map->dscp_pri_map[5],
1222                    p_dscp_map->dscp_pri_map[6], p_dscp_map->dscp_pri_map[7]);
1223
1224         return ECORE_SUCCESS;
1225 }
1226
1227 enum _ecore_status_t ecore_dcbx_config_params(struct ecore_hwfn *p_hwfn,
1228                                               struct ecore_ptt *p_ptt,
1229                                               struct ecore_dcbx_set *params,
1230                                               bool hw_commit)
1231 {
1232         struct dcbx_local_params local_admin;
1233         struct ecore_dcbx_mib_meta_data data;
1234         struct dcb_dscp_map dscp_map;
1235         u32 resp = 0, param = 0;
1236         enum _ecore_status_t rc = ECORE_SUCCESS;
1237
1238         OSAL_MEMCPY(&p_hwfn->p_dcbx_info->set, params,
1239                     sizeof(p_hwfn->p_dcbx_info->set));
1240         if (!hw_commit)
1241                 return ECORE_SUCCESS;
1242
1243         OSAL_MEMSET(&local_admin, 0, sizeof(local_admin));
1244         ecore_dcbx_set_local_params(p_hwfn, &local_admin, params);
1245
1246         data.addr = p_hwfn->mcp_info->port_addr +
1247                         offsetof(struct public_port, local_admin_dcbx_mib);
1248         data.local_admin = &local_admin;
1249         data.size = sizeof(struct dcbx_local_params);
1250         ecore_memcpy_to(p_hwfn, p_ptt, data.addr, data.local_admin, data.size);
1251
1252         if (params->override_flags & ECORE_DCBX_OVERRIDE_DSCP_CFG) {
1253                 OSAL_MEMSET(&dscp_map, 0, sizeof(dscp_map));
1254                 ecore_dcbx_set_dscp_params(p_hwfn, &dscp_map, params);
1255
1256                 data.addr = p_hwfn->mcp_info->port_addr +
1257                                 offsetof(struct public_port, dcb_dscp_map);
1258                 data.dscp_map = &dscp_map;
1259                 data.size = sizeof(struct dcb_dscp_map);
1260                 ecore_memcpy_to(p_hwfn, p_ptt, data.addr, data.dscp_map,
1261                                 data.size);
1262         }
1263
1264         rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_DCBX,
1265                            1 << DRV_MB_PARAM_LLDP_SEND_OFFSET, &resp, &param);
1266         if (rc != ECORE_SUCCESS)
1267                 DP_NOTICE(p_hwfn, false,
1268                           "Failed to send DCBX update request\n");
1269
1270         return rc;
1271 }
1272
1273 enum _ecore_status_t ecore_dcbx_get_config_params(struct ecore_hwfn *p_hwfn,
1274                                                   struct ecore_dcbx_set *params)
1275 {
1276         struct ecore_dcbx_get *dcbx_info;
1277         int rc;
1278
1279         if (p_hwfn->p_dcbx_info->set.config.valid) {
1280                 OSAL_MEMCPY(params, &p_hwfn->p_dcbx_info->set,
1281                             sizeof(struct ecore_dcbx_set));
1282                 return ECORE_SUCCESS;
1283         }
1284
1285         dcbx_info = OSAL_ALLOC(p_hwfn->p_dev, GFP_KERNEL,
1286                                sizeof(*dcbx_info));
1287         if (!dcbx_info)
1288                 return ECORE_NOMEM;
1289
1290         OSAL_MEMSET(dcbx_info, 0, sizeof(*dcbx_info));
1291         rc = ecore_dcbx_query_params(p_hwfn, dcbx_info,
1292                                      ECORE_DCBX_OPERATIONAL_MIB);
1293         if (rc) {
1294                 OSAL_FREE(p_hwfn->p_dev, dcbx_info);
1295                 return rc;
1296         }
1297         p_hwfn->p_dcbx_info->set.override_flags = 0;
1298
1299         p_hwfn->p_dcbx_info->set.ver_num = DCBX_CONFIG_VERSION_DISABLED;
1300         if (dcbx_info->operational.cee)
1301                 p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_CEE;
1302         if (dcbx_info->operational.ieee)
1303                 p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_IEEE;
1304         if (dcbx_info->operational.local)
1305                 p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_STATIC;
1306
1307         p_hwfn->p_dcbx_info->set.enabled = dcbx_info->operational.enabled;
1308         OSAL_MEMCPY(&p_hwfn->p_dcbx_info->set.dscp,
1309                     &p_hwfn->p_dcbx_info->get.dscp,
1310                     sizeof(struct ecore_dcbx_dscp_params));
1311         OSAL_MEMCPY(&p_hwfn->p_dcbx_info->set.config.params,
1312                     &dcbx_info->operational.params,
1313                     sizeof(p_hwfn->p_dcbx_info->set.config.params));
1314         p_hwfn->p_dcbx_info->set.config.valid = true;
1315
1316         OSAL_MEMCPY(params, &p_hwfn->p_dcbx_info->set,
1317                     sizeof(struct ecore_dcbx_set));
1318
1319         OSAL_FREE(p_hwfn->p_dev, dcbx_info);
1320
1321         return ECORE_SUCCESS;
1322 }
1323
1324 enum _ecore_status_t ecore_lldp_register_tlv(struct ecore_hwfn *p_hwfn,
1325                                              struct ecore_ptt *p_ptt,
1326                                              enum ecore_lldp_agent agent,
1327                                              u8 tlv_type)
1328 {
1329         u32 mb_param = 0, mcp_resp = 0, mcp_param = 0, val = 0;
1330         enum _ecore_status_t rc = ECORE_SUCCESS;
1331
1332         switch (agent) {
1333         case ECORE_LLDP_NEAREST_BRIDGE:
1334                 val = LLDP_NEAREST_BRIDGE;
1335                 break;
1336         case ECORE_LLDP_NEAREST_NON_TPMR_BRIDGE:
1337                 val = LLDP_NEAREST_NON_TPMR_BRIDGE;
1338                 break;
1339         case ECORE_LLDP_NEAREST_CUSTOMER_BRIDGE:
1340                 val = LLDP_NEAREST_CUSTOMER_BRIDGE;
1341                 break;
1342         default:
1343                 DP_ERR(p_hwfn, "Invalid agent type %d\n", agent);
1344                 return ECORE_INVAL;
1345         }
1346
1347         SET_MFW_FIELD(mb_param, DRV_MB_PARAM_LLDP_AGENT, val);
1348         SET_MFW_FIELD(mb_param, DRV_MB_PARAM_LLDP_TLV_RX_TYPE, tlv_type);
1349
1350         rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_REGISTER_LLDP_TLVS_RX,
1351                            mb_param, &mcp_resp, &mcp_param);
1352         if (rc != ECORE_SUCCESS)
1353                 DP_NOTICE(p_hwfn, false, "Failed to register TLV\n");
1354
1355         return rc;
1356 }
1357
1358 enum _ecore_status_t
1359 ecore_lldp_mib_update_event(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
1360 {
1361         struct ecore_dcbx_mib_meta_data data;
1362         enum _ecore_status_t rc = ECORE_SUCCESS;
1363         struct lldp_received_tlvs_s tlvs;
1364         int i;
1365
1366         for (i = 0; i < LLDP_MAX_LLDP_AGENTS; i++) {
1367                 OSAL_MEM_ZERO(&data, sizeof(data));
1368                 data.addr = p_hwfn->mcp_info->port_addr +
1369                             offsetof(struct public_port, lldp_received_tlvs[i]);
1370                 data.lldp_tlvs = &tlvs;
1371                 data.size = sizeof(tlvs);
1372                 rc = ecore_dcbx_copy_mib(p_hwfn, p_ptt, &data,
1373                                          ECORE_DCBX_LLDP_TLVS);
1374                 if (rc != ECORE_SUCCESS) {
1375                         DP_NOTICE(p_hwfn, false, "Failed to read lldp TLVs\n");
1376                         return rc;
1377                 }
1378
1379                 if (!tlvs.length)
1380                         continue;
1381
1382                 for (i = 0; i < MAX_TLV_BUFFER; i++)
1383                         tlvs.tlvs_buffer[i] =
1384                                 OSAL_CPU_TO_BE32(tlvs.tlvs_buffer[i]);
1385
1386                 OSAL_LLDP_RX_TLVS(p_hwfn, tlvs.tlvs_buffer, tlvs.length);
1387         }
1388
1389         return rc;
1390 }
1391
1392 enum _ecore_status_t
1393 ecore_lldp_get_params(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
1394                       struct ecore_lldp_config_params *p_params)
1395 {
1396         struct lldp_config_params_s lldp_params;
1397         u32 addr, val;
1398         int i;
1399
1400         switch (p_params->agent) {
1401         case ECORE_LLDP_NEAREST_BRIDGE:
1402                 val = LLDP_NEAREST_BRIDGE;
1403                 break;
1404         case ECORE_LLDP_NEAREST_NON_TPMR_BRIDGE:
1405                 val = LLDP_NEAREST_NON_TPMR_BRIDGE;
1406                 break;
1407         case ECORE_LLDP_NEAREST_CUSTOMER_BRIDGE:
1408                 val = LLDP_NEAREST_CUSTOMER_BRIDGE;
1409                 break;
1410         default:
1411                 DP_ERR(p_hwfn, "Invalid agent type %d\n", p_params->agent);
1412                 return ECORE_INVAL;
1413         }
1414
1415         addr = p_hwfn->mcp_info->port_addr +
1416                         offsetof(struct public_port, lldp_config_params[val]);
1417
1418         ecore_memcpy_from(p_hwfn, p_ptt, &lldp_params, addr,
1419                           sizeof(lldp_params));
1420
1421         p_params->tx_interval = GET_MFW_FIELD(lldp_params.config,
1422                                               LLDP_CONFIG_TX_INTERVAL);
1423         p_params->tx_hold = GET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_HOLD);
1424         p_params->tx_credit = GET_MFW_FIELD(lldp_params.config,
1425                                             LLDP_CONFIG_MAX_CREDIT);
1426         p_params->rx_enable = GET_MFW_FIELD(lldp_params.config,
1427                                             LLDP_CONFIG_ENABLE_RX);
1428         p_params->tx_enable = GET_MFW_FIELD(lldp_params.config,
1429                                             LLDP_CONFIG_ENABLE_TX);
1430
1431         OSAL_MEMCPY(p_params->chassis_id_tlv, lldp_params.local_chassis_id,
1432                     sizeof(p_params->chassis_id_tlv));
1433         for (i = 0; i < ECORE_LLDP_CHASSIS_ID_STAT_LEN; i++)
1434                 p_params->chassis_id_tlv[i] =
1435                                 OSAL_BE32_TO_CPU(p_params->chassis_id_tlv[i]);
1436
1437         OSAL_MEMCPY(p_params->port_id_tlv, lldp_params.local_port_id,
1438                     sizeof(p_params->port_id_tlv));
1439         for (i = 0; i < ECORE_LLDP_PORT_ID_STAT_LEN; i++)
1440                 p_params->port_id_tlv[i] =
1441                                 OSAL_BE32_TO_CPU(p_params->port_id_tlv[i]);
1442
1443         return ECORE_SUCCESS;
1444 }
1445
1446 enum _ecore_status_t
1447 ecore_lldp_set_params(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
1448                       struct ecore_lldp_config_params *p_params)
1449 {
1450         u32 mb_param = 0, mcp_resp = 0, mcp_param = 0;
1451         struct lldp_config_params_s lldp_params;
1452         enum _ecore_status_t rc = ECORE_SUCCESS;
1453         u32 addr, val;
1454         int i;
1455
1456         switch (p_params->agent) {
1457         case ECORE_LLDP_NEAREST_BRIDGE:
1458                 val = LLDP_NEAREST_BRIDGE;
1459                 break;
1460         case ECORE_LLDP_NEAREST_NON_TPMR_BRIDGE:
1461                 val = LLDP_NEAREST_NON_TPMR_BRIDGE;
1462                 break;
1463         case ECORE_LLDP_NEAREST_CUSTOMER_BRIDGE:
1464                 val = LLDP_NEAREST_CUSTOMER_BRIDGE;
1465                 break;
1466         default:
1467                 DP_ERR(p_hwfn, "Invalid agent type %d\n", p_params->agent);
1468                 return ECORE_INVAL;
1469         }
1470
1471         SET_MFW_FIELD(mb_param, DRV_MB_PARAM_LLDP_AGENT, val);
1472         addr = p_hwfn->mcp_info->port_addr +
1473                         offsetof(struct public_port, lldp_config_params[val]);
1474
1475         OSAL_MEMSET(&lldp_params, 0, sizeof(lldp_params));
1476         SET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_TX_INTERVAL,
1477                       p_params->tx_interval);
1478         SET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_HOLD, p_params->tx_hold);
1479         SET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_MAX_CREDIT,
1480                       p_params->tx_credit);
1481         SET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_ENABLE_RX,
1482                       !!p_params->rx_enable);
1483         SET_MFW_FIELD(lldp_params.config, LLDP_CONFIG_ENABLE_TX,
1484                       !!p_params->tx_enable);
1485
1486         for (i = 0; i < ECORE_LLDP_CHASSIS_ID_STAT_LEN; i++)
1487                 p_params->chassis_id_tlv[i] =
1488                                 OSAL_CPU_TO_BE32(p_params->chassis_id_tlv[i]);
1489         OSAL_MEMCPY(lldp_params.local_chassis_id, p_params->chassis_id_tlv,
1490                     sizeof(lldp_params.local_chassis_id));
1491
1492         for (i = 0; i < ECORE_LLDP_PORT_ID_STAT_LEN; i++)
1493                 p_params->port_id_tlv[i] =
1494                                 OSAL_CPU_TO_BE32(p_params->port_id_tlv[i]);
1495         OSAL_MEMCPY(lldp_params.local_port_id, p_params->port_id_tlv,
1496                     sizeof(lldp_params.local_port_id));
1497
1498         ecore_memcpy_to(p_hwfn, p_ptt, addr, &lldp_params, sizeof(lldp_params));
1499
1500         rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_LLDP,
1501                            mb_param, &mcp_resp, &mcp_param);
1502         if (rc != ECORE_SUCCESS)
1503                 DP_NOTICE(p_hwfn, false, "SET_LLDP failed, error = %d\n", rc);
1504
1505         return rc;
1506 }
1507
1508 enum _ecore_status_t
1509 ecore_lldp_set_system_tlvs(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
1510                            struct ecore_lldp_sys_tlvs *p_params)
1511 {
1512         u32 mb_param = 0, mcp_resp = 0, mcp_param = 0;
1513         enum _ecore_status_t rc = ECORE_SUCCESS;
1514         struct lldp_system_tlvs_buffer_s lld_tlv_buf;
1515         u32 addr, *p_val;
1516         u8 len;
1517         int i;
1518
1519         p_val = (u32 *)p_params->buf;
1520         for (i = 0; i < ECORE_LLDP_SYS_TLV_SIZE / 4; i++)
1521                 p_val[i] = OSAL_CPU_TO_BE32(p_val[i]);
1522
1523         OSAL_MEMSET(&lld_tlv_buf, 0, sizeof(lld_tlv_buf));
1524         SET_MFW_FIELD(lld_tlv_buf.flags, LLDP_SYSTEM_TLV_VALID, 1);
1525         SET_MFW_FIELD(lld_tlv_buf.flags, LLDP_SYSTEM_TLV_MANDATORY,
1526                       !!p_params->discard_mandatory_tlv);
1527         SET_MFW_FIELD(lld_tlv_buf.flags, LLDP_SYSTEM_TLV_LENGTH,
1528                       p_params->buf_size);
1529         len = ECORE_LLDP_SYS_TLV_SIZE / 2;
1530         OSAL_MEMCPY(lld_tlv_buf.data, p_params->buf, len);
1531
1532         addr = p_hwfn->mcp_info->port_addr +
1533                 offsetof(struct public_port, system_lldp_tlvs_buf);
1534         ecore_memcpy_to(p_hwfn, p_ptt, addr, &lld_tlv_buf, sizeof(lld_tlv_buf));
1535
1536         if  (p_params->buf_size > len) {
1537                 addr = p_hwfn->mcp_info->port_addr +
1538                         offsetof(struct public_port, system_lldp_tlvs_buf2);
1539                 ecore_memcpy_to(p_hwfn, p_ptt, addr, &p_params->buf[len],
1540                                 ECORE_LLDP_SYS_TLV_SIZE / 2);
1541         }
1542
1543         rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_SET_LLDP,
1544                            mb_param, &mcp_resp, &mcp_param);
1545         if (rc != ECORE_SUCCESS)
1546                 DP_NOTICE(p_hwfn, false, "SET_LLDP failed, error = %d\n", rc);
1547
1548         return rc;
1549 }
1550
1551 enum _ecore_status_t
1552 ecore_dcbx_get_dscp_priority(struct ecore_hwfn *p_hwfn,
1553                              u8 dscp_index, u8 *p_dscp_pri)
1554 {
1555         struct ecore_dcbx_get *p_dcbx_info;
1556         enum _ecore_status_t rc;
1557
1558         if (dscp_index >= ECORE_DCBX_DSCP_SIZE) {
1559                 DP_ERR(p_hwfn, "Invalid dscp index %d\n", dscp_index);
1560                 return ECORE_INVAL;
1561         }
1562
1563         p_dcbx_info = OSAL_ALLOC(p_hwfn->p_dev, GFP_KERNEL,
1564                                  sizeof(*p_dcbx_info));
1565         if (!p_dcbx_info)
1566                 return ECORE_NOMEM;
1567
1568         OSAL_MEMSET(p_dcbx_info, 0, sizeof(*p_dcbx_info));
1569         rc = ecore_dcbx_query_params(p_hwfn, p_dcbx_info,
1570                                      ECORE_DCBX_OPERATIONAL_MIB);
1571         if (rc) {
1572                 OSAL_FREE(p_hwfn->p_dev, p_dcbx_info);
1573                 return rc;
1574         }
1575
1576         *p_dscp_pri = p_dcbx_info->dscp.dscp_pri_map[dscp_index];
1577         OSAL_FREE(p_hwfn->p_dev, p_dcbx_info);
1578
1579         return ECORE_SUCCESS;
1580 }
1581
1582 enum _ecore_status_t
1583 ecore_dcbx_set_dscp_priority(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
1584                              u8 dscp_index, u8 pri_val)
1585 {
1586         struct ecore_dcbx_set dcbx_set;
1587         enum _ecore_status_t rc;
1588
1589         if (dscp_index >= ECORE_DCBX_DSCP_SIZE ||
1590             pri_val >= ECORE_MAX_PFC_PRIORITIES) {
1591                 DP_ERR(p_hwfn, "Invalid dscp params: index = %d pri = %d\n",
1592                        dscp_index, pri_val);
1593                 return ECORE_INVAL;
1594         }
1595
1596         OSAL_MEMSET(&dcbx_set, 0, sizeof(dcbx_set));
1597         rc = ecore_dcbx_get_config_params(p_hwfn, &dcbx_set);
1598         if (rc)
1599                 return rc;
1600
1601         dcbx_set.override_flags = ECORE_DCBX_OVERRIDE_DSCP_CFG;
1602         dcbx_set.dscp.dscp_pri_map[dscp_index] = pri_val;
1603
1604         return ecore_dcbx_config_params(p_hwfn, p_ptt, &dcbx_set, 1);
1605 }