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