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