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