]> Pileus Git - ~andy/linux/blob - drivers/net/bnx2x/bnx2x_dcb.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[~andy/linux] / drivers / net / bnx2x / bnx2x_dcb.c
1 /* bnx2x_dcb.c: Broadcom Everest network driver.
2  *
3  * Copyright 2009-2010 Broadcom Corporation
4  *
5  * Unless you and Broadcom execute a separate written software license
6  * agreement governing use of this software, this software is licensed to you
7  * under the terms of the GNU General Public License version 2, available
8  * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
9  *
10  * Notwithstanding the above, under no circumstances may you combine this
11  * software in any way with any other Broadcom software provided under a
12  * license other than the GPL, without Broadcom's express prior written
13  * consent.
14  *
15  * Maintained by: Eilon Greenstein <eilong@broadcom.com>
16  * Written by: Dmitry Kravkov
17  *
18  */
19 #include <linux/netdevice.h>
20 #include <linux/types.h>
21 #include <linux/errno.h>
22
23 #include "bnx2x.h"
24 #include "bnx2x_cmn.h"
25 #include "bnx2x_dcb.h"
26
27
28 /* forward declarations of dcbx related functions */
29 static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp);
30 static void bnx2x_pfc_set_pfc(struct bnx2x *bp);
31 static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp);
32 static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp);
33 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
34                                           u32 *set_configuration_ets_pg,
35                                           u32 *pri_pg_tbl);
36 static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
37                                             u32 *pg_pri_orginal_spread,
38                                             struct pg_help_data *help_data);
39 static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
40                                        struct pg_help_data *help_data,
41                                        struct dcbx_ets_feature *ets,
42                                        u32 *pg_pri_orginal_spread);
43 static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
44                                 struct cos_help_data *cos_data,
45                                 u32 *pg_pri_orginal_spread,
46                                 struct dcbx_ets_feature *ets);
47 static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp);
48
49
50 static void bnx2x_pfc_set(struct bnx2x *bp)
51 {
52         struct bnx2x_nig_brb_pfc_port_params pfc_params = {0};
53         u32 pri_bit, val = 0;
54         u8 pri;
55
56         /* Tx COS configuration */
57         if (bp->dcbx_port_params.ets.cos_params[0].pauseable)
58                 pfc_params.rx_cos0_priority_mask =
59                         bp->dcbx_port_params.ets.cos_params[0].pri_bitmask;
60         if (bp->dcbx_port_params.ets.cos_params[1].pauseable)
61                 pfc_params.rx_cos1_priority_mask =
62                         bp->dcbx_port_params.ets.cos_params[1].pri_bitmask;
63
64
65         /**
66          * Rx COS configuration
67          * Changing PFC RX configuration .
68          * In RX COS0 will always be configured to lossy and COS1 to lossless
69          */
70         for (pri = 0 ; pri < MAX_PFC_PRIORITIES ; pri++) {
71                 pri_bit = 1 << pri;
72
73                 if (pri_bit & DCBX_PFC_PRI_PAUSE_MASK(bp))
74                         val |= 1 << (pri * 4);
75         }
76
77         pfc_params.pkt_priority_to_cos = val;
78
79         /* RX COS0 */
80         pfc_params.llfc_low_priority_classes = 0;
81         /* RX COS1 */
82         pfc_params.llfc_high_priority_classes = DCBX_PFC_PRI_PAUSE_MASK(bp);
83
84         /* BRB configuration */
85         pfc_params.cos0_pauseable = false;
86         pfc_params.cos1_pauseable = true;
87
88         bnx2x_acquire_phy_lock(bp);
89         bp->link_params.feature_config_flags |= FEATURE_CONFIG_PFC_ENABLED;
90         bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &pfc_params);
91         bnx2x_release_phy_lock(bp);
92 }
93
94 static void bnx2x_pfc_clear(struct bnx2x *bp)
95 {
96         struct bnx2x_nig_brb_pfc_port_params nig_params = {0};
97         nig_params.pause_enable = 1;
98 #ifdef BNX2X_SAFC
99         if (bp->flags & SAFC_TX_FLAG) {
100                 u32 high = 0, low = 0;
101                 int i;
102
103                 for (i = 0; i < BNX2X_MAX_PRIORITY; i++) {
104                         if (bp->pri_map[i] == 1)
105                                 high |= (1 << i);
106                         if (bp->pri_map[i] == 0)
107                                 low |= (1 << i);
108                 }
109
110                 nig_params.llfc_low_priority_classes = high;
111                 nig_params.llfc_low_priority_classes = low;
112
113                 nig_params.pause_enable = 0;
114                 nig_params.llfc_enable = 1;
115                 nig_params.llfc_out_en = 1;
116         }
117 #endif /* BNX2X_SAFC */
118         bnx2x_acquire_phy_lock(bp);
119         bp->link_params.feature_config_flags &= ~FEATURE_CONFIG_PFC_ENABLED;
120         bnx2x_update_pfc(&bp->link_params, &bp->link_vars, &nig_params);
121         bnx2x_release_phy_lock(bp);
122 }
123
124 static void  bnx2x_dump_dcbx_drv_param(struct bnx2x *bp,
125                                        struct dcbx_features *features,
126                                        u32 error)
127 {
128         u8 i = 0;
129         DP(NETIF_MSG_LINK, "local_mib.error %x\n", error);
130
131         /* PG */
132         DP(NETIF_MSG_LINK,
133            "local_mib.features.ets.enabled %x\n", features->ets.enabled);
134         for (i = 0; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++)
135                 DP(NETIF_MSG_LINK,
136                    "local_mib.features.ets.pg_bw_tbl[%d] %d\n", i,
137                    DCBX_PG_BW_GET(features->ets.pg_bw_tbl, i));
138         for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++)
139                 DP(NETIF_MSG_LINK,
140                    "local_mib.features.ets.pri_pg_tbl[%d] %d\n", i,
141                    DCBX_PRI_PG_GET(features->ets.pri_pg_tbl, i));
142
143         /* pfc */
144         DP(NETIF_MSG_LINK, "dcbx_features.pfc.pri_en_bitmap %x\n",
145                                         features->pfc.pri_en_bitmap);
146         DP(NETIF_MSG_LINK, "dcbx_features.pfc.pfc_caps %x\n",
147                                         features->pfc.pfc_caps);
148         DP(NETIF_MSG_LINK, "dcbx_features.pfc.enabled %x\n",
149                                         features->pfc.enabled);
150
151         DP(NETIF_MSG_LINK, "dcbx_features.app.default_pri %x\n",
152                                         features->app.default_pri);
153         DP(NETIF_MSG_LINK, "dcbx_features.app.tc_supported %x\n",
154                                         features->app.tc_supported);
155         DP(NETIF_MSG_LINK, "dcbx_features.app.enabled %x\n",
156                                         features->app.enabled);
157         for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++) {
158                 DP(NETIF_MSG_LINK,
159                    "dcbx_features.app.app_pri_tbl[%x].app_id %x\n",
160                    i, features->app.app_pri_tbl[i].app_id);
161                 DP(NETIF_MSG_LINK,
162                    "dcbx_features.app.app_pri_tbl[%x].pri_bitmap %x\n",
163                    i, features->app.app_pri_tbl[i].pri_bitmap);
164                 DP(NETIF_MSG_LINK,
165                    "dcbx_features.app.app_pri_tbl[%x].appBitfield %x\n",
166                    i, features->app.app_pri_tbl[i].appBitfield);
167         }
168 }
169
170 static void bnx2x_dcbx_get_ap_priority(struct bnx2x *bp,
171                                        u8 pri_bitmap,
172                                        u8 llfc_traf_type)
173 {
174         u32 pri = MAX_PFC_PRIORITIES;
175         u32 index = MAX_PFC_PRIORITIES - 1;
176         u32 pri_mask;
177         u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
178
179         /* Choose the highest priority */
180         while ((MAX_PFC_PRIORITIES == pri) && (0 != index)) {
181                 pri_mask = 1 << index;
182                 if (GET_FLAGS(pri_bitmap, pri_mask))
183                         pri = index ;
184                 index--;
185         }
186
187         if (pri < MAX_PFC_PRIORITIES)
188                 ttp[llfc_traf_type] = max_t(u32, ttp[llfc_traf_type], pri);
189 }
190
191 static void bnx2x_dcbx_get_ap_feature(struct bnx2x *bp,
192                                    struct dcbx_app_priority_feature *app,
193                                    u32 error) {
194         u8 index;
195         u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
196
197         if (GET_FLAGS(error, DCBX_LOCAL_APP_ERROR))
198                 DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_ERROR\n");
199
200         if (app->enabled && !GET_FLAGS(error, DCBX_LOCAL_APP_ERROR)) {
201
202                 bp->dcbx_port_params.app.enabled = true;
203
204                 for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
205                         ttp[index] = 0;
206
207                 if (app->default_pri < MAX_PFC_PRIORITIES)
208                         ttp[LLFC_TRAFFIC_TYPE_NW] = app->default_pri;
209
210                 for (index = 0 ; index < DCBX_MAX_APP_PROTOCOL; index++) {
211                         struct dcbx_app_priority_entry *entry =
212                                                         app->app_pri_tbl;
213
214                         if (GET_FLAGS(entry[index].appBitfield,
215                                      DCBX_APP_SF_ETH_TYPE) &&
216                            ETH_TYPE_FCOE == entry[index].app_id)
217                                 bnx2x_dcbx_get_ap_priority(bp,
218                                                 entry[index].pri_bitmap,
219                                                 LLFC_TRAFFIC_TYPE_FCOE);
220
221                         if (GET_FLAGS(entry[index].appBitfield,
222                                      DCBX_APP_SF_PORT) &&
223                            TCP_PORT_ISCSI == entry[index].app_id)
224                                 bnx2x_dcbx_get_ap_priority(bp,
225                                                 entry[index].pri_bitmap,
226                                                 LLFC_TRAFFIC_TYPE_ISCSI);
227                 }
228         } else {
229                 DP(NETIF_MSG_LINK, "DCBX_LOCAL_APP_DISABLED\n");
230                 bp->dcbx_port_params.app.enabled = false;
231                 for (index = 0 ; index < LLFC_DRIVER_TRAFFIC_TYPE_MAX; index++)
232                         ttp[index] = INVALID_TRAFFIC_TYPE_PRIORITY;
233         }
234 }
235
236 static void bnx2x_dcbx_get_ets_feature(struct bnx2x *bp,
237                                        struct dcbx_ets_feature *ets,
238                                        u32 error) {
239         int i = 0;
240         u32 pg_pri_orginal_spread[DCBX_MAX_NUM_PG_BW_ENTRIES] = {0};
241         struct pg_help_data pg_help_data;
242         struct bnx2x_dcbx_cos_params *cos_params =
243                         bp->dcbx_port_params.ets.cos_params;
244
245         memset(&pg_help_data, 0, sizeof(struct pg_help_data));
246
247
248         if (GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR))
249                 DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_ERROR\n");
250
251
252         /* Clean up old settings of ets on COS */
253         for (i = 0; i < E2_NUM_OF_COS ; i++) {
254
255                 cos_params[i].pauseable = false;
256                 cos_params[i].strict = BNX2X_DCBX_COS_NOT_STRICT;
257                 cos_params[i].bw_tbl = DCBX_INVALID_COS_BW;
258                 cos_params[i].pri_bitmask = DCBX_PFC_PRI_GET_NON_PAUSE(bp, 0);
259         }
260
261         if (bp->dcbx_port_params.app.enabled &&
262            !GET_FLAGS(error, DCBX_LOCAL_ETS_ERROR) &&
263            ets->enabled) {
264                 DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_ENABLE\n");
265                 bp->dcbx_port_params.ets.enabled = true;
266
267                 bnx2x_dcbx_get_ets_pri_pg_tbl(bp,
268                                               pg_pri_orginal_spread,
269                                               ets->pri_pg_tbl);
270
271                 bnx2x_dcbx_get_num_pg_traf_type(bp,
272                                                 pg_pri_orginal_spread,
273                                                 &pg_help_data);
274
275                 bnx2x_dcbx_fill_cos_params(bp, &pg_help_data,
276                                            ets, pg_pri_orginal_spread);
277
278         } else {
279                 DP(NETIF_MSG_LINK, "DCBX_LOCAL_ETS_DISABLED\n");
280                 bp->dcbx_port_params.ets.enabled = false;
281                 ets->pri_pg_tbl[0] = 0;
282
283                 for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES ; i++)
284                         DCBX_PG_BW_SET(ets->pg_bw_tbl, i, 1);
285         }
286 }
287
288 static void  bnx2x_dcbx_get_pfc_feature(struct bnx2x *bp,
289                                         struct dcbx_pfc_feature *pfc, u32 error)
290 {
291
292         if (GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR))
293                 DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_ERROR\n");
294
295         if (bp->dcbx_port_params.app.enabled &&
296            !GET_FLAGS(error, DCBX_LOCAL_PFC_ERROR) &&
297            pfc->enabled) {
298                 bp->dcbx_port_params.pfc.enabled = true;
299                 bp->dcbx_port_params.pfc.priority_non_pauseable_mask =
300                         ~(pfc->pri_en_bitmap);
301         } else {
302                 DP(NETIF_MSG_LINK, "DCBX_LOCAL_PFC_DISABLED\n");
303                 bp->dcbx_port_params.pfc.enabled = false;
304                 bp->dcbx_port_params.pfc.priority_non_pauseable_mask = 0;
305         }
306 }
307
308 static void bnx2x_get_dcbx_drv_param(struct bnx2x *bp,
309                                      struct dcbx_features *features,
310                                      u32 error)
311 {
312         bnx2x_dcbx_get_ap_feature(bp, &features->app, error);
313
314         bnx2x_dcbx_get_pfc_feature(bp, &features->pfc, error);
315
316         bnx2x_dcbx_get_ets_feature(bp, &features->ets, error);
317 }
318
319 #define DCBX_LOCAL_MIB_MAX_TRY_READ             (100)
320 static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
321                                u32 *base_mib_addr,
322                                u32 offset,
323                                int read_mib_type)
324 {
325         int max_try_read = 0, i;
326         u32 *buff, mib_size, prefix_seq_num, suffix_seq_num;
327         struct lldp_remote_mib *remote_mib ;
328         struct lldp_local_mib  *local_mib;
329
330
331         switch (read_mib_type) {
332         case DCBX_READ_LOCAL_MIB:
333                 mib_size = sizeof(struct lldp_local_mib);
334                 break;
335         case DCBX_READ_REMOTE_MIB:
336                 mib_size = sizeof(struct lldp_remote_mib);
337                 break;
338         default:
339                 return 1; /*error*/
340         }
341
342         offset += BP_PORT(bp) * mib_size;
343
344         do {
345                 buff = base_mib_addr;
346                 for (i = 0; i < mib_size; i += 4, buff++)
347                         *buff = REG_RD(bp, offset + i);
348
349                 max_try_read++;
350
351                 switch (read_mib_type) {
352                 case DCBX_READ_LOCAL_MIB:
353                         local_mib = (struct lldp_local_mib *) base_mib_addr;
354                         prefix_seq_num = local_mib->prefix_seq_num;
355                         suffix_seq_num = local_mib->suffix_seq_num;
356                         break;
357                 case DCBX_READ_REMOTE_MIB:
358                         remote_mib = (struct lldp_remote_mib *) base_mib_addr;
359                         prefix_seq_num = remote_mib->prefix_seq_num;
360                         suffix_seq_num = remote_mib->suffix_seq_num;
361                         break;
362                 default:
363                         return 1; /*error*/
364                 }
365         } while ((prefix_seq_num != suffix_seq_num) &&
366                (max_try_read < DCBX_LOCAL_MIB_MAX_TRY_READ));
367
368         if (max_try_read >= DCBX_LOCAL_MIB_MAX_TRY_READ) {
369                 BNX2X_ERR("MIB could not be read\n");
370                 return 1;
371         }
372
373         return 0;
374 }
375
376 static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
377 {
378         if (CHIP_IS_E2(bp)) {
379                 if (BP_PORT(bp)) {
380                         BNX2X_ERR("4 port mode is not supported");
381                         return;
382                 }
383
384                 if (bp->dcbx_port_params.pfc.enabled)
385
386                         /* 1. Fills up common PFC structures if required.*/
387                         /* 2. Configure NIG, MAC and BRB via the elink:
388                          *    elink must first check if BMAC is not in reset
389                          *    and only then configures the BMAC
390                          *    Or, configure EMAC.
391                          */
392                         bnx2x_pfc_set(bp);
393
394                 else
395                         bnx2x_pfc_clear(bp);
396         }
397 }
398
399 static void bnx2x_dcbx_stop_hw_tx(struct bnx2x *bp)
400 {
401         DP(NETIF_MSG_LINK, "sending STOP TRAFFIC\n");
402         bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_STOP_TRAFFIC,
403                       0 /* connectionless */,
404                       0 /* dataHi is zero */,
405                       0 /* dataLo is zero */,
406                       1 /* common */);
407 }
408
409 static void bnx2x_dcbx_resume_hw_tx(struct bnx2x *bp)
410 {
411         bnx2x_pfc_fw_struct_e2(bp);
412         DP(NETIF_MSG_LINK, "sending START TRAFFIC\n");
413         bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_START_TRAFFIC,
414                       0, /* connectionless */
415                       U64_HI(bnx2x_sp_mapping(bp, pfc_config)),
416                       U64_LO(bnx2x_sp_mapping(bp, pfc_config)),
417                       1  /* commmon */);
418 }
419
420 static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
421 {
422         struct bnx2x_dcbx_pg_params *ets = &(bp->dcbx_port_params.ets);
423         u8      status = 0;
424
425         bnx2x_ets_disabled(&bp->link_params);
426
427         if (!ets->enabled)
428                 return;
429
430         if ((ets->num_of_cos == 0) || (ets->num_of_cos > E2_NUM_OF_COS)) {
431                 BNX2X_ERR("illegal num of cos= %x", ets->num_of_cos);
432                 return;
433         }
434
435         /* valid COS entries */
436         if (ets->num_of_cos == 1)   /* no ETS */
437                 return;
438
439         /* sanity */
440         if (((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[0].strict) &&
441              (DCBX_INVALID_COS_BW == ets->cos_params[0].bw_tbl)) ||
442             ((BNX2X_DCBX_COS_NOT_STRICT == ets->cos_params[1].strict) &&
443              (DCBX_INVALID_COS_BW == ets->cos_params[1].bw_tbl))) {
444                 BNX2X_ERR("all COS should have at least bw_limit or strict"
445                             "ets->cos_params[0].strict= %x"
446                             "ets->cos_params[0].bw_tbl= %x"
447                             "ets->cos_params[1].strict= %x"
448                             "ets->cos_params[1].bw_tbl= %x",
449                           ets->cos_params[0].strict,
450                           ets->cos_params[0].bw_tbl,
451                           ets->cos_params[1].strict,
452                           ets->cos_params[1].bw_tbl);
453                 return;
454         }
455         /* If we join a group and there is bw_tbl and strict then bw rules */
456         if ((DCBX_INVALID_COS_BW != ets->cos_params[0].bw_tbl) &&
457             (DCBX_INVALID_COS_BW != ets->cos_params[1].bw_tbl)) {
458                 u32 bw_tbl_0 = ets->cos_params[0].bw_tbl;
459                 u32 bw_tbl_1 = ets->cos_params[1].bw_tbl;
460                 /* Do not allow 0-100 configuration
461                  * since PBF does not support it
462                  * force 1-99 instead
463                  */
464                 if (bw_tbl_0 == 0) {
465                         bw_tbl_0 = 1;
466                         bw_tbl_1 = 99;
467                 } else if (bw_tbl_1 == 0) {
468                         bw_tbl_1 = 1;
469                         bw_tbl_0 = 99;
470                 }
471
472                 bnx2x_ets_bw_limit(&bp->link_params, bw_tbl_0, bw_tbl_1);
473         } else {
474                 if (ets->cos_params[0].strict == BNX2X_DCBX_COS_HIGH_STRICT)
475                         status = bnx2x_ets_strict(&bp->link_params, 0);
476                 else if (ets->cos_params[1].strict
477                                                 == BNX2X_DCBX_COS_HIGH_STRICT)
478                         status = bnx2x_ets_strict(&bp->link_params, 1);
479
480                 if (status)
481                         BNX2X_ERR("update_ets_params failed\n");
482         }
483 }
484
485 static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp)
486 {
487         struct lldp_local_mib local_mib = {0};
488         u32 dcbx_neg_res_offset = SHMEM2_RD(bp, dcbx_neg_res_offset);
489         int rc;
490
491         DP(NETIF_MSG_LINK, "dcbx_neg_res_offset 0x%x\n", dcbx_neg_res_offset);
492
493         if (SHMEM_DCBX_NEG_RES_NONE == dcbx_neg_res_offset) {
494                 BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
495                 return -EINVAL;
496         }
497         rc = bnx2x_dcbx_read_mib(bp, (u32 *)&local_mib, dcbx_neg_res_offset,
498                                  DCBX_READ_LOCAL_MIB);
499
500         if (rc) {
501                 BNX2X_ERR("Faild to read local mib from FW\n");
502                 return rc;
503         }
504
505         /* save features and error */
506         bp->dcbx_local_feat = local_mib.features;
507         bp->dcbx_error = local_mib.error;
508         return 0;
509 }
510
511 void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
512 {
513         switch (state) {
514         case BNX2X_DCBX_STATE_NEG_RECEIVED:
515                 {
516                         DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
517
518                         /* Read neg results if dcbx is in the FW */
519                         if (bnx2x_dcbx_read_shmem_neg_results(bp))
520                                 return;
521
522                         bnx2x_dump_dcbx_drv_param(bp, &bp->dcbx_local_feat,
523                                                   bp->dcbx_error);
524
525                         bnx2x_get_dcbx_drv_param(bp, &bp->dcbx_local_feat,
526                                                  bp->dcbx_error);
527
528                         if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
529                                 bnx2x_dcbx_stop_hw_tx(bp);
530                                 return;
531                         }
532                         /* fall through */
533                 }
534         case BNX2X_DCBX_STATE_TX_PAUSED:
535                 DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_PAUSED\n");
536                 bnx2x_pfc_set_pfc(bp);
537
538                 bnx2x_dcbx_update_ets_params(bp);
539                 if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
540                         bnx2x_dcbx_resume_hw_tx(bp);
541                         return;
542                 }
543                 /* fall through */
544         case BNX2X_DCBX_STATE_TX_RELEASED:
545                 DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_RELEASED\n");
546                 if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD)
547                         bnx2x_fw_command(bp, DRV_MSG_CODE_DCBX_PMF_DRV_OK, 0);
548
549                 return;
550         default:
551                 BNX2X_ERR("Unknown DCBX_STATE\n");
552         }
553 }
554
555
556 #define LLDP_STATS_OFFSET(bp)           (BP_PORT(bp)*\
557                                         sizeof(struct lldp_dcbx_stat))
558
559 /* calculate struct offset in array according to chip information */
560 #define LLDP_PARAMS_OFFSET(bp)          (BP_PORT(bp)*sizeof(struct lldp_params))
561
562 #define LLDP_ADMIN_MIB_OFFSET(bp)       (PORT_MAX*sizeof(struct lldp_params) + \
563                                       BP_PORT(bp)*sizeof(struct lldp_admin_mib))
564
565 static void bnx2x_dcbx_lldp_updated_params(struct bnx2x *bp,
566                                            u32 dcbx_lldp_params_offset)
567 {
568         struct lldp_params lldp_params = {0};
569         u32 i = 0, *buff = NULL;
570         u32 offset = dcbx_lldp_params_offset + LLDP_PARAMS_OFFSET(bp);
571
572         DP(NETIF_MSG_LINK, "lldp_offset 0x%x\n", offset);
573
574         if ((bp->lldp_config_params.overwrite_settings ==
575                                 BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE)) {
576                 /* Read the data first */
577                 buff = (u32 *)&lldp_params;
578                 for (i = 0; i < sizeof(struct lldp_params); i += 4,  buff++)
579                         *buff = REG_RD(bp, (offset + i));
580
581                 lldp_params.msg_tx_hold =
582                         (u8)bp->lldp_config_params.msg_tx_hold;
583                 lldp_params.msg_fast_tx_interval =
584                         (u8)bp->lldp_config_params.msg_fast_tx;
585                 lldp_params.tx_crd_max =
586                         (u8)bp->lldp_config_params.tx_credit_max;
587                 lldp_params.msg_tx_interval =
588                         (u8)bp->lldp_config_params.msg_tx_interval;
589                 lldp_params.tx_fast =
590                         (u8)bp->lldp_config_params.tx_fast;
591
592                 /* Write the data.*/
593                 buff = (u32 *)&lldp_params;
594                 for (i = 0; i < sizeof(struct lldp_params); i += 4, buff++)
595                         REG_WR(bp, (offset + i) , *buff);
596
597
598         } else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
599                                 bp->lldp_config_params.overwrite_settings)
600                 bp->lldp_config_params.overwrite_settings =
601                                 BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
602 }
603
604 static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
605                                 u32 dcbx_lldp_params_offset)
606 {
607         struct lldp_admin_mib admin_mib;
608         u32 i, other_traf_type = PREDEFINED_APP_IDX_MAX, traf_type = 0;
609         u32 *buff;
610         u32 offset = dcbx_lldp_params_offset + LLDP_ADMIN_MIB_OFFSET(bp);
611
612         /*shortcuts*/
613         struct dcbx_features *af = &admin_mib.features;
614         struct bnx2x_config_dcbx_params *dp = &bp->dcbx_config_params;
615
616         memset(&admin_mib, 0, sizeof(struct lldp_admin_mib));
617         buff = (u32 *)&admin_mib;
618         /* Read the data first */
619         for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
620                 *buff = REG_RD(bp, (offset + i));
621
622         if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
623                 SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
624         else
625                 RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
626
627         if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
628                                 dp->overwrite_settings)) {
629                 RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_CEE_VERSION_MASK);
630                 admin_mib.ver_cfg_flags |=
631                         (dp->admin_dcbx_version << DCBX_CEE_VERSION_SHIFT) &
632                          DCBX_CEE_VERSION_MASK;
633
634                 af->ets.enabled = (u8)dp->admin_ets_enable;
635
636                 af->pfc.enabled = (u8)dp->admin_pfc_enable;
637
638                 /* FOR IEEE dp->admin_tc_supported_tx_enable */
639                 if (dp->admin_ets_configuration_tx_enable)
640                         SET_FLAGS(admin_mib.ver_cfg_flags,
641                                   DCBX_ETS_CONFIG_TX_ENABLED);
642                 else
643                         RESET_FLAGS(admin_mib.ver_cfg_flags,
644                                     DCBX_ETS_CONFIG_TX_ENABLED);
645                 /* For IEEE admin_ets_recommendation_tx_enable */
646                 if (dp->admin_pfc_tx_enable)
647                         SET_FLAGS(admin_mib.ver_cfg_flags,
648                                   DCBX_PFC_CONFIG_TX_ENABLED);
649                 else
650                         RESET_FLAGS(admin_mib.ver_cfg_flags,
651                                   DCBX_PFC_CONFIG_TX_ENABLED);
652
653                 if (dp->admin_application_priority_tx_enable)
654                         SET_FLAGS(admin_mib.ver_cfg_flags,
655                                   DCBX_APP_CONFIG_TX_ENABLED);
656                 else
657                         RESET_FLAGS(admin_mib.ver_cfg_flags,
658                                   DCBX_APP_CONFIG_TX_ENABLED);
659
660                 if (dp->admin_ets_willing)
661                         SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
662                 else
663                         RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_ETS_WILLING);
664                 /* For IEEE admin_ets_reco_valid */
665                 if (dp->admin_pfc_willing)
666                         SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
667                 else
668                         RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_PFC_WILLING);
669
670                 if (dp->admin_app_priority_willing)
671                         SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
672                 else
673                         RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_APP_WILLING);
674
675                 for (i = 0 ; i < DCBX_MAX_NUM_PG_BW_ENTRIES; i++) {
676                         DCBX_PG_BW_SET(af->ets.pg_bw_tbl, i,
677                                 (u8)dp->admin_configuration_bw_precentage[i]);
678
679                         DP(NETIF_MSG_LINK, "pg_bw_tbl[%d] = %02x\n",
680                            i, DCBX_PG_BW_GET(af->ets.pg_bw_tbl, i));
681                 }
682
683                 for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
684                         DCBX_PRI_PG_SET(af->ets.pri_pg_tbl, i,
685                                         (u8)dp->admin_configuration_ets_pg[i]);
686
687                         DP(NETIF_MSG_LINK, "pri_pg_tbl[%d] = %02x\n",
688                            i, DCBX_PRI_PG_GET(af->ets.pri_pg_tbl, i));
689                 }
690
691                 /*For IEEE admin_recommendation_bw_precentage
692                  *For IEEE admin_recommendation_ets_pg */
693                 af->pfc.pri_en_bitmap = (u8)dp->admin_pfc_bitmap;
694                 for (i = 0; i < 4; i++) {
695                         if (dp->admin_priority_app_table[i].valid) {
696                                 struct bnx2x_admin_priority_app_table *table =
697                                         dp->admin_priority_app_table;
698                                 if ((ETH_TYPE_FCOE == table[i].app_id) &&
699                                    (TRAFFIC_TYPE_ETH == table[i].traffic_type))
700                                         traf_type = FCOE_APP_IDX;
701                                 else if ((TCP_PORT_ISCSI == table[i].app_id) &&
702                                    (TRAFFIC_TYPE_PORT == table[i].traffic_type))
703                                         traf_type = ISCSI_APP_IDX;
704                                 else
705                                         traf_type = other_traf_type++;
706
707                                 af->app.app_pri_tbl[traf_type].app_id =
708                                         table[i].app_id;
709
710                                 af->app.app_pri_tbl[traf_type].pri_bitmap =
711                                         (u8)(1 << table[i].priority);
712
713                                 af->app.app_pri_tbl[traf_type].appBitfield =
714                                     (DCBX_APP_ENTRY_VALID);
715
716                                 af->app.app_pri_tbl[traf_type].appBitfield |=
717                                    (TRAFFIC_TYPE_ETH == table[i].traffic_type) ?
718                                         DCBX_APP_SF_ETH_TYPE : DCBX_APP_SF_PORT;
719                         }
720                 }
721
722                 af->app.default_pri = (u8)dp->admin_default_priority;
723
724         } else if (BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
725                                                 dp->overwrite_settings)
726                 dp->overwrite_settings = BNX2X_DCBX_OVERWRITE_SETTINGS_INVALID;
727
728         /* Write the data. */
729         buff = (u32 *)&admin_mib;
730         for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
731                 REG_WR(bp, (offset + i), *buff);
732 }
733
734 void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
735 {
736         if (CHIP_IS_E2(bp) && !CHIP_MODE_IS_4_PORT(bp)) {
737                 bp->dcb_state = dcb_on;
738                 bp->dcbx_enabled = dcbx_enabled;
739         } else {
740                 bp->dcb_state = false;
741                 bp->dcbx_enabled = BNX2X_DCBX_ENABLED_INVALID;
742         }
743         DP(NETIF_MSG_LINK, "DCB state [%s:%s]\n",
744            dcb_on ? "ON" : "OFF",
745            dcbx_enabled == BNX2X_DCBX_ENABLED_OFF ? "user-mode" :
746            dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF ? "on-chip static" :
747            dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON ?
748            "on-chip with negotiation" : "invalid");
749 }
750
751 void bnx2x_dcbx_init_params(struct bnx2x *bp)
752 {
753         bp->dcbx_config_params.admin_dcbx_version = 0x0; /* 0 - CEE; 1 - IEEE */
754         bp->dcbx_config_params.admin_ets_willing = 1;
755         bp->dcbx_config_params.admin_pfc_willing = 1;
756         bp->dcbx_config_params.overwrite_settings = 1;
757         bp->dcbx_config_params.admin_ets_enable = 1;
758         bp->dcbx_config_params.admin_pfc_enable = 1;
759         bp->dcbx_config_params.admin_tc_supported_tx_enable = 1;
760         bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
761         bp->dcbx_config_params.admin_pfc_tx_enable = 1;
762         bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
763         bp->dcbx_config_params.admin_ets_reco_valid = 1;
764         bp->dcbx_config_params.admin_app_priority_willing = 1;
765         bp->dcbx_config_params.admin_configuration_bw_precentage[0] = 00;
766         bp->dcbx_config_params.admin_configuration_bw_precentage[1] = 50;
767         bp->dcbx_config_params.admin_configuration_bw_precentage[2] = 50;
768         bp->dcbx_config_params.admin_configuration_bw_precentage[3] = 0;
769         bp->dcbx_config_params.admin_configuration_bw_precentage[4] = 0;
770         bp->dcbx_config_params.admin_configuration_bw_precentage[5] = 0;
771         bp->dcbx_config_params.admin_configuration_bw_precentage[6] = 0;
772         bp->dcbx_config_params.admin_configuration_bw_precentage[7] = 0;
773         bp->dcbx_config_params.admin_configuration_ets_pg[0] = 1;
774         bp->dcbx_config_params.admin_configuration_ets_pg[1] = 0;
775         bp->dcbx_config_params.admin_configuration_ets_pg[2] = 0;
776         bp->dcbx_config_params.admin_configuration_ets_pg[3] = 2;
777         bp->dcbx_config_params.admin_configuration_ets_pg[4] = 0;
778         bp->dcbx_config_params.admin_configuration_ets_pg[5] = 0;
779         bp->dcbx_config_params.admin_configuration_ets_pg[6] = 0;
780         bp->dcbx_config_params.admin_configuration_ets_pg[7] = 0;
781         bp->dcbx_config_params.admin_recommendation_bw_precentage[0] = 0;
782         bp->dcbx_config_params.admin_recommendation_bw_precentage[1] = 1;
783         bp->dcbx_config_params.admin_recommendation_bw_precentage[2] = 2;
784         bp->dcbx_config_params.admin_recommendation_bw_precentage[3] = 0;
785         bp->dcbx_config_params.admin_recommendation_bw_precentage[4] = 7;
786         bp->dcbx_config_params.admin_recommendation_bw_precentage[5] = 5;
787         bp->dcbx_config_params.admin_recommendation_bw_precentage[6] = 6;
788         bp->dcbx_config_params.admin_recommendation_bw_precentage[7] = 7;
789         bp->dcbx_config_params.admin_recommendation_ets_pg[0] = 0;
790         bp->dcbx_config_params.admin_recommendation_ets_pg[1] = 1;
791         bp->dcbx_config_params.admin_recommendation_ets_pg[2] = 2;
792         bp->dcbx_config_params.admin_recommendation_ets_pg[3] = 3;
793         bp->dcbx_config_params.admin_recommendation_ets_pg[4] = 4;
794         bp->dcbx_config_params.admin_recommendation_ets_pg[5] = 5;
795         bp->dcbx_config_params.admin_recommendation_ets_pg[6] = 6;
796         bp->dcbx_config_params.admin_recommendation_ets_pg[7] = 7;
797         bp->dcbx_config_params.admin_pfc_bitmap = 0x8; /* FCoE(3) enable */
798         bp->dcbx_config_params.admin_priority_app_table[0].valid = 1;
799         bp->dcbx_config_params.admin_priority_app_table[1].valid = 1;
800         bp->dcbx_config_params.admin_priority_app_table[2].valid = 0;
801         bp->dcbx_config_params.admin_priority_app_table[3].valid = 0;
802         bp->dcbx_config_params.admin_priority_app_table[0].priority = 3;
803         bp->dcbx_config_params.admin_priority_app_table[1].priority = 0;
804         bp->dcbx_config_params.admin_priority_app_table[2].priority = 0;
805         bp->dcbx_config_params.admin_priority_app_table[3].priority = 0;
806         bp->dcbx_config_params.admin_priority_app_table[0].traffic_type = 0;
807         bp->dcbx_config_params.admin_priority_app_table[1].traffic_type = 1;
808         bp->dcbx_config_params.admin_priority_app_table[2].traffic_type = 0;
809         bp->dcbx_config_params.admin_priority_app_table[3].traffic_type = 0;
810         bp->dcbx_config_params.admin_priority_app_table[0].app_id = 0x8906;
811         bp->dcbx_config_params.admin_priority_app_table[1].app_id = 3260;
812         bp->dcbx_config_params.admin_priority_app_table[2].app_id = 0;
813         bp->dcbx_config_params.admin_priority_app_table[3].app_id = 0;
814         bp->dcbx_config_params.admin_default_priority =
815                 bp->dcbx_config_params.admin_priority_app_table[1].priority;
816 }
817
818 void bnx2x_dcbx_init(struct bnx2x *bp)
819 {
820         u32 dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
821
822         if (bp->dcbx_enabled <= 0)
823                 return;
824
825         /* validate:
826          * chip of good for dcbx version,
827          * dcb is wanted
828          * the function is pmf
829          * shmem2 contains DCBX support fields
830          */
831         DP(NETIF_MSG_LINK, "dcb_state %d bp->port.pmf %d\n",
832            bp->dcb_state, bp->port.pmf);
833
834         if (bp->dcb_state ==  BNX2X_DCB_STATE_ON && bp->port.pmf &&
835             SHMEM2_HAS(bp, dcbx_lldp_params_offset)) {
836                 dcbx_lldp_params_offset =
837                         SHMEM2_RD(bp, dcbx_lldp_params_offset);
838
839                 DP(NETIF_MSG_LINK, "dcbx_lldp_params_offset 0x%x\n",
840                    dcbx_lldp_params_offset);
841
842                 if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
843                         bnx2x_dcbx_lldp_updated_params(bp,
844                                                        dcbx_lldp_params_offset);
845
846                         bnx2x_dcbx_admin_mib_updated_params(bp,
847                                 dcbx_lldp_params_offset);
848
849                         /* set default configuration BC has */
850                         bnx2x_dcbx_set_params(bp,
851                                               BNX2X_DCBX_STATE_NEG_RECEIVED);
852
853                         bnx2x_fw_command(bp,
854                                          DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG, 0);
855                 }
856         }
857 }
858
859 void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp)
860 {
861         struct priority_cos pricos[MAX_PFC_TRAFFIC_TYPES];
862         u32 i = 0, addr;
863         memset(pricos, 0, sizeof(pricos));
864         /* Default initialization */
865         for (i = 0; i < MAX_PFC_TRAFFIC_TYPES; i++)
866                 pricos[i].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
867
868         /* Store per port struct to internal memory */
869         addr = BAR_XSTRORM_INTMEM +
870                         XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
871                         offsetof(struct cmng_struct_per_port,
872                                  traffic_type_to_priority_cos);
873         __storm_memset_struct(bp, addr, sizeof(pricos), (u32 *)pricos);
874
875
876         /* LLFC disabled.*/
877         REG_WR8(bp , BAR_XSTRORM_INTMEM +
878                     XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
879                     offsetof(struct cmng_struct_per_port, llfc_mode),
880                         LLFC_MODE_NONE);
881
882         /* DCBX disabled.*/
883         REG_WR8(bp , BAR_XSTRORM_INTMEM +
884                     XSTORM_CMNG_PER_PORT_VARS_OFFSET(BP_PORT(bp)) +
885                     offsetof(struct cmng_struct_per_port, dcb_enabled),
886                         DCB_DISABLED);
887 }
888
889 static void
890 bnx2x_dcbx_print_cos_params(struct bnx2x *bp,
891                             struct flow_control_configuration *pfc_fw_cfg)
892 {
893         u8 pri = 0;
894         u8 cos = 0;
895
896         DP(NETIF_MSG_LINK,
897            "pfc_fw_cfg->dcb_version %x\n", pfc_fw_cfg->dcb_version);
898         DP(NETIF_MSG_LINK,
899            "pdev->params.dcbx_port_params.pfc."
900            "priority_non_pauseable_mask %x\n",
901            bp->dcbx_port_params.pfc.priority_non_pauseable_mask);
902
903         for (cos = 0 ; cos < bp->dcbx_port_params.ets.num_of_cos ; cos++) {
904                 DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
905                    "cos_params[%d].pri_bitmask %x\n", cos,
906                    bp->dcbx_port_params.ets.cos_params[cos].pri_bitmask);
907
908                 DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
909                    "cos_params[%d].bw_tbl %x\n", cos,
910                    bp->dcbx_port_params.ets.cos_params[cos].bw_tbl);
911
912                 DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
913                    "cos_params[%d].strict %x\n", cos,
914                    bp->dcbx_port_params.ets.cos_params[cos].strict);
915
916                 DP(NETIF_MSG_LINK, "pdev->params.dcbx_port_params.ets."
917                    "cos_params[%d].pauseable %x\n", cos,
918                    bp->dcbx_port_params.ets.cos_params[cos].pauseable);
919         }
920
921         for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
922                 DP(NETIF_MSG_LINK,
923                    "pfc_fw_cfg->traffic_type_to_priority_cos[%d]."
924                    "priority %x\n", pri,
925                    pfc_fw_cfg->traffic_type_to_priority_cos[pri].priority);
926
927                 DP(NETIF_MSG_LINK,
928                    "pfc_fw_cfg->traffic_type_to_priority_cos[%d].cos %x\n",
929                    pri, pfc_fw_cfg->traffic_type_to_priority_cos[pri].cos);
930         }
931 }
932
933 /* fills help_data according to pg_info */
934 static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x *bp,
935                                             u32 *pg_pri_orginal_spread,
936                                             struct pg_help_data *help_data)
937 {
938         bool pg_found  = false;
939         u32 i, traf_type, add_traf_type, add_pg;
940         u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
941         struct pg_entry_help_data *data = help_data->data; /*shotcut*/
942
943         /* Set to invalid */
944         for (i = 0; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++)
945                 data[i].pg = DCBX_ILLEGAL_PG;
946
947         for (add_traf_type = 0;
948              add_traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX; add_traf_type++) {
949                 pg_found = false;
950                 if (ttp[add_traf_type] < MAX_PFC_PRIORITIES) {
951                         add_pg = (u8)pg_pri_orginal_spread[ttp[add_traf_type]];
952                         for (traf_type = 0;
953                              traf_type < LLFC_DRIVER_TRAFFIC_TYPE_MAX;
954                              traf_type++) {
955                                 if (data[traf_type].pg == add_pg) {
956                                         if (!(data[traf_type].pg_priority &
957                                              (1 << ttp[add_traf_type])))
958                                                 data[traf_type].
959                                                         num_of_dif_pri++;
960                                         data[traf_type].pg_priority |=
961                                                 (1 << ttp[add_traf_type]);
962                                         pg_found = true;
963                                         break;
964                                 }
965                         }
966                         if (false == pg_found) {
967                                 data[help_data->num_of_pg].pg = add_pg;
968                                 data[help_data->num_of_pg].pg_priority =
969                                                 (1 << ttp[add_traf_type]);
970                                 data[help_data->num_of_pg].num_of_dif_pri = 1;
971                                 help_data->num_of_pg++;
972                         }
973                 }
974                 DP(NETIF_MSG_LINK,
975                    "add_traf_type %d pg_found %s num_of_pg %d\n",
976                    add_traf_type, (false == pg_found) ? "NO" : "YES",
977                    help_data->num_of_pg);
978         }
979 }
980
981
982 /*******************************************************************************
983  * Description: single priority group
984  *
985  * Return:
986  ******************************************************************************/
987 static void bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x *bp,
988                                                struct cos_help_data *cos_data,
989                                                u32 pri_join_mask)
990 {
991         /* Only one priority than only one COS */
992         cos_data->data[0].pausable =
993                 IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
994         cos_data->data[0].pri_join_mask = pri_join_mask;
995         cos_data->data[0].cos_bw = 100;
996         cos_data->num_of_cos = 1;
997 }
998
999 /*******************************************************************************
1000  * Description: updating the cos bw
1001  *
1002  * Return:
1003  ******************************************************************************/
1004 static inline void bnx2x_dcbx_add_to_cos_bw(struct bnx2x *bp,
1005                                             struct cos_entry_help_data *data,
1006                                             u8 pg_bw)
1007 {
1008         if (data->cos_bw == DCBX_INVALID_COS_BW)
1009                 data->cos_bw = pg_bw;
1010         else
1011                 data->cos_bw += pg_bw;
1012 }
1013
1014 /*******************************************************************************
1015  * Description: single priority group
1016  *
1017  * Return:
1018  ******************************************************************************/
1019 static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x *bp,
1020                         struct cos_help_data *cos_data,
1021                         u32 *pg_pri_orginal_spread,
1022                         struct dcbx_ets_feature *ets)
1023 {
1024         u32     pri_tested      = 0;
1025         u8      i               = 0;
1026         u8      entry           = 0;
1027         u8      pg_entry        = 0;
1028         u8      num_of_pri      = LLFC_DRIVER_TRAFFIC_TYPE_MAX;
1029
1030         cos_data->data[0].pausable = true;
1031         cos_data->data[1].pausable = false;
1032         cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
1033
1034         for (i = 0 ; i < num_of_pri ; i++) {
1035                 pri_tested = 1 << bp->dcbx_port_params.
1036                                         app.traffic_type_priority[i];
1037
1038                 if (pri_tested & DCBX_PFC_PRI_NON_PAUSE_MASK(bp)) {
1039                         cos_data->data[1].pri_join_mask |= pri_tested;
1040                         entry = 1;
1041                 } else {
1042                         cos_data->data[0].pri_join_mask |= pri_tested;
1043                         entry = 0;
1044                 }
1045                 pg_entry = (u8)pg_pri_orginal_spread[bp->dcbx_port_params.
1046                                                 app.traffic_type_priority[i]];
1047                 /* There can be only one strict pg */
1048                 if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES)
1049                         bnx2x_dcbx_add_to_cos_bw(bp, &cos_data->data[entry],
1050                                 DCBX_PG_BW_GET(ets->pg_bw_tbl, pg_entry));
1051                 else
1052                         /* If we join a group and one is strict
1053                          * than the bw rulls */
1054                         cos_data->data[entry].strict =
1055                                                 BNX2X_DCBX_COS_HIGH_STRICT;
1056         }
1057         if ((0 == cos_data->data[0].pri_join_mask) &&
1058             (0 == cos_data->data[1].pri_join_mask))
1059                 BNX2X_ERR("dcbx error: Both groups must have priorities\n");
1060 }
1061
1062
1063 #ifndef POWER_OF_2
1064 #define POWER_OF_2(x)   ((0 != x) && (0 == (x & (x-1))))
1065 #endif
1066
1067 static void bxn2x_dcbx_single_pg_to_cos_params(struct bnx2x *bp,
1068                                               struct pg_help_data *pg_help_data,
1069                                               struct cos_help_data *cos_data,
1070                                               u32 pri_join_mask,
1071                                               u8 num_of_dif_pri)
1072 {
1073         u8 i = 0;
1074         u32 pri_tested = 0;
1075         u32 pri_mask_without_pri = 0;
1076         u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
1077         /*debug*/
1078         if (num_of_dif_pri == 1) {
1079                 bnx2x_dcbx_ets_disabled_entry_data(bp, cos_data, pri_join_mask);
1080                 return;
1081         }
1082         /* single priority group */
1083         if (pg_help_data->data[0].pg < DCBX_MAX_NUM_PG_BW_ENTRIES) {
1084                 /* If there are both pauseable and non-pauseable priorities,
1085                  * the pauseable priorities go to the first queue and
1086                  * the non-pauseable priorities go to the second queue.
1087                  */
1088                 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
1089                         /* Pauseable */
1090                         cos_data->data[0].pausable = true;
1091                         /* Non pauseable.*/
1092                         cos_data->data[1].pausable = false;
1093
1094                         if (2 == num_of_dif_pri) {
1095                                 cos_data->data[0].cos_bw = 50;
1096                                 cos_data->data[1].cos_bw = 50;
1097                         }
1098
1099                         if (3 == num_of_dif_pri) {
1100                                 if (POWER_OF_2(DCBX_PFC_PRI_GET_PAUSE(bp,
1101                                                         pri_join_mask))) {
1102                                         cos_data->data[0].cos_bw = 33;
1103                                         cos_data->data[1].cos_bw = 67;
1104                                 } else {
1105                                         cos_data->data[0].cos_bw = 67;
1106                                         cos_data->data[1].cos_bw = 33;
1107                                 }
1108                         }
1109
1110                 } else if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask)) {
1111                         /* If there are only pauseable priorities,
1112                          * then one/two priorities go to the first queue
1113                          * and one priority goes to the second queue.
1114                          */
1115                         if (2 == num_of_dif_pri) {
1116                                 cos_data->data[0].cos_bw = 50;
1117                                 cos_data->data[1].cos_bw = 50;
1118                         } else {
1119                                 cos_data->data[0].cos_bw = 67;
1120                                 cos_data->data[1].cos_bw = 33;
1121                         }
1122                         cos_data->data[1].pausable = true;
1123                         cos_data->data[0].pausable = true;
1124                         /* All priorities except FCOE */
1125                         cos_data->data[0].pri_join_mask = (pri_join_mask &
1126                                 ((u8)~(1 << ttp[LLFC_TRAFFIC_TYPE_FCOE])));
1127                         /* Only FCOE priority.*/
1128                         cos_data->data[1].pri_join_mask =
1129                                 (1 << ttp[LLFC_TRAFFIC_TYPE_FCOE]);
1130                 } else
1131                         /* If there are only non-pauseable priorities,
1132                          * they will all go to the same queue.
1133                          */
1134                         bnx2x_dcbx_ets_disabled_entry_data(bp,
1135                                                 cos_data, pri_join_mask);
1136         } else {
1137                 /* priority group which is not BW limited (PG#15):*/
1138                 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
1139                         /* If there are both pauseable and non-pauseable
1140                          * priorities, the pauseable priorities go to the first
1141                          * queue and the non-pauseable priorities
1142                          * go to the second queue.
1143                          */
1144                         if (DCBX_PFC_PRI_GET_PAUSE(bp, pri_join_mask) >
1145                             DCBX_PFC_PRI_GET_NON_PAUSE(bp, pri_join_mask)) {
1146                                 cos_data->data[0].strict =
1147                                         BNX2X_DCBX_COS_HIGH_STRICT;
1148                                 cos_data->data[1].strict =
1149                                         BNX2X_DCBX_COS_LOW_STRICT;
1150                         } else {
1151                                 cos_data->data[0].strict =
1152                                         BNX2X_DCBX_COS_LOW_STRICT;
1153                                 cos_data->data[1].strict =
1154                                         BNX2X_DCBX_COS_HIGH_STRICT;
1155                         }
1156                         /* Pauseable */
1157                         cos_data->data[0].pausable = true;
1158                         /* Non pause-able.*/
1159                         cos_data->data[1].pausable = false;
1160                 } else {
1161                         /* If there are only pauseable priorities or
1162                          * only non-pauseable,* the lower priorities go
1163                          * to the first queue and the higherpriorities go
1164                          * to the second queue.
1165                          */
1166                         cos_data->data[0].pausable =
1167                                 cos_data->data[1].pausable =
1168                                 IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
1169
1170                         for (i = 0 ; i < LLFC_DRIVER_TRAFFIC_TYPE_MAX; i++) {
1171                                 pri_tested = 1 << bp->dcbx_port_params.
1172                                         app.traffic_type_priority[i];
1173                                 /* Remove priority tested */
1174                                 pri_mask_without_pri =
1175                                         (pri_join_mask & ((u8)(~pri_tested)));
1176                                 if (pri_mask_without_pri < pri_tested)
1177                                         break;
1178                         }
1179
1180                         if (i == LLFC_DRIVER_TRAFFIC_TYPE_MAX)
1181                                 BNX2X_ERR("Invalid value for pri_join_mask -"
1182                                           " could not find a priority\n");
1183
1184                         cos_data->data[0].pri_join_mask = pri_mask_without_pri;
1185                         cos_data->data[1].pri_join_mask = pri_tested;
1186                         /* Both queues are strict priority,
1187                          * and that with the highest priority
1188                          * gets the highest strict priority in the arbiter.
1189                          */
1190                         cos_data->data[0].strict = BNX2X_DCBX_COS_LOW_STRICT;
1191                         cos_data->data[1].strict = BNX2X_DCBX_COS_HIGH_STRICT;
1192                 }
1193         }
1194 }
1195
1196 static void bnx2x_dcbx_two_pg_to_cos_params(
1197                             struct bnx2x                *bp,
1198                             struct  pg_help_data        *pg_help_data,
1199                             struct dcbx_ets_feature     *ets,
1200                             struct cos_help_data        *cos_data,
1201                             u32                 *pg_pri_orginal_spread,
1202                             u32                         pri_join_mask,
1203                             u8                          num_of_dif_pri)
1204 {
1205         u8 i = 0;
1206         u8 pg[E2_NUM_OF_COS] = {0};
1207
1208         /* If there are both pauseable and non-pauseable priorities,
1209          * the pauseable priorities go to the first queue and
1210          * the non-pauseable priorities go to the second queue.
1211          */
1212         if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask)) {
1213                 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
1214                                          pg_help_data->data[0].pg_priority) ||
1215                     IS_DCBX_PFC_PRI_MIX_PAUSE(bp,
1216                                          pg_help_data->data[1].pg_priority)) {
1217                         /* If one PG contains both pauseable and
1218                          * non-pauseable priorities then ETS is disabled.
1219                          */
1220                         bnx2x_dcbx_separate_pauseable_from_non(bp, cos_data,
1221                                         pg_pri_orginal_spread, ets);
1222                         bp->dcbx_port_params.ets.enabled = false;
1223                         return;
1224                 }
1225
1226                 /* Pauseable */
1227                 cos_data->data[0].pausable = true;
1228                 /* Non pauseable. */
1229                 cos_data->data[1].pausable = false;
1230                 if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp,
1231                                 pg_help_data->data[0].pg_priority)) {
1232                         /* 0 is pauseable */
1233                         cos_data->data[0].pri_join_mask =
1234                                 pg_help_data->data[0].pg_priority;
1235                         pg[0] = pg_help_data->data[0].pg;
1236                         cos_data->data[1].pri_join_mask =
1237                                 pg_help_data->data[1].pg_priority;
1238                         pg[1] = pg_help_data->data[1].pg;
1239                 } else {/* 1 is pauseable */
1240                         cos_data->data[0].pri_join_mask =
1241                                 pg_help_data->data[1].pg_priority;
1242                         pg[0] = pg_help_data->data[1].pg;
1243                         cos_data->data[1].pri_join_mask =
1244                                 pg_help_data->data[0].pg_priority;
1245                         pg[1] = pg_help_data->data[0].pg;
1246                 }
1247         } else {
1248                 /* If there are only pauseable priorities or
1249                  * only non-pauseable, each PG goes to a queue.
1250                  */
1251                 cos_data->data[0].pausable = cos_data->data[1].pausable =
1252                         IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
1253                 cos_data->data[0].pri_join_mask =
1254                         pg_help_data->data[0].pg_priority;
1255                 pg[0] = pg_help_data->data[0].pg;
1256                 cos_data->data[1].pri_join_mask =
1257                         pg_help_data->data[1].pg_priority;
1258                 pg[1] = pg_help_data->data[1].pg;
1259         }
1260
1261         /* There can be only one strict pg */
1262         for (i = 0 ; i < E2_NUM_OF_COS; i++) {
1263                 if (pg[i] < DCBX_MAX_NUM_PG_BW_ENTRIES)
1264                         cos_data->data[i].cos_bw =
1265                                 DCBX_PG_BW_GET(ets->pg_bw_tbl, pg[i]);
1266                 else
1267                         cos_data->data[i].strict = BNX2X_DCBX_COS_HIGH_STRICT;
1268         }
1269 }
1270
1271 /*******************************************************************************
1272  * Description: Still
1273  *
1274  * Return:
1275  ******************************************************************************/
1276 static void bnx2x_dcbx_three_pg_to_cos_params(
1277                               struct bnx2x              *bp,
1278                               struct pg_help_data       *pg_help_data,
1279                               struct dcbx_ets_feature   *ets,
1280                               struct cos_help_data      *cos_data,
1281                               u32                       *pg_pri_orginal_spread,
1282                               u32                       pri_join_mask,
1283                               u8                        num_of_dif_pri)
1284 {
1285         u8 i = 0;
1286         u32 pri_tested = 0;
1287         u8 entry = 0;
1288         u8 pg_entry = 0;
1289         bool b_found_strict = false;
1290         u8 num_of_pri = LLFC_DRIVER_TRAFFIC_TYPE_MAX;
1291
1292         cos_data->data[0].pri_join_mask = cos_data->data[1].pri_join_mask = 0;
1293         /* If there are both pauseable and non-pauseable priorities,
1294          * the pauseable priorities go to the first queue and the
1295          * non-pauseable priorities go to the second queue.
1296          */
1297         if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp, pri_join_mask))
1298                 bnx2x_dcbx_separate_pauseable_from_non(bp,
1299                                 cos_data, pg_pri_orginal_spread, ets);
1300         else {
1301                 /* If two BW-limited PG-s were combined to one queue,
1302                  * the BW is their sum.
1303                  *
1304                  * If there are only pauseable priorities or only non-pauseable,
1305                  * and there are both BW-limited and non-BW-limited PG-s,
1306                  * the BW-limited PG/s go to one queue and the non-BW-limited
1307                  * PG/s go to the second queue.
1308                  *
1309                  * If there are only pauseable priorities or only non-pauseable
1310                  * and all are BW limited, then two priorities go to the first
1311                  * queue and one priority goes to the second queue.
1312                  *
1313                  * We will join this two cases:
1314                  * if one is BW limited it will go to the secoend queue
1315                  * otherwise the last priority will get it
1316                  */
1317
1318                 cos_data->data[0].pausable = cos_data->data[1].pausable =
1319                         IS_DCBX_PFC_PRI_ONLY_PAUSE(bp, pri_join_mask);
1320
1321                 for (i = 0 ; i < num_of_pri; i++) {
1322                         pri_tested = 1 << bp->dcbx_port_params.
1323                                 app.traffic_type_priority[i];
1324                         pg_entry = (u8)pg_pri_orginal_spread[bp->
1325                                 dcbx_port_params.app.traffic_type_priority[i]];
1326
1327                         if (pg_entry < DCBX_MAX_NUM_PG_BW_ENTRIES) {
1328                                 entry = 0;
1329
1330                                 if (i == (num_of_pri-1) &&
1331                                     false == b_found_strict)
1332                                         /* last entry will be handled separately
1333                                          * If no priority is strict than last
1334                                          * enty goes to last queue.*/
1335                                         entry = 1;
1336                                 cos_data->data[entry].pri_join_mask |=
1337                                                                 pri_tested;
1338                                 bnx2x_dcbx_add_to_cos_bw(bp,
1339                                         &cos_data->data[entry],
1340                                         DCBX_PG_BW_GET(ets->pg_bw_tbl,
1341                                                        pg_entry));
1342                         } else {
1343                                 b_found_strict = true;
1344                                 cos_data->data[1].pri_join_mask |= pri_tested;
1345                                 /* If we join a group and one is strict
1346                                  * than the bw rulls */
1347                                 cos_data->data[1].strict =
1348                                         BNX2X_DCBX_COS_HIGH_STRICT;
1349                         }
1350                 }
1351         }
1352 }
1353
1354
1355 static void bnx2x_dcbx_fill_cos_params(struct bnx2x *bp,
1356                                        struct pg_help_data *help_data,
1357                                        struct dcbx_ets_feature *ets,
1358                                        u32 *pg_pri_orginal_spread)
1359 {
1360         struct cos_help_data         cos_data ;
1361         u8                    i                           = 0;
1362         u32                   pri_join_mask               = 0;
1363         u8                    num_of_dif_pri              = 0;
1364
1365         memset(&cos_data, 0, sizeof(cos_data));
1366         /* Validate the pg value */
1367         for (i = 0; i < help_data->num_of_pg ; i++) {
1368                 if (DCBX_STRICT_PRIORITY != help_data->data[i].pg &&
1369                     DCBX_MAX_NUM_PG_BW_ENTRIES <= help_data->data[i].pg)
1370                         BNX2X_ERR("Invalid pg[%d] data %x\n", i,
1371                                   help_data->data[i].pg);
1372                 pri_join_mask   |=  help_data->data[i].pg_priority;
1373                 num_of_dif_pri  += help_data->data[i].num_of_dif_pri;
1374         }
1375
1376         /* default settings */
1377         cos_data.num_of_cos = 2;
1378         for (i = 0; i < E2_NUM_OF_COS ; i++) {
1379                 cos_data.data[i].pri_join_mask    = pri_join_mask;
1380                 cos_data.data[i].pausable         = false;
1381                 cos_data.data[i].strict           = BNX2X_DCBX_COS_NOT_STRICT;
1382                 cos_data.data[i].cos_bw           = DCBX_INVALID_COS_BW;
1383         }
1384
1385         switch (help_data->num_of_pg) {
1386         case 1:
1387
1388                 bxn2x_dcbx_single_pg_to_cos_params(
1389                                                bp,
1390                                                help_data,
1391                                                &cos_data,
1392                                                pri_join_mask,
1393                                                num_of_dif_pri);
1394                 break;
1395         case 2:
1396                 bnx2x_dcbx_two_pg_to_cos_params(
1397                                             bp,
1398                                             help_data,
1399                                             ets,
1400                                             &cos_data,
1401                                             pg_pri_orginal_spread,
1402                                             pri_join_mask,
1403                                             num_of_dif_pri);
1404                 break;
1405
1406         case 3:
1407                 bnx2x_dcbx_three_pg_to_cos_params(
1408                                               bp,
1409                                               help_data,
1410                                               ets,
1411                                               &cos_data,
1412                                               pg_pri_orginal_spread,
1413                                               pri_join_mask,
1414                                               num_of_dif_pri);
1415
1416                 break;
1417         default:
1418                 BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
1419                 bnx2x_dcbx_ets_disabled_entry_data(bp,
1420                                                    &cos_data, pri_join_mask);
1421         }
1422
1423         for (i = 0; i < cos_data.num_of_cos ; i++) {
1424                 struct bnx2x_dcbx_cos_params *params =
1425                         &bp->dcbx_port_params.ets.cos_params[i];
1426
1427                 params->pauseable = cos_data.data[i].pausable;
1428                 params->strict = cos_data.data[i].strict;
1429                 params->bw_tbl = cos_data.data[i].cos_bw;
1430                 if (params->pauseable) {
1431                         params->pri_bitmask =
1432                         DCBX_PFC_PRI_GET_PAUSE(bp,
1433                                         cos_data.data[i].pri_join_mask);
1434                         DP(NETIF_MSG_LINK, "COS %d PAUSABLE prijoinmask 0x%x\n",
1435                                   i, cos_data.data[i].pri_join_mask);
1436                 } else {
1437                         params->pri_bitmask =
1438                         DCBX_PFC_PRI_GET_NON_PAUSE(bp,
1439                                         cos_data.data[i].pri_join_mask);
1440                         DP(NETIF_MSG_LINK, "COS %d NONPAUSABLE prijoinmask "
1441                                           "0x%x\n",
1442                                   i, cos_data.data[i].pri_join_mask);
1443                 }
1444         }
1445
1446         bp->dcbx_port_params.ets.num_of_cos = cos_data.num_of_cos ;
1447 }
1448
1449 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
1450                                 u32 *set_configuration_ets_pg,
1451                                 u32 *pri_pg_tbl)
1452 {
1453         int i;
1454
1455         for (i = 0; i < DCBX_MAX_NUM_PRI_PG_ENTRIES; i++) {
1456                 set_configuration_ets_pg[i] = DCBX_PRI_PG_GET(pri_pg_tbl, i);
1457
1458                 DP(NETIF_MSG_LINK, "set_configuration_ets_pg[%d] = 0x%x\n",
1459                    i, set_configuration_ets_pg[i]);
1460         }
1461 }
1462
1463 /*******************************************************************************
1464  * Description: Fill pfc_config struct that will be sent in DCBX start ramrod
1465  *
1466  * Return:
1467  ******************************************************************************/
1468 static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
1469 {
1470         struct flow_control_configuration   *pfc_fw_cfg = NULL;
1471         u16 pri_bit = 0;
1472         u8 cos = 0, pri = 0;
1473         struct priority_cos *tt2cos;
1474         u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
1475
1476         pfc_fw_cfg = (struct flow_control_configuration *)
1477                                         bnx2x_sp(bp, pfc_config);
1478         memset(pfc_fw_cfg, 0, sizeof(struct flow_control_configuration));
1479
1480         /*shortcut*/
1481         tt2cos = pfc_fw_cfg->traffic_type_to_priority_cos;
1482
1483         /* Fw version should be incremented each update */
1484         pfc_fw_cfg->dcb_version = ++bp->dcb_version;
1485         pfc_fw_cfg->dcb_enabled = DCB_ENABLED;
1486
1487         /* Default initialization */
1488         for (pri = 0; pri < MAX_PFC_TRAFFIC_TYPES ; pri++) {
1489                 tt2cos[pri].priority = LLFC_TRAFFIC_TYPE_TO_PRIORITY_UNMAPPED;
1490                 tt2cos[pri].cos = 0;
1491         }
1492
1493         /* Fill priority parameters */
1494         for (pri = 0; pri < LLFC_DRIVER_TRAFFIC_TYPE_MAX; pri++) {
1495                 tt2cos[pri].priority = ttp[pri];
1496                 pri_bit = 1 << tt2cos[pri].priority;
1497
1498                 /* Fill COS parameters based on COS calculated to
1499                  * make it more generally for future use */
1500                 for (cos = 0; cos < bp->dcbx_port_params.ets.num_of_cos; cos++)
1501                         if (bp->dcbx_port_params.ets.cos_params[cos].
1502                                                 pri_bitmask & pri_bit)
1503                                         tt2cos[pri].cos = cos;
1504         }
1505         bnx2x_dcbx_print_cos_params(bp, pfc_fw_cfg);
1506 }
1507 /* DCB netlink */
1508 #ifdef BCM_DCB
1509 #include <linux/dcbnl.h>
1510
1511 #define BNX2X_DCBX_CAPS         (DCB_CAP_DCBX_LLD_MANAGED | \
1512                                 DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
1513
1514 static inline bool bnx2x_dcbnl_set_valid(struct bnx2x *bp)
1515 {
1516         /* validate dcbnl call that may change HW state:
1517          * DCB is on and DCBX mode was SUCCESSFULLY set by the user.
1518          */
1519         return bp->dcb_state && bp->dcbx_mode_uset;
1520 }
1521
1522 static u8 bnx2x_dcbnl_get_state(struct net_device *netdev)
1523 {
1524         struct bnx2x *bp = netdev_priv(netdev);
1525         DP(NETIF_MSG_LINK, "state = %d\n", bp->dcb_state);
1526         return bp->dcb_state;
1527 }
1528
1529 static u8 bnx2x_dcbnl_set_state(struct net_device *netdev, u8 state)
1530 {
1531         struct bnx2x *bp = netdev_priv(netdev);
1532         DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
1533
1534         bnx2x_dcbx_set_state(bp, (state ? true : false), bp->dcbx_enabled);
1535         return 0;
1536 }
1537
1538 static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
1539                                          u8 *perm_addr)
1540 {
1541         struct bnx2x *bp = netdev_priv(netdev);
1542         DP(NETIF_MSG_LINK, "GET-PERM-ADDR\n");
1543
1544         /* first the HW mac address */
1545         memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
1546
1547 #ifdef BCM_CNIC
1548         /* second SAN address */
1549         memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len);
1550 #endif
1551 }
1552
1553 static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
1554                                         u8 prio_type, u8 pgid, u8 bw_pct,
1555                                         u8 up_map)
1556 {
1557         struct bnx2x *bp = netdev_priv(netdev);
1558
1559         DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, pgid);
1560         if (!bnx2x_dcbnl_set_valid(bp) || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
1561                 return;
1562
1563         /**
1564          * bw_pct ingnored -    band-width percentage devision between user
1565          *                      priorities within the same group is not
1566          *                      standard and hence not supported
1567          *
1568          * prio_type igonred -  priority levels within the same group are not
1569          *                      standard and hence are not supported. According
1570          *                      to the standard pgid 15 is dedicated to strict
1571          *                      prioirty traffic (on the port level).
1572          *
1573          * up_map ignored
1574          */
1575
1576         bp->dcbx_config_params.admin_configuration_ets_pg[prio] = pgid;
1577         bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
1578 }
1579
1580 static void bnx2x_dcbnl_set_pg_bwgcfg_tx(struct net_device *netdev,
1581                                          int pgid, u8 bw_pct)
1582 {
1583         struct bnx2x *bp = netdev_priv(netdev);
1584         DP(NETIF_MSG_LINK, "pgid[%d] = %d\n", pgid, bw_pct);
1585
1586         if (!bnx2x_dcbnl_set_valid(bp) || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
1587                 return;
1588
1589         bp->dcbx_config_params.admin_configuration_bw_precentage[pgid] = bw_pct;
1590         bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
1591 }
1592
1593 static void bnx2x_dcbnl_set_pg_tccfg_rx(struct net_device *netdev, int prio,
1594                                         u8 prio_type, u8 pgid, u8 bw_pct,
1595                                         u8 up_map)
1596 {
1597         struct bnx2x *bp = netdev_priv(netdev);
1598         DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
1599 }
1600
1601 static void bnx2x_dcbnl_set_pg_bwgcfg_rx(struct net_device *netdev,
1602                                          int pgid, u8 bw_pct)
1603 {
1604         struct bnx2x *bp = netdev_priv(netdev);
1605         DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
1606 }
1607
1608 static void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device *netdev, int prio,
1609                                         u8 *prio_type, u8 *pgid, u8 *bw_pct,
1610                                         u8 *up_map)
1611 {
1612         struct bnx2x *bp = netdev_priv(netdev);
1613         DP(NETIF_MSG_LINK, "prio = %d\n", prio);
1614
1615         /**
1616          * bw_pct ingnored -    band-width percentage devision between user
1617          *                      priorities within the same group is not
1618          *                      standard and hence not supported
1619          *
1620          * prio_type igonred -  priority levels within the same group are not
1621          *                      standard and hence are not supported. According
1622          *                      to the standard pgid 15 is dedicated to strict
1623          *                      prioirty traffic (on the port level).
1624          *
1625          * up_map ignored
1626          */
1627         *up_map = *bw_pct = *prio_type = *pgid = 0;
1628
1629         if (!bp->dcb_state || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
1630                 return;
1631
1632         *pgid = DCBX_PRI_PG_GET(bp->dcbx_local_feat.ets.pri_pg_tbl, prio);
1633 }
1634
1635 static void bnx2x_dcbnl_get_pg_bwgcfg_tx(struct net_device *netdev,
1636                                          int pgid, u8 *bw_pct)
1637 {
1638         struct bnx2x *bp = netdev_priv(netdev);
1639         DP(NETIF_MSG_LINK, "pgid = %d\n", pgid);
1640
1641         *bw_pct = 0;
1642
1643         if (!bp->dcb_state || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
1644                 return;
1645
1646         *bw_pct = DCBX_PG_BW_GET(bp->dcbx_local_feat.ets.pg_bw_tbl, pgid);
1647 }
1648
1649 static void bnx2x_dcbnl_get_pg_tccfg_rx(struct net_device *netdev, int prio,
1650                                         u8 *prio_type, u8 *pgid, u8 *bw_pct,
1651                                         u8 *up_map)
1652 {
1653         struct bnx2x *bp = netdev_priv(netdev);
1654         DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
1655
1656         *prio_type = *pgid = *bw_pct = *up_map = 0;
1657 }
1658
1659 static void bnx2x_dcbnl_get_pg_bwgcfg_rx(struct net_device *netdev,
1660                                          int pgid, u8 *bw_pct)
1661 {
1662         struct bnx2x *bp = netdev_priv(netdev);
1663         DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
1664
1665         *bw_pct = 0;
1666 }
1667
1668 static void bnx2x_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,
1669                                     u8 setting)
1670 {
1671         struct bnx2x *bp = netdev_priv(netdev);
1672         DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, setting);
1673
1674         if (!bnx2x_dcbnl_set_valid(bp) || prio >= MAX_PFC_PRIORITIES)
1675                 return;
1676
1677         bp->dcbx_config_params.admin_pfc_bitmap |= ((setting ? 1 : 0) << prio);
1678
1679         if (setting)
1680                 bp->dcbx_config_params.admin_pfc_tx_enable = 1;
1681 }
1682
1683 static void bnx2x_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,
1684                                     u8 *setting)
1685 {
1686         struct bnx2x *bp = netdev_priv(netdev);
1687         DP(NETIF_MSG_LINK, "prio = %d\n", prio);
1688
1689         *setting = 0;
1690
1691         if (!bp->dcb_state || prio >= MAX_PFC_PRIORITIES)
1692                 return;
1693
1694         *setting = (bp->dcbx_local_feat.pfc.pri_en_bitmap >> prio) & 0x1;
1695 }
1696
1697 static u8 bnx2x_dcbnl_set_all(struct net_device *netdev)
1698 {
1699         struct bnx2x *bp = netdev_priv(netdev);
1700         int rc = 0;
1701
1702         DP(NETIF_MSG_LINK, "SET-ALL\n");
1703
1704         if (!bnx2x_dcbnl_set_valid(bp))
1705                 return 1;
1706
1707         if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
1708                 netdev_err(bp->dev, "Handling parity error recovery. "
1709                                 "Try again later\n");
1710                 return 1;
1711         }
1712         if (netif_running(bp->dev)) {
1713                 bnx2x_nic_unload(bp, UNLOAD_NORMAL);
1714                 rc = bnx2x_nic_load(bp, LOAD_NORMAL);
1715         }
1716         DP(NETIF_MSG_LINK, "set_dcbx_params done (%d)\n", rc);
1717         if (rc)
1718                 return 1;
1719
1720         return 0;
1721 }
1722
1723 static u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)
1724 {
1725         struct bnx2x *bp = netdev_priv(netdev);
1726         u8 rval = 0;
1727
1728         if (bp->dcb_state) {
1729                 switch (capid) {
1730                 case DCB_CAP_ATTR_PG:
1731                         *cap = true;
1732                         break;
1733                 case DCB_CAP_ATTR_PFC:
1734                         *cap = true;
1735                         break;
1736                 case DCB_CAP_ATTR_UP2TC:
1737                         *cap = false;
1738                         break;
1739                 case DCB_CAP_ATTR_PG_TCS:
1740                         *cap = 0x80;    /* 8 priorities for PGs */
1741                         break;
1742                 case DCB_CAP_ATTR_PFC_TCS:
1743                         *cap = 0x80;    /* 8 priorities for PFC */
1744                         break;
1745                 case DCB_CAP_ATTR_GSP:
1746                         *cap = true;
1747                         break;
1748                 case DCB_CAP_ATTR_BCN:
1749                         *cap = false;
1750                         break;
1751                 case DCB_CAP_ATTR_DCBX:
1752                         *cap = BNX2X_DCBX_CAPS;
1753                 default:
1754                         rval = -EINVAL;
1755                         break;
1756                 }
1757         } else
1758                 rval = -EINVAL;
1759
1760         DP(NETIF_MSG_LINK, "capid %d:%x\n", capid, *cap);
1761         return rval;
1762 }
1763
1764 static u8 bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)
1765 {
1766         struct bnx2x *bp = netdev_priv(netdev);
1767         u8 rval = 0;
1768
1769         DP(NETIF_MSG_LINK, "tcid %d\n", tcid);
1770
1771         if (bp->dcb_state) {
1772                 switch (tcid) {
1773                 case DCB_NUMTCS_ATTR_PG:
1774                         *num = E2_NUM_OF_COS;
1775                         break;
1776                 case DCB_NUMTCS_ATTR_PFC:
1777                         *num = E2_NUM_OF_COS;
1778                         break;
1779                 default:
1780                         rval = -EINVAL;
1781                         break;
1782                 }
1783         } else
1784                 rval = -EINVAL;
1785
1786         return rval;
1787 }
1788
1789 static u8 bnx2x_dcbnl_set_numtcs(struct net_device *netdev, int tcid, u8 num)
1790 {
1791         struct bnx2x *bp = netdev_priv(netdev);
1792         DP(NETIF_MSG_LINK, "num tcs = %d; Not supported\n", num);
1793         return -EINVAL;
1794 }
1795
1796 static u8  bnx2x_dcbnl_get_pfc_state(struct net_device *netdev)
1797 {
1798         struct bnx2x *bp = netdev_priv(netdev);
1799         DP(NETIF_MSG_LINK, "state = %d\n", bp->dcbx_local_feat.pfc.enabled);
1800
1801         if (!bp->dcb_state)
1802                 return 0;
1803
1804         return bp->dcbx_local_feat.pfc.enabled;
1805 }
1806
1807 static void bnx2x_dcbnl_set_pfc_state(struct net_device *netdev, u8 state)
1808 {
1809         struct bnx2x *bp = netdev_priv(netdev);
1810         DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
1811
1812         if (!bnx2x_dcbnl_set_valid(bp))
1813                 return;
1814
1815         bp->dcbx_config_params.admin_pfc_tx_enable =
1816         bp->dcbx_config_params.admin_pfc_enable = (state ? 1 : 0);
1817 }
1818
1819 static bool bnx2x_app_is_equal(struct dcbx_app_priority_entry *app_ent,
1820                                u8 idtype, u16 idval)
1821 {
1822         if (!(app_ent->appBitfield & DCBX_APP_ENTRY_VALID))
1823                 return false;
1824
1825         switch (idtype) {
1826         case DCB_APP_IDTYPE_ETHTYPE:
1827                 if ((app_ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) !=
1828                         DCBX_APP_SF_ETH_TYPE)
1829                         return false;
1830                 break;
1831         case DCB_APP_IDTYPE_PORTNUM:
1832                 if ((app_ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) !=
1833                         DCBX_APP_SF_PORT)
1834                         return false;
1835                 break;
1836         default:
1837                 return false;
1838         }
1839         if (app_ent->app_id != idval)
1840                 return false;
1841
1842         return true;
1843 }
1844
1845 static void bnx2x_admin_app_set_ent(
1846         struct bnx2x_admin_priority_app_table *app_ent,
1847         u8 idtype, u16 idval, u8 up)
1848 {
1849         app_ent->valid = 1;
1850
1851         switch (idtype) {
1852         case DCB_APP_IDTYPE_ETHTYPE:
1853                 app_ent->traffic_type = TRAFFIC_TYPE_ETH;
1854                 break;
1855         case DCB_APP_IDTYPE_PORTNUM:
1856                 app_ent->traffic_type = TRAFFIC_TYPE_PORT;
1857                 break;
1858         default:
1859                 break; /* never gets here */
1860         }
1861         app_ent->app_id = idval;
1862         app_ent->priority = up;
1863 }
1864
1865 static bool bnx2x_admin_app_is_equal(
1866         struct bnx2x_admin_priority_app_table *app_ent,
1867         u8 idtype, u16 idval)
1868 {
1869         if (!app_ent->valid)
1870                 return false;
1871
1872         switch (idtype) {
1873         case DCB_APP_IDTYPE_ETHTYPE:
1874                 if (app_ent->traffic_type != TRAFFIC_TYPE_ETH)
1875                         return false;
1876                 break;
1877         case DCB_APP_IDTYPE_PORTNUM:
1878                 if (app_ent->traffic_type != TRAFFIC_TYPE_PORT)
1879                         return false;
1880                 break;
1881         default:
1882                 return false;
1883         }
1884         if (app_ent->app_id != idval)
1885                 return false;
1886
1887         return true;
1888 }
1889
1890 static int bnx2x_set_admin_app_up(struct bnx2x *bp, u8 idtype, u16 idval, u8 up)
1891 {
1892         int i, ff;
1893
1894         /* iterate over the app entries looking for idtype and idval */
1895         for (i = 0, ff = -1; i < 4; i++) {
1896                 struct bnx2x_admin_priority_app_table *app_ent =
1897                         &bp->dcbx_config_params.admin_priority_app_table[i];
1898                 if (bnx2x_admin_app_is_equal(app_ent, idtype, idval))
1899                         break;
1900
1901                 if (ff < 0 && !app_ent->valid)
1902                         ff = i;
1903         }
1904         if (i < 4)
1905                 /* if found overwrite up */
1906                 bp->dcbx_config_params.
1907                         admin_priority_app_table[i].priority = up;
1908         else if (ff >= 0)
1909                 /* not found use first-free */
1910                 bnx2x_admin_app_set_ent(
1911                         &bp->dcbx_config_params.admin_priority_app_table[ff],
1912                         idtype, idval, up);
1913         else
1914                 /* app table is full */
1915                 return -EBUSY;
1916
1917         /* up configured, if not 0 make sure feature is enabled */
1918         if (up)
1919                 bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
1920
1921         return 0;
1922 }
1923
1924 static u8 bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
1925                                  u16 idval, u8 up)
1926 {
1927         struct bnx2x *bp = netdev_priv(netdev);
1928
1929         DP(NETIF_MSG_LINK, "app_type %d, app_id %x, prio bitmap %d\n",
1930            idtype, idval, up);
1931
1932         if (!bnx2x_dcbnl_set_valid(bp))
1933                 return -EINVAL;
1934
1935         /* verify idtype */
1936         switch (idtype) {
1937         case DCB_APP_IDTYPE_ETHTYPE:
1938         case DCB_APP_IDTYPE_PORTNUM:
1939                 break;
1940         default:
1941                 return -EINVAL;
1942         }
1943         return bnx2x_set_admin_app_up(bp, idtype, idval, up);
1944 }
1945
1946 static u8 bnx2x_dcbnl_get_app_up(struct net_device *netdev, u8 idtype,
1947                                  u16 idval)
1948 {
1949         int i;
1950         u8 up = 0;
1951
1952         struct bnx2x *bp = netdev_priv(netdev);
1953         DP(NETIF_MSG_LINK, "app_type %d, app_id 0x%x\n", idtype, idval);
1954
1955         /* iterate over the app entries looking for idtype and idval */
1956         for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
1957                 if (bnx2x_app_is_equal(&bp->dcbx_local_feat.app.app_pri_tbl[i],
1958                                        idtype, idval))
1959                         break;
1960
1961         if (i < DCBX_MAX_APP_PROTOCOL)
1962                 /* if found return up */
1963                 up = bp->dcbx_local_feat.app.app_pri_tbl[i].pri_bitmap;
1964         else
1965                 DP(NETIF_MSG_LINK, "app not found\n");
1966
1967         return up;
1968 }
1969
1970 static u8 bnx2x_dcbnl_get_dcbx(struct net_device *netdev)
1971 {
1972         struct bnx2x *bp = netdev_priv(netdev);
1973         u8 state;
1974
1975         state = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_CEE;
1976
1977         if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF)
1978                 state |= DCB_CAP_DCBX_STATIC;
1979
1980         return state;
1981 }
1982
1983 static u8 bnx2x_dcbnl_set_dcbx(struct net_device *netdev, u8 state)
1984 {
1985         struct bnx2x *bp = netdev_priv(netdev);
1986         DP(NETIF_MSG_LINK, "state = %02x\n", state);
1987
1988         /* set dcbx mode */
1989
1990         if ((state & BNX2X_DCBX_CAPS) != state) {
1991                 BNX2X_ERR("Requested DCBX mode %x is beyond advertised "
1992                           "capabilities\n", state);
1993                 return 1;
1994         }
1995
1996         if (bp->dcb_state != BNX2X_DCB_STATE_ON) {
1997                 BNX2X_ERR("DCB turned off, DCBX configuration is invalid\n");
1998                 return 1;
1999         }
2000
2001         if (state & DCB_CAP_DCBX_STATIC)
2002                 bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_OFF;
2003         else
2004                 bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_ON;
2005
2006         bp->dcbx_mode_uset = true;
2007         return 0;
2008 }
2009
2010
2011 static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
2012                                   u8 *flags)
2013 {
2014         struct bnx2x *bp = netdev_priv(netdev);
2015         u8 rval = 0;
2016
2017         DP(NETIF_MSG_LINK, "featid %d\n", featid);
2018
2019         if (bp->dcb_state) {
2020                 *flags = 0;
2021                 switch (featid) {
2022                 case DCB_FEATCFG_ATTR_PG:
2023                         if (bp->dcbx_local_feat.ets.enabled)
2024                                 *flags |= DCB_FEATCFG_ENABLE;
2025                         if (bp->dcbx_error & DCBX_LOCAL_ETS_ERROR)
2026                                 *flags |= DCB_FEATCFG_ERROR;
2027                         break;
2028                 case DCB_FEATCFG_ATTR_PFC:
2029                         if (bp->dcbx_local_feat.pfc.enabled)
2030                                 *flags |= DCB_FEATCFG_ENABLE;
2031                         if (bp->dcbx_error & (DCBX_LOCAL_PFC_ERROR |
2032                             DCBX_LOCAL_PFC_MISMATCH))
2033                                 *flags |= DCB_FEATCFG_ERROR;
2034                         break;
2035                 case DCB_FEATCFG_ATTR_APP:
2036                         if (bp->dcbx_local_feat.app.enabled)
2037                                 *flags |= DCB_FEATCFG_ENABLE;
2038                         if (bp->dcbx_error & (DCBX_LOCAL_APP_ERROR |
2039                             DCBX_LOCAL_APP_MISMATCH))
2040                                 *flags |= DCB_FEATCFG_ERROR;
2041                         break;
2042                 default:
2043                         rval = -EINVAL;
2044                         break;
2045                 }
2046         } else
2047                 rval = -EINVAL;
2048
2049         return rval;
2050 }
2051
2052 static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid,
2053                                   u8 flags)
2054 {
2055         struct bnx2x *bp = netdev_priv(netdev);
2056         u8 rval = 0;
2057
2058         DP(NETIF_MSG_LINK, "featid = %d flags = %02x\n", featid, flags);
2059
2060         /* ignore the 'advertise' flag */
2061         if (bnx2x_dcbnl_set_valid(bp)) {
2062                 switch (featid) {
2063                 case DCB_FEATCFG_ATTR_PG:
2064                         bp->dcbx_config_params.admin_ets_enable =
2065                                 flags & DCB_FEATCFG_ENABLE ? 1 : 0;
2066                         bp->dcbx_config_params.admin_ets_willing =
2067                                 flags & DCB_FEATCFG_WILLING ? 1 : 0;
2068                         break;
2069                 case DCB_FEATCFG_ATTR_PFC:
2070                         bp->dcbx_config_params.admin_pfc_enable =
2071                                 flags & DCB_FEATCFG_ENABLE ? 1 : 0;
2072                         bp->dcbx_config_params.admin_pfc_willing =
2073                                 flags & DCB_FEATCFG_WILLING ? 1 : 0;
2074                         break;
2075                 case DCB_FEATCFG_ATTR_APP:
2076                         /* ignore enable, always enabled */
2077                         bp->dcbx_config_params.admin_app_priority_willing =
2078                                 flags & DCB_FEATCFG_WILLING ? 1 : 0;
2079                         break;
2080                 default:
2081                         rval = -EINVAL;
2082                         break;
2083                 }
2084         } else
2085                 rval = -EINVAL;
2086
2087         return rval;
2088 }
2089
2090 const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops = {
2091         .getstate       = bnx2x_dcbnl_get_state,
2092         .setstate       = bnx2x_dcbnl_set_state,
2093         .getpermhwaddr  = bnx2x_dcbnl_get_perm_hw_addr,
2094         .setpgtccfgtx   = bnx2x_dcbnl_set_pg_tccfg_tx,
2095         .setpgbwgcfgtx  = bnx2x_dcbnl_set_pg_bwgcfg_tx,
2096         .setpgtccfgrx   = bnx2x_dcbnl_set_pg_tccfg_rx,
2097         .setpgbwgcfgrx  = bnx2x_dcbnl_set_pg_bwgcfg_rx,
2098         .getpgtccfgtx   = bnx2x_dcbnl_get_pg_tccfg_tx,
2099         .getpgbwgcfgtx  = bnx2x_dcbnl_get_pg_bwgcfg_tx,
2100         .getpgtccfgrx   = bnx2x_dcbnl_get_pg_tccfg_rx,
2101         .getpgbwgcfgrx  = bnx2x_dcbnl_get_pg_bwgcfg_rx,
2102         .setpfccfg      = bnx2x_dcbnl_set_pfc_cfg,
2103         .getpfccfg      = bnx2x_dcbnl_get_pfc_cfg,
2104         .setall         = bnx2x_dcbnl_set_all,
2105         .getcap         = bnx2x_dcbnl_get_cap,
2106         .getnumtcs      = bnx2x_dcbnl_get_numtcs,
2107         .setnumtcs      = bnx2x_dcbnl_set_numtcs,
2108         .getpfcstate    = bnx2x_dcbnl_get_pfc_state,
2109         .setpfcstate    = bnx2x_dcbnl_set_pfc_state,
2110         .getapp         = bnx2x_dcbnl_get_app_up,
2111         .setapp         = bnx2x_dcbnl_set_app_up,
2112         .getdcbx        = bnx2x_dcbnl_get_dcbx,
2113         .setdcbx        = bnx2x_dcbnl_set_dcbx,
2114         .getfeatcfg     = bnx2x_dcbnl_get_featcfg,
2115         .setfeatcfg     = bnx2x_dcbnl_set_featcfg,
2116 };
2117
2118 #endif /* BCM_DCB */