1 /* bnx2x_dcb.c: Broadcom Everest network driver.
3 * Copyright 2009-2013 Broadcom Corporation
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").
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
15 * Maintained by: Eilon Greenstein <eilong@broadcom.com>
16 * Written by: Dmitry Kravkov
20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22 #include <linux/netdevice.h>
23 #include <linux/types.h>
24 #include <linux/errno.h>
25 #include <linux/rtnetlink.h>
26 #include <net/dcbnl.h>
29 #include "bnx2x_cmn.h"
30 #include "bnx2x_dcb.h"
32 /* forward declarations of dcbx related functions */
33 static void bnx2x_pfc_set_pfc(struct bnx2x
*bp
);
34 static void bnx2x_dcbx_update_ets_params(struct bnx2x
*bp
);
35 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x
*bp
,
36 u32
*set_configuration_ets_pg
,
38 static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x
*bp
,
39 u32
*pg_pri_orginal_spread
,
40 struct pg_help_data
*help_data
);
41 static void bnx2x_dcbx_fill_cos_params(struct bnx2x
*bp
,
42 struct pg_help_data
*help_data
,
43 struct dcbx_ets_feature
*ets
,
44 u32
*pg_pri_orginal_spread
);
45 static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x
*bp
,
46 struct cos_help_data
*cos_data
,
47 u32
*pg_pri_orginal_spread
,
48 struct dcbx_ets_feature
*ets
);
49 static void bnx2x_dcbx_fw_struct(struct bnx2x
*bp
,
50 struct bnx2x_func_tx_start_params
*);
52 /* helpers: read/write len bytes from addr into buff by REG_RD/REG_WR */
53 static void bnx2x_read_data(struct bnx2x
*bp
, u32
*buff
,
57 for (i
= 0; i
< len
; i
+= 4, buff
++)
58 *buff
= REG_RD(bp
, addr
+ i
);
61 static void bnx2x_write_data(struct bnx2x
*bp
, u32
*buff
,
65 for (i
= 0; i
< len
; i
+= 4, buff
++)
66 REG_WR(bp
, addr
+ i
, *buff
);
69 static void bnx2x_pfc_set(struct bnx2x
*bp
)
71 struct bnx2x_nig_brb_pfc_port_params pfc_params
= {0};
75 pfc_params
.num_of_rx_cos_priority_mask
=
76 bp
->dcbx_port_params
.ets
.num_of_cos
;
78 /* Tx COS configuration */
79 for (i
= 0; i
< bp
->dcbx_port_params
.ets
.num_of_cos
; i
++)
81 * We configure only the pauseable bits (non pauseable aren't
82 * configured at all) it's done to avoid false pauses from
85 pfc_params
.rx_cos_priority_mask
[i
] =
86 bp
->dcbx_port_params
.ets
.cos_params
[i
].pri_bitmask
87 & DCBX_PFC_PRI_PAUSE_MASK(bp
);
90 * Rx COS configuration
91 * Changing PFC RX configuration .
92 * In RX COS0 will always be configured to lossless and COS1 to lossy
94 for (i
= 0 ; i
< MAX_PFC_PRIORITIES
; i
++) {
97 if (!(pri_bit
& DCBX_PFC_PRI_PAUSE_MASK(bp
)))
101 pfc_params
.pkt_priority_to_cos
= val
;
104 pfc_params
.llfc_low_priority_classes
= DCBX_PFC_PRI_PAUSE_MASK(bp
);
106 pfc_params
.llfc_high_priority_classes
= 0;
108 bnx2x_acquire_phy_lock(bp
);
109 bp
->link_params
.feature_config_flags
|= FEATURE_CONFIG_PFC_ENABLED
;
110 bnx2x_update_pfc(&bp
->link_params
, &bp
->link_vars
, &pfc_params
);
111 bnx2x_release_phy_lock(bp
);
114 static void bnx2x_pfc_clear(struct bnx2x
*bp
)
116 struct bnx2x_nig_brb_pfc_port_params nig_params
= {0};
117 nig_params
.pause_enable
= 1;
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
);
124 static void bnx2x_dump_dcbx_drv_param(struct bnx2x
*bp
,
125 struct dcbx_features
*features
,
129 DP(NETIF_MSG_LINK
, "local_mib.error %x\n", error
);
133 "local_mib.features.ets.enabled %x\n", features
->ets
.enabled
);
134 for (i
= 0; i
< DCBX_MAX_NUM_PG_BW_ENTRIES
; i
++)
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
++)
140 "local_mib.features.ets.pri_pg_tbl[%d] %d\n", i
,
141 DCBX_PRI_PG_GET(features
->ets
.pri_pg_tbl
, i
));
144 DP(BNX2X_MSG_DCB
, "dcbx_features.pfc.pri_en_bitmap %x\n",
145 features
->pfc
.pri_en_bitmap
);
146 DP(BNX2X_MSG_DCB
, "dcbx_features.pfc.pfc_caps %x\n",
147 features
->pfc
.pfc_caps
);
148 DP(BNX2X_MSG_DCB
, "dcbx_features.pfc.enabled %x\n",
149 features
->pfc
.enabled
);
151 DP(BNX2X_MSG_DCB
, "dcbx_features.app.default_pri %x\n",
152 features
->app
.default_pri
);
153 DP(BNX2X_MSG_DCB
, "dcbx_features.app.tc_supported %x\n",
154 features
->app
.tc_supported
);
155 DP(BNX2X_MSG_DCB
, "dcbx_features.app.enabled %x\n",
156 features
->app
.enabled
);
157 for (i
= 0; i
< DCBX_MAX_APP_PROTOCOL
; i
++) {
159 "dcbx_features.app.app_pri_tbl[%x].app_id %x\n",
160 i
, features
->app
.app_pri_tbl
[i
].app_id
);
162 "dcbx_features.app.app_pri_tbl[%x].pri_bitmap %x\n",
163 i
, features
->app
.app_pri_tbl
[i
].pri_bitmap
);
165 "dcbx_features.app.app_pri_tbl[%x].appBitfield %x\n",
166 i
, features
->app
.app_pri_tbl
[i
].appBitfield
);
170 static void bnx2x_dcbx_get_ap_priority(struct bnx2x
*bp
,
174 u32 pri
= MAX_PFC_PRIORITIES
;
175 u32 index
= MAX_PFC_PRIORITIES
- 1;
177 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
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
))
187 if (pri
< MAX_PFC_PRIORITIES
)
188 ttp
[llfc_traf_type
] = max_t(u32
, ttp
[llfc_traf_type
], pri
);
191 static void bnx2x_dcbx_get_ap_feature(struct bnx2x
*bp
,
192 struct dcbx_app_priority_feature
*app
,
195 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
197 if (GET_FLAGS(error
, DCBX_LOCAL_APP_ERROR
))
198 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_APP_ERROR\n");
200 if (GET_FLAGS(error
, DCBX_LOCAL_APP_MISMATCH
))
201 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_APP_MISMATCH\n");
203 if (GET_FLAGS(error
, DCBX_REMOTE_APP_TLV_NOT_FOUND
))
204 DP(BNX2X_MSG_DCB
, "DCBX_REMOTE_APP_TLV_NOT_FOUND\n");
206 !GET_FLAGS(error
, DCBX_LOCAL_APP_ERROR
| DCBX_LOCAL_APP_MISMATCH
|
207 DCBX_REMOTE_APP_TLV_NOT_FOUND
)) {
209 bp
->dcbx_port_params
.app
.enabled
= true;
211 for (index
= 0 ; index
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; index
++)
214 if (app
->default_pri
< MAX_PFC_PRIORITIES
)
215 ttp
[LLFC_TRAFFIC_TYPE_NW
] = app
->default_pri
;
217 for (index
= 0 ; index
< DCBX_MAX_APP_PROTOCOL
; index
++) {
218 struct dcbx_app_priority_entry
*entry
=
221 if (GET_FLAGS(entry
[index
].appBitfield
,
222 DCBX_APP_SF_ETH_TYPE
) &&
223 ETH_TYPE_FCOE
== entry
[index
].app_id
)
224 bnx2x_dcbx_get_ap_priority(bp
,
225 entry
[index
].pri_bitmap
,
226 LLFC_TRAFFIC_TYPE_FCOE
);
228 if (GET_FLAGS(entry
[index
].appBitfield
,
230 TCP_PORT_ISCSI
== entry
[index
].app_id
)
231 bnx2x_dcbx_get_ap_priority(bp
,
232 entry
[index
].pri_bitmap
,
233 LLFC_TRAFFIC_TYPE_ISCSI
);
236 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_APP_DISABLED\n");
237 bp
->dcbx_port_params
.app
.enabled
= false;
238 for (index
= 0 ; index
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; index
++)
239 ttp
[index
] = INVALID_TRAFFIC_TYPE_PRIORITY
;
243 static void bnx2x_dcbx_get_ets_feature(struct bnx2x
*bp
,
244 struct dcbx_ets_feature
*ets
,
247 u32 pg_pri_orginal_spread
[DCBX_MAX_NUM_PG_BW_ENTRIES
] = {0};
248 struct pg_help_data pg_help_data
;
249 struct bnx2x_dcbx_cos_params
*cos_params
=
250 bp
->dcbx_port_params
.ets
.cos_params
;
252 memset(&pg_help_data
, 0, sizeof(struct pg_help_data
));
254 if (GET_FLAGS(error
, DCBX_LOCAL_ETS_ERROR
))
255 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_ETS_ERROR\n");
257 if (GET_FLAGS(error
, DCBX_REMOTE_ETS_TLV_NOT_FOUND
))
258 DP(BNX2X_MSG_DCB
, "DCBX_REMOTE_ETS_TLV_NOT_FOUND\n");
260 /* Clean up old settings of ets on COS */
261 for (i
= 0; i
< ARRAY_SIZE(bp
->dcbx_port_params
.ets
.cos_params
) ; i
++) {
262 cos_params
[i
].pauseable
= false;
263 cos_params
[i
].strict
= BNX2X_DCBX_STRICT_INVALID
;
264 cos_params
[i
].bw_tbl
= DCBX_INVALID_COS_BW
;
265 cos_params
[i
].pri_bitmask
= 0;
268 if (bp
->dcbx_port_params
.app
.enabled
&& ets
->enabled
&&
270 DCBX_LOCAL_ETS_ERROR
| DCBX_REMOTE_ETS_TLV_NOT_FOUND
)) {
271 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_ETS_ENABLE\n");
272 bp
->dcbx_port_params
.ets
.enabled
= true;
274 bnx2x_dcbx_get_ets_pri_pg_tbl(bp
,
275 pg_pri_orginal_spread
,
278 bnx2x_dcbx_get_num_pg_traf_type(bp
,
279 pg_pri_orginal_spread
,
282 bnx2x_dcbx_fill_cos_params(bp
, &pg_help_data
,
283 ets
, pg_pri_orginal_spread
);
286 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_ETS_DISABLED\n");
287 bp
->dcbx_port_params
.ets
.enabled
= false;
288 ets
->pri_pg_tbl
[0] = 0;
290 for (i
= 0; i
< DCBX_MAX_NUM_PRI_PG_ENTRIES
; i
++)
291 DCBX_PG_BW_SET(ets
->pg_bw_tbl
, i
, 1);
295 static void bnx2x_dcbx_get_pfc_feature(struct bnx2x
*bp
,
296 struct dcbx_pfc_feature
*pfc
, u32 error
)
298 if (GET_FLAGS(error
, DCBX_LOCAL_PFC_ERROR
))
299 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_PFC_ERROR\n");
301 if (GET_FLAGS(error
, DCBX_REMOTE_PFC_TLV_NOT_FOUND
))
302 DP(BNX2X_MSG_DCB
, "DCBX_REMOTE_PFC_TLV_NOT_FOUND\n");
303 if (bp
->dcbx_port_params
.app
.enabled
&& pfc
->enabled
&&
304 !GET_FLAGS(error
, DCBX_LOCAL_PFC_ERROR
| DCBX_LOCAL_PFC_MISMATCH
|
305 DCBX_REMOTE_PFC_TLV_NOT_FOUND
)) {
306 bp
->dcbx_port_params
.pfc
.enabled
= true;
307 bp
->dcbx_port_params
.pfc
.priority_non_pauseable_mask
=
308 ~(pfc
->pri_en_bitmap
);
310 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_PFC_DISABLED\n");
311 bp
->dcbx_port_params
.pfc
.enabled
= false;
312 bp
->dcbx_port_params
.pfc
.priority_non_pauseable_mask
= 0;
316 /* maps unmapped priorities to to the same COS as L2 */
317 static void bnx2x_dcbx_map_nw(struct bnx2x
*bp
)
320 u32 unmapped
= (1 << MAX_PFC_PRIORITIES
) - 1; /* all ones */
321 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
322 u32 nw_prio
= 1 << ttp
[LLFC_TRAFFIC_TYPE_NW
];
323 struct bnx2x_dcbx_cos_params
*cos_params
=
324 bp
->dcbx_port_params
.ets
.cos_params
;
326 /* get unmapped priorities by clearing mapped bits */
327 for (i
= 0; i
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; i
++)
328 unmapped
&= ~(1 << ttp
[i
]);
330 /* find cos for nw prio and extend it with unmapped */
331 for (i
= 0; i
< ARRAY_SIZE(bp
->dcbx_port_params
.ets
.cos_params
); i
++) {
332 if (cos_params
[i
].pri_bitmask
& nw_prio
) {
333 /* extend the bitmask with unmapped */
335 "cos %d extended with 0x%08x\n", i
, unmapped
);
336 cos_params
[i
].pri_bitmask
|= unmapped
;
342 static void bnx2x_get_dcbx_drv_param(struct bnx2x
*bp
,
343 struct dcbx_features
*features
,
346 bnx2x_dcbx_get_ap_feature(bp
, &features
->app
, error
);
348 bnx2x_dcbx_get_pfc_feature(bp
, &features
->pfc
, error
);
350 bnx2x_dcbx_get_ets_feature(bp
, &features
->ets
, error
);
352 bnx2x_dcbx_map_nw(bp
);
355 #define DCBX_LOCAL_MIB_MAX_TRY_READ (100)
356 static int bnx2x_dcbx_read_mib(struct bnx2x
*bp
,
361 int max_try_read
= 0;
362 u32 mib_size
, prefix_seq_num
, suffix_seq_num
;
363 struct lldp_remote_mib
*remote_mib
;
364 struct lldp_local_mib
*local_mib
;
366 switch (read_mib_type
) {
367 case DCBX_READ_LOCAL_MIB
:
368 mib_size
= sizeof(struct lldp_local_mib
);
370 case DCBX_READ_REMOTE_MIB
:
371 mib_size
= sizeof(struct lldp_remote_mib
);
377 offset
+= BP_PORT(bp
) * mib_size
;
380 bnx2x_read_data(bp
, base_mib_addr
, offset
, mib_size
);
384 switch (read_mib_type
) {
385 case DCBX_READ_LOCAL_MIB
:
386 local_mib
= (struct lldp_local_mib
*) base_mib_addr
;
387 prefix_seq_num
= local_mib
->prefix_seq_num
;
388 suffix_seq_num
= local_mib
->suffix_seq_num
;
390 case DCBX_READ_REMOTE_MIB
:
391 remote_mib
= (struct lldp_remote_mib
*) base_mib_addr
;
392 prefix_seq_num
= remote_mib
->prefix_seq_num
;
393 suffix_seq_num
= remote_mib
->suffix_seq_num
;
398 } while ((prefix_seq_num
!= suffix_seq_num
) &&
399 (max_try_read
< DCBX_LOCAL_MIB_MAX_TRY_READ
));
401 if (max_try_read
>= DCBX_LOCAL_MIB_MAX_TRY_READ
) {
402 BNX2X_ERR("MIB could not be read\n");
409 static void bnx2x_pfc_set_pfc(struct bnx2x
*bp
)
411 int mfw_configured
= SHMEM2_HAS(bp
, drv_flags
) &&
412 GET_FLAGS(SHMEM2_RD(bp
, drv_flags
),
413 1 << DRV_FLAGS_DCB_MFW_CONFIGURED
);
415 if (bp
->dcbx_port_params
.pfc
.enabled
&&
416 (!(bp
->dcbx_error
& DCBX_REMOTE_MIB_ERROR
) || mfw_configured
))
418 * 1. Fills up common PFC structures if required
419 * 2. Configure NIG, MAC and BRB via the elink
426 int bnx2x_dcbx_stop_hw_tx(struct bnx2x
*bp
)
428 struct bnx2x_func_state_params func_params
= {NULL
};
431 func_params
.f_obj
= &bp
->func_obj
;
432 func_params
.cmd
= BNX2X_F_CMD_TX_STOP
;
434 __set_bit(RAMROD_COMP_WAIT
, &func_params
.ramrod_flags
);
435 __set_bit(RAMROD_RETRY
, &func_params
.ramrod_flags
);
437 DP(BNX2X_MSG_DCB
, "STOP TRAFFIC\n");
439 rc
= bnx2x_func_state_change(bp
, &func_params
);
441 BNX2X_ERR("Unable to hold traffic for HW configuration\n");
448 int bnx2x_dcbx_resume_hw_tx(struct bnx2x
*bp
)
450 struct bnx2x_func_state_params func_params
= {NULL
};
451 struct bnx2x_func_tx_start_params
*tx_params
=
452 &func_params
.params
.tx_start
;
455 func_params
.f_obj
= &bp
->func_obj
;
456 func_params
.cmd
= BNX2X_F_CMD_TX_START
;
458 __set_bit(RAMROD_COMP_WAIT
, &func_params
.ramrod_flags
);
459 __set_bit(RAMROD_RETRY
, &func_params
.ramrod_flags
);
461 bnx2x_dcbx_fw_struct(bp
, tx_params
);
463 DP(BNX2X_MSG_DCB
, "START TRAFFIC\n");
465 rc
= bnx2x_func_state_change(bp
, &func_params
);
467 BNX2X_ERR("Unable to resume traffic after HW configuration\n");
474 static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x
*bp
)
476 struct bnx2x_dcbx_pg_params
*ets
= &(bp
->dcbx_port_params
.ets
);
479 if (ets
->num_of_cos
== 0 || ets
->num_of_cos
> DCBX_COS_MAX_NUM_E2
) {
480 BNX2X_ERR("Illegal number of COSes %d\n", ets
->num_of_cos
);
484 /* valid COS entries */
485 if (ets
->num_of_cos
== 1) /* no ETS */
489 if (((BNX2X_DCBX_STRICT_INVALID
== ets
->cos_params
[0].strict
) &&
490 (DCBX_INVALID_COS_BW
== ets
->cos_params
[0].bw_tbl
)) ||
491 ((BNX2X_DCBX_STRICT_INVALID
== ets
->cos_params
[1].strict
) &&
492 (DCBX_INVALID_COS_BW
== ets
->cos_params
[1].bw_tbl
))) {
493 BNX2X_ERR("all COS should have at least bw_limit or strict"
494 "ets->cos_params[0].strict= %x"
495 "ets->cos_params[0].bw_tbl= %x"
496 "ets->cos_params[1].strict= %x"
497 "ets->cos_params[1].bw_tbl= %x",
498 ets
->cos_params
[0].strict
,
499 ets
->cos_params
[0].bw_tbl
,
500 ets
->cos_params
[1].strict
,
501 ets
->cos_params
[1].bw_tbl
);
504 /* If we join a group and there is bw_tbl and strict then bw rules */
505 if ((DCBX_INVALID_COS_BW
!= ets
->cos_params
[0].bw_tbl
) &&
506 (DCBX_INVALID_COS_BW
!= ets
->cos_params
[1].bw_tbl
)) {
507 u32 bw_tbl_0
= ets
->cos_params
[0].bw_tbl
;
508 u32 bw_tbl_1
= ets
->cos_params
[1].bw_tbl
;
509 /* Do not allow 0-100 configuration
510 * since PBF does not support it
516 } else if (bw_tbl_1
== 0) {
521 bnx2x_ets_bw_limit(&bp
->link_params
, bw_tbl_0
, bw_tbl_1
);
523 if (ets
->cos_params
[0].strict
== BNX2X_DCBX_STRICT_COS_HIGHEST
)
524 rc
= bnx2x_ets_strict(&bp
->link_params
, 0);
525 else if (ets
->cos_params
[1].strict
526 == BNX2X_DCBX_STRICT_COS_HIGHEST
)
527 rc
= bnx2x_ets_strict(&bp
->link_params
, 1);
529 BNX2X_ERR("update_ets_params failed\n");
534 * In E3B0 the configuration may have more than 2 COS.
536 static void bnx2x_dcbx_update_ets_config(struct bnx2x
*bp
)
538 struct bnx2x_dcbx_pg_params
*ets
= &(bp
->dcbx_port_params
.ets
);
539 struct bnx2x_ets_params ets_params
= { 0 };
542 ets_params
.num_of_cos
= ets
->num_of_cos
;
544 for (i
= 0; i
< ets
->num_of_cos
; i
++) {
546 if (ets
->cos_params
[i
].strict
!= BNX2X_DCBX_STRICT_INVALID
) {
547 if (ets
->cos_params
[i
].bw_tbl
!= DCBX_INVALID_COS_BW
) {
548 BNX2X_ERR("COS can't be not BW and not SP\n");
552 ets_params
.cos
[i
].state
= bnx2x_cos_state_strict
;
553 ets_params
.cos
[i
].params
.sp_params
.pri
=
554 ets
->cos_params
[i
].strict
;
555 } else { /* COS is BW */
556 if (ets
->cos_params
[i
].bw_tbl
== DCBX_INVALID_COS_BW
) {
557 BNX2X_ERR("COS can't be not BW and not SP\n");
560 ets_params
.cos
[i
].state
= bnx2x_cos_state_bw
;
561 ets_params
.cos
[i
].params
.bw_params
.bw
=
562 (u8
)ets
->cos_params
[i
].bw_tbl
;
566 /* Configure the ETS in HW */
567 if (bnx2x_ets_e3b0_config(&bp
->link_params
, &bp
->link_vars
,
569 BNX2X_ERR("bnx2x_ets_e3b0_config failed\n");
570 bnx2x_ets_disabled(&bp
->link_params
, &bp
->link_vars
);
574 static void bnx2x_dcbx_update_ets_params(struct bnx2x
*bp
)
576 int mfw_configured
= SHMEM2_HAS(bp
, drv_flags
) &&
577 GET_FLAGS(SHMEM2_RD(bp
, drv_flags
),
578 1 << DRV_FLAGS_DCB_MFW_CONFIGURED
);
580 bnx2x_ets_disabled(&bp
->link_params
, &bp
->link_vars
);
582 if (!bp
->dcbx_port_params
.ets
.enabled
||
583 ((bp
->dcbx_error
& DCBX_REMOTE_MIB_ERROR
) && !mfw_configured
))
586 if (CHIP_IS_E3B0(bp
))
587 bnx2x_dcbx_update_ets_config(bp
);
589 bnx2x_dcbx_2cos_limit_update_ets_config(bp
);
593 static int bnx2x_dcbx_read_shmem_remote_mib(struct bnx2x
*bp
)
595 struct lldp_remote_mib remote_mib
= {0};
596 u32 dcbx_remote_mib_offset
= SHMEM2_RD(bp
, dcbx_remote_mib_offset
);
599 DP(BNX2X_MSG_DCB
, "dcbx_remote_mib_offset 0x%x\n",
600 dcbx_remote_mib_offset
);
602 if (SHMEM_DCBX_REMOTE_MIB_NONE
== dcbx_remote_mib_offset
) {
603 BNX2X_ERR("FW doesn't support dcbx_remote_mib_offset\n");
607 rc
= bnx2x_dcbx_read_mib(bp
, (u32
*)&remote_mib
, dcbx_remote_mib_offset
,
608 DCBX_READ_REMOTE_MIB
);
611 BNX2X_ERR("Failed to read remote mib from FW\n");
615 /* save features and flags */
616 bp
->dcbx_remote_feat
= remote_mib
.features
;
617 bp
->dcbx_remote_flags
= remote_mib
.flags
;
622 static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x
*bp
)
624 struct lldp_local_mib local_mib
= {0};
625 u32 dcbx_neg_res_offset
= SHMEM2_RD(bp
, dcbx_neg_res_offset
);
628 DP(BNX2X_MSG_DCB
, "dcbx_neg_res_offset 0x%x\n", dcbx_neg_res_offset
);
630 if (SHMEM_DCBX_NEG_RES_NONE
== dcbx_neg_res_offset
) {
631 BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
635 rc
= bnx2x_dcbx_read_mib(bp
, (u32
*)&local_mib
, dcbx_neg_res_offset
,
636 DCBX_READ_LOCAL_MIB
);
639 BNX2X_ERR("Failed to read local mib from FW\n");
643 /* save features and error */
644 bp
->dcbx_local_feat
= local_mib
.features
;
645 bp
->dcbx_error
= local_mib
.error
;
651 u8
bnx2x_dcbx_dcbnl_app_up(struct dcbx_app_priority_entry
*ent
)
655 /* Choose the highest priority */
656 for (pri
= MAX_PFC_PRIORITIES
- 1; pri
> 0; pri
--)
657 if (ent
->pri_bitmap
& (1 << pri
))
663 u8
bnx2x_dcbx_dcbnl_app_idtype(struct dcbx_app_priority_entry
*ent
)
665 return ((ent
->appBitfield
& DCBX_APP_ENTRY_SF_MASK
) ==
666 DCBX_APP_SF_PORT
) ? DCB_APP_IDTYPE_PORTNUM
:
667 DCB_APP_IDTYPE_ETHTYPE
;
670 int bnx2x_dcbnl_update_applist(struct bnx2x
*bp
, bool delall
)
674 for (i
= 0; i
< DCBX_MAX_APP_PROTOCOL
&& err
== 0; i
++) {
675 struct dcbx_app_priority_entry
*ent
=
676 &bp
->dcbx_local_feat
.app
.app_pri_tbl
[i
];
678 if (ent
->appBitfield
& DCBX_APP_ENTRY_VALID
) {
679 u8 up
= bnx2x_dcbx_dcbnl_app_up(ent
);
681 /* avoid invalid user-priority */
684 app
.selector
= bnx2x_dcbx_dcbnl_app_idtype(ent
);
685 app
.protocol
= ent
->app_id
;
686 app
.priority
= delall
? 0 : up
;
687 err
= dcb_setapp(bp
->dev
, &app
);
695 static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x
*bp
)
698 for (cos
= 0; cos
< bp
->dcbx_port_params
.ets
.num_of_cos
; cos
++) {
699 for (prio
= 0; prio
< BNX2X_MAX_PRIORITY
; prio
++) {
700 if (bp
->dcbx_port_params
.ets
.cos_params
[cos
].pri_bitmask
702 bp
->prio_to_cos
[prio
] = cos
;
704 "tx_mapping %d --> %d\n", prio
, cos
);
709 /* setup tc must be called under rtnl lock, but we can't take it here
710 * as we are handling an attention on a work queue which must be
711 * flushed at some rtnl-locked contexts (e.g. if down)
713 if (!test_and_set_bit(BNX2X_SP_RTNL_SETUP_TC
, &bp
->sp_rtnl_state
))
714 schedule_delayed_work(&bp
->sp_rtnl_task
, 0);
717 void bnx2x_dcbx_set_params(struct bnx2x
*bp
, u32 state
)
720 case BNX2X_DCBX_STATE_NEG_RECEIVED
:
722 DP(BNX2X_MSG_DCB
, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
725 * Delete app tlvs from dcbnl before reading new
726 * negotiation results
728 bnx2x_dcbnl_update_applist(bp
, true);
730 /* Read remote mib if dcbx is in the FW */
731 if (bnx2x_dcbx_read_shmem_remote_mib(bp
))
734 /* Read neg results if dcbx is in the FW */
735 if (bnx2x_dcbx_read_shmem_neg_results(bp
))
738 bnx2x_dump_dcbx_drv_param(bp
, &bp
->dcbx_local_feat
,
741 bnx2x_get_dcbx_drv_param(bp
, &bp
->dcbx_local_feat
,
744 /* mark DCBX result for PMF migration */
745 bnx2x_update_drv_flags(bp
,
746 1 << DRV_FLAGS_DCB_CONFIGURED
,
750 * Add new app tlvs to dcbnl
752 bnx2x_dcbnl_update_applist(bp
, false);
755 * reconfigure the netdevice with the results of the new
758 bnx2x_dcbx_update_tc_mapping(bp
);
761 * allow other functions to update their netdevices
765 bnx2x_link_sync_notify(bp
);
767 set_bit(BNX2X_SP_RTNL_TX_STOP
, &bp
->sp_rtnl_state
);
769 schedule_delayed_work(&bp
->sp_rtnl_task
, 0);
773 case BNX2X_DCBX_STATE_TX_PAUSED
:
774 DP(BNX2X_MSG_DCB
, "BNX2X_DCBX_STATE_TX_PAUSED\n");
775 bnx2x_pfc_set_pfc(bp
);
777 bnx2x_dcbx_update_ets_params(bp
);
779 /* ets may affect cmng configuration: reinit it in hw */
780 bnx2x_set_local_cmng(bp
);
782 set_bit(BNX2X_SP_RTNL_TX_RESUME
, &bp
->sp_rtnl_state
);
784 schedule_delayed_work(&bp
->sp_rtnl_task
, 0);
787 case BNX2X_DCBX_STATE_TX_RELEASED
:
788 DP(BNX2X_MSG_DCB
, "BNX2X_DCBX_STATE_TX_RELEASED\n");
789 bnx2x_fw_command(bp
, DRV_MSG_CODE_DCBX_PMF_DRV_OK
, 0);
792 * Send a notification for the new negotiated parameters
794 dcbnl_cee_notify(bp
->dev
, RTM_GETDCB
, DCB_CMD_CEE_GET
, 0, 0);
798 BNX2X_ERR("Unknown DCBX_STATE\n");
802 #define LLDP_ADMIN_MIB_OFFSET(bp) (PORT_MAX*sizeof(struct lldp_params) + \
803 BP_PORT(bp)*sizeof(struct lldp_admin_mib))
805 static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x
*bp
,
806 u32 dcbx_lldp_params_offset
)
808 struct lldp_admin_mib admin_mib
;
809 u32 i
, other_traf_type
= PREDEFINED_APP_IDX_MAX
, traf_type
= 0;
810 u32 offset
= dcbx_lldp_params_offset
+ LLDP_ADMIN_MIB_OFFSET(bp
);
813 struct dcbx_features
*af
= &admin_mib
.features
;
814 struct bnx2x_config_dcbx_params
*dp
= &bp
->dcbx_config_params
;
816 memset(&admin_mib
, 0, sizeof(struct lldp_admin_mib
));
818 /* Read the data first */
819 bnx2x_read_data(bp
, (u32
*)&admin_mib
, offset
,
820 sizeof(struct lldp_admin_mib
));
822 if (bp
->dcbx_enabled
== BNX2X_DCBX_ENABLED_ON_NEG_ON
)
823 SET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_DCBX_ENABLED
);
825 RESET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_DCBX_ENABLED
);
827 if (dp
->overwrite_settings
== BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE
) {
829 RESET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_CEE_VERSION_MASK
);
830 admin_mib
.ver_cfg_flags
|=
831 (dp
->admin_dcbx_version
<< DCBX_CEE_VERSION_SHIFT
) &
832 DCBX_CEE_VERSION_MASK
;
834 af
->ets
.enabled
= (u8
)dp
->admin_ets_enable
;
836 af
->pfc
.enabled
= (u8
)dp
->admin_pfc_enable
;
838 /* FOR IEEE dp->admin_tc_supported_tx_enable */
839 if (dp
->admin_ets_configuration_tx_enable
)
840 SET_FLAGS(admin_mib
.ver_cfg_flags
,
841 DCBX_ETS_CONFIG_TX_ENABLED
);
843 RESET_FLAGS(admin_mib
.ver_cfg_flags
,
844 DCBX_ETS_CONFIG_TX_ENABLED
);
845 /* For IEEE admin_ets_recommendation_tx_enable */
846 if (dp
->admin_pfc_tx_enable
)
847 SET_FLAGS(admin_mib
.ver_cfg_flags
,
848 DCBX_PFC_CONFIG_TX_ENABLED
);
850 RESET_FLAGS(admin_mib
.ver_cfg_flags
,
851 DCBX_PFC_CONFIG_TX_ENABLED
);
853 if (dp
->admin_application_priority_tx_enable
)
854 SET_FLAGS(admin_mib
.ver_cfg_flags
,
855 DCBX_APP_CONFIG_TX_ENABLED
);
857 RESET_FLAGS(admin_mib
.ver_cfg_flags
,
858 DCBX_APP_CONFIG_TX_ENABLED
);
860 if (dp
->admin_ets_willing
)
861 SET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_ETS_WILLING
);
863 RESET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_ETS_WILLING
);
864 /* For IEEE admin_ets_reco_valid */
865 if (dp
->admin_pfc_willing
)
866 SET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_PFC_WILLING
);
868 RESET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_PFC_WILLING
);
870 if (dp
->admin_app_priority_willing
)
871 SET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_APP_WILLING
);
873 RESET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_APP_WILLING
);
875 for (i
= 0 ; i
< DCBX_MAX_NUM_PG_BW_ENTRIES
; i
++) {
876 DCBX_PG_BW_SET(af
->ets
.pg_bw_tbl
, i
,
877 (u8
)dp
->admin_configuration_bw_precentage
[i
]);
879 DP(BNX2X_MSG_DCB
, "pg_bw_tbl[%d] = %02x\n",
880 i
, DCBX_PG_BW_GET(af
->ets
.pg_bw_tbl
, i
));
883 for (i
= 0; i
< DCBX_MAX_NUM_PRI_PG_ENTRIES
; i
++) {
884 DCBX_PRI_PG_SET(af
->ets
.pri_pg_tbl
, i
,
885 (u8
)dp
->admin_configuration_ets_pg
[i
]);
887 DP(BNX2X_MSG_DCB
, "pri_pg_tbl[%d] = %02x\n",
888 i
, DCBX_PRI_PG_GET(af
->ets
.pri_pg_tbl
, i
));
891 /*For IEEE admin_recommendation_bw_percentage
892 *For IEEE admin_recommendation_ets_pg */
893 af
->pfc
.pri_en_bitmap
= (u8
)dp
->admin_pfc_bitmap
;
894 for (i
= 0; i
< DCBX_CONFIG_MAX_APP_PROTOCOL
; i
++) {
895 if (dp
->admin_priority_app_table
[i
].valid
) {
896 struct bnx2x_admin_priority_app_table
*table
=
897 dp
->admin_priority_app_table
;
898 if ((ETH_TYPE_FCOE
== table
[i
].app_id
) &&
899 (TRAFFIC_TYPE_ETH
== table
[i
].traffic_type
))
900 traf_type
= FCOE_APP_IDX
;
901 else if ((TCP_PORT_ISCSI
== table
[i
].app_id
) &&
902 (TRAFFIC_TYPE_PORT
== table
[i
].traffic_type
))
903 traf_type
= ISCSI_APP_IDX
;
905 traf_type
= other_traf_type
++;
907 af
->app
.app_pri_tbl
[traf_type
].app_id
=
910 af
->app
.app_pri_tbl
[traf_type
].pri_bitmap
=
911 (u8
)(1 << table
[i
].priority
);
913 af
->app
.app_pri_tbl
[traf_type
].appBitfield
=
914 (DCBX_APP_ENTRY_VALID
);
916 af
->app
.app_pri_tbl
[traf_type
].appBitfield
|=
917 (TRAFFIC_TYPE_ETH
== table
[i
].traffic_type
) ?
918 DCBX_APP_SF_ETH_TYPE
: DCBX_APP_SF_PORT
;
922 af
->app
.default_pri
= (u8
)dp
->admin_default_priority
;
925 /* Write the data. */
926 bnx2x_write_data(bp
, (u32
*)&admin_mib
, offset
,
927 sizeof(struct lldp_admin_mib
));
930 void bnx2x_dcbx_set_state(struct bnx2x
*bp
, bool dcb_on
, u32 dcbx_enabled
)
932 if (!CHIP_IS_E1x(bp
)) {
933 bp
->dcb_state
= dcb_on
;
934 bp
->dcbx_enabled
= dcbx_enabled
;
936 bp
->dcb_state
= false;
937 bp
->dcbx_enabled
= BNX2X_DCBX_ENABLED_INVALID
;
939 DP(BNX2X_MSG_DCB
, "DCB state [%s:%s]\n",
940 dcb_on
? "ON" : "OFF",
941 dcbx_enabled
== BNX2X_DCBX_ENABLED_OFF
? "user-mode" :
942 dcbx_enabled
== BNX2X_DCBX_ENABLED_ON_NEG_OFF
? "on-chip static" :
943 dcbx_enabled
== BNX2X_DCBX_ENABLED_ON_NEG_ON
?
944 "on-chip with negotiation" : "invalid");
947 void bnx2x_dcbx_init_params(struct bnx2x
*bp
)
949 bp
->dcbx_config_params
.admin_dcbx_version
= 0x0; /* 0 - CEE; 1 - IEEE */
950 bp
->dcbx_config_params
.admin_ets_willing
= 1;
951 bp
->dcbx_config_params
.admin_pfc_willing
= 1;
952 bp
->dcbx_config_params
.overwrite_settings
= 1;
953 bp
->dcbx_config_params
.admin_ets_enable
= 1;
954 bp
->dcbx_config_params
.admin_pfc_enable
= 1;
955 bp
->dcbx_config_params
.admin_tc_supported_tx_enable
= 1;
956 bp
->dcbx_config_params
.admin_ets_configuration_tx_enable
= 1;
957 bp
->dcbx_config_params
.admin_pfc_tx_enable
= 1;
958 bp
->dcbx_config_params
.admin_application_priority_tx_enable
= 1;
959 bp
->dcbx_config_params
.admin_ets_reco_valid
= 1;
960 bp
->dcbx_config_params
.admin_app_priority_willing
= 1;
961 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[0] = 100;
962 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[1] = 0;
963 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[2] = 0;
964 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[3] = 0;
965 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[4] = 0;
966 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[5] = 0;
967 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[6] = 0;
968 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[7] = 0;
969 bp
->dcbx_config_params
.admin_configuration_ets_pg
[0] = 0;
970 bp
->dcbx_config_params
.admin_configuration_ets_pg
[1] = 0;
971 bp
->dcbx_config_params
.admin_configuration_ets_pg
[2] = 0;
972 bp
->dcbx_config_params
.admin_configuration_ets_pg
[3] = 0;
973 bp
->dcbx_config_params
.admin_configuration_ets_pg
[4] = 0;
974 bp
->dcbx_config_params
.admin_configuration_ets_pg
[5] = 0;
975 bp
->dcbx_config_params
.admin_configuration_ets_pg
[6] = 0;
976 bp
->dcbx_config_params
.admin_configuration_ets_pg
[7] = 0;
977 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[0] = 100;
978 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[1] = 0;
979 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[2] = 0;
980 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[3] = 0;
981 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[4] = 0;
982 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[5] = 0;
983 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[6] = 0;
984 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[7] = 0;
985 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[0] = 0;
986 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[1] = 1;
987 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[2] = 2;
988 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[3] = 3;
989 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[4] = 4;
990 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[5] = 5;
991 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[6] = 6;
992 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[7] = 7;
993 bp
->dcbx_config_params
.admin_pfc_bitmap
= 0x0;
994 bp
->dcbx_config_params
.admin_priority_app_table
[0].valid
= 0;
995 bp
->dcbx_config_params
.admin_priority_app_table
[1].valid
= 0;
996 bp
->dcbx_config_params
.admin_priority_app_table
[2].valid
= 0;
997 bp
->dcbx_config_params
.admin_priority_app_table
[3].valid
= 0;
998 bp
->dcbx_config_params
.admin_default_priority
= 0;
1001 void bnx2x_dcbx_init(struct bnx2x
*bp
, bool update_shmem
)
1003 u32 dcbx_lldp_params_offset
= SHMEM_LLDP_DCBX_PARAMS_NONE
;
1005 /* only PMF can send ADMIN msg to MFW in old MFW versions */
1006 if ((!bp
->port
.pmf
) && (!(bp
->flags
& BC_SUPPORTS_DCBX_MSG_NON_PMF
)))
1009 if (bp
->dcbx_enabled
<= 0)
1013 * chip of good for dcbx version,
1015 * shmem2 contains DCBX support fields
1017 DP(BNX2X_MSG_DCB
, "dcb_state %d bp->port.pmf %d\n",
1018 bp
->dcb_state
, bp
->port
.pmf
);
1020 if (bp
->dcb_state
== BNX2X_DCB_STATE_ON
&&
1021 SHMEM2_HAS(bp
, dcbx_lldp_params_offset
)) {
1022 dcbx_lldp_params_offset
=
1023 SHMEM2_RD(bp
, dcbx_lldp_params_offset
);
1025 DP(BNX2X_MSG_DCB
, "dcbx_lldp_params_offset 0x%x\n",
1026 dcbx_lldp_params_offset
);
1028 bnx2x_update_drv_flags(bp
, 1 << DRV_FLAGS_DCB_CONFIGURED
, 0);
1030 if (SHMEM_LLDP_DCBX_PARAMS_NONE
!= dcbx_lldp_params_offset
) {
1031 /* need HW lock to avoid scenario of two drivers
1032 * writing in parallel to shmem
1034 bnx2x_acquire_hw_lock(bp
,
1035 HW_LOCK_RESOURCE_DCBX_ADMIN_MIB
);
1037 bnx2x_dcbx_admin_mib_updated_params(bp
,
1038 dcbx_lldp_params_offset
);
1040 /* Let HW start negotiation */
1041 bnx2x_fw_command(bp
,
1042 DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG
, 0);
1043 /* release HW lock only after MFW acks that it finished
1044 * reading values from shmem
1046 bnx2x_release_hw_lock(bp
,
1047 HW_LOCK_RESOURCE_DCBX_ADMIN_MIB
);
1052 bnx2x_dcbx_print_cos_params(struct bnx2x
*bp
,
1053 struct bnx2x_func_tx_start_params
*pfc_fw_cfg
)
1059 "pfc_fw_cfg->dcb_version %x\n", pfc_fw_cfg
->dcb_version
);
1061 "pdev->params.dcbx_port_params.pfc.priority_non_pauseable_mask %x\n",
1062 bp
->dcbx_port_params
.pfc
.priority_non_pauseable_mask
);
1064 for (cos
= 0 ; cos
< bp
->dcbx_port_params
.ets
.num_of_cos
; cos
++) {
1066 "pdev->params.dcbx_port_params.ets.cos_params[%d].pri_bitmask %x\n",
1067 cos
, bp
->dcbx_port_params
.ets
.cos_params
[cos
].pri_bitmask
);
1070 "pdev->params.dcbx_port_params.ets.cos_params[%d].bw_tbl %x\n",
1071 cos
, bp
->dcbx_port_params
.ets
.cos_params
[cos
].bw_tbl
);
1074 "pdev->params.dcbx_port_params.ets.cos_params[%d].strict %x\n",
1075 cos
, bp
->dcbx_port_params
.ets
.cos_params
[cos
].strict
);
1078 "pdev->params.dcbx_port_params.ets.cos_params[%d].pauseable %x\n",
1079 cos
, bp
->dcbx_port_params
.ets
.cos_params
[cos
].pauseable
);
1082 for (pri
= 0; pri
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; pri
++) {
1084 "pfc_fw_cfg->traffic_type_to_priority_cos[%d].priority %x\n",
1085 pri
, pfc_fw_cfg
->traffic_type_to_priority_cos
[pri
].priority
);
1088 "pfc_fw_cfg->traffic_type_to_priority_cos[%d].cos %x\n",
1089 pri
, pfc_fw_cfg
->traffic_type_to_priority_cos
[pri
].cos
);
1093 /* fills help_data according to pg_info */
1094 static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x
*bp
,
1095 u32
*pg_pri_orginal_spread
,
1096 struct pg_help_data
*help_data
)
1098 bool pg_found
= false;
1099 u32 i
, traf_type
, add_traf_type
, add_pg
;
1100 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
1101 struct pg_entry_help_data
*data
= help_data
->data
; /*shortcut*/
1103 /* Set to invalid */
1104 for (i
= 0; i
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; i
++)
1105 data
[i
].pg
= DCBX_ILLEGAL_PG
;
1107 for (add_traf_type
= 0;
1108 add_traf_type
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; add_traf_type
++) {
1110 if (ttp
[add_traf_type
] < MAX_PFC_PRIORITIES
) {
1111 add_pg
= (u8
)pg_pri_orginal_spread
[ttp
[add_traf_type
]];
1113 traf_type
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
;
1115 if (data
[traf_type
].pg
== add_pg
) {
1116 if (!(data
[traf_type
].pg_priority
&
1117 (1 << ttp
[add_traf_type
])))
1120 data
[traf_type
].pg_priority
|=
1121 (1 << ttp
[add_traf_type
]);
1126 if (false == pg_found
) {
1127 data
[help_data
->num_of_pg
].pg
= add_pg
;
1128 data
[help_data
->num_of_pg
].pg_priority
=
1129 (1 << ttp
[add_traf_type
]);
1130 data
[help_data
->num_of_pg
].num_of_dif_pri
= 1;
1131 help_data
->num_of_pg
++;
1135 "add_traf_type %d pg_found %s num_of_pg %d\n",
1136 add_traf_type
, (false == pg_found
) ? "NO" : "YES",
1137 help_data
->num_of_pg
);
1141 static void bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x
*bp
,
1142 struct cos_help_data
*cos_data
,
1145 /* Only one priority than only one COS */
1146 cos_data
->data
[0].pausable
=
1147 IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
, pri_join_mask
);
1148 cos_data
->data
[0].pri_join_mask
= pri_join_mask
;
1149 cos_data
->data
[0].cos_bw
= 100;
1150 cos_data
->num_of_cos
= 1;
1153 static inline void bnx2x_dcbx_add_to_cos_bw(struct bnx2x
*bp
,
1154 struct cos_entry_help_data
*data
,
1157 if (data
->cos_bw
== DCBX_INVALID_COS_BW
)
1158 data
->cos_bw
= pg_bw
;
1160 data
->cos_bw
+= pg_bw
;
1163 static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x
*bp
,
1164 struct cos_help_data
*cos_data
,
1165 u32
*pg_pri_orginal_spread
,
1166 struct dcbx_ets_feature
*ets
)
1172 u8 num_of_pri
= LLFC_DRIVER_TRAFFIC_TYPE_MAX
;
1174 cos_data
->data
[0].pausable
= true;
1175 cos_data
->data
[1].pausable
= false;
1176 cos_data
->data
[0].pri_join_mask
= cos_data
->data
[1].pri_join_mask
= 0;
1178 for (i
= 0 ; i
< num_of_pri
; i
++) {
1179 pri_tested
= 1 << bp
->dcbx_port_params
.
1180 app
.traffic_type_priority
[i
];
1182 if (pri_tested
& DCBX_PFC_PRI_NON_PAUSE_MASK(bp
)) {
1183 cos_data
->data
[1].pri_join_mask
|= pri_tested
;
1186 cos_data
->data
[0].pri_join_mask
|= pri_tested
;
1189 pg_entry
= (u8
)pg_pri_orginal_spread
[bp
->dcbx_port_params
.
1190 app
.traffic_type_priority
[i
]];
1191 /* There can be only one strict pg */
1192 if (pg_entry
< DCBX_MAX_NUM_PG_BW_ENTRIES
)
1193 bnx2x_dcbx_add_to_cos_bw(bp
, &cos_data
->data
[entry
],
1194 DCBX_PG_BW_GET(ets
->pg_bw_tbl
, pg_entry
));
1196 /* If we join a group and one is strict
1199 cos_data
->data
[entry
].strict
=
1200 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1202 if ((0 == cos_data
->data
[0].pri_join_mask
) &&
1203 (0 == cos_data
->data
[1].pri_join_mask
))
1204 BNX2X_ERR("dcbx error: Both groups must have priorities\n");
1208 #define POWER_OF_2(x) ((0 != x) && (0 == (x & (x-1))))
1211 static void bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(struct bnx2x
*bp
,
1212 struct pg_help_data
*pg_help_data
,
1213 struct cos_help_data
*cos_data
,
1219 u32 pri_mask_without_pri
= 0;
1220 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
1222 if (num_of_dif_pri
== 1) {
1223 bnx2x_dcbx_ets_disabled_entry_data(bp
, cos_data
, pri_join_mask
);
1226 /* single priority group */
1227 if (pg_help_data
->data
[0].pg
< DCBX_MAX_NUM_PG_BW_ENTRIES
) {
1228 /* If there are both pauseable and non-pauseable priorities,
1229 * the pauseable priorities go to the first queue and
1230 * the non-pauseable priorities go to the second queue.
1232 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp
, pri_join_mask
)) {
1234 cos_data
->data
[0].pausable
= true;
1236 cos_data
->data
[1].pausable
= false;
1238 if (2 == num_of_dif_pri
) {
1239 cos_data
->data
[0].cos_bw
= 50;
1240 cos_data
->data
[1].cos_bw
= 50;
1243 if (3 == num_of_dif_pri
) {
1244 if (POWER_OF_2(DCBX_PFC_PRI_GET_PAUSE(bp
,
1246 cos_data
->data
[0].cos_bw
= 33;
1247 cos_data
->data
[1].cos_bw
= 67;
1249 cos_data
->data
[0].cos_bw
= 67;
1250 cos_data
->data
[1].cos_bw
= 33;
1254 } else if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
, pri_join_mask
)) {
1255 /* If there are only pauseable priorities,
1256 * then one/two priorities go to the first queue
1257 * and one priority goes to the second queue.
1259 if (2 == num_of_dif_pri
) {
1260 cos_data
->data
[0].cos_bw
= 50;
1261 cos_data
->data
[1].cos_bw
= 50;
1263 cos_data
->data
[0].cos_bw
= 67;
1264 cos_data
->data
[1].cos_bw
= 33;
1266 cos_data
->data
[1].pausable
= true;
1267 cos_data
->data
[0].pausable
= true;
1268 /* All priorities except FCOE */
1269 cos_data
->data
[0].pri_join_mask
= (pri_join_mask
&
1270 ((u8
)~(1 << ttp
[LLFC_TRAFFIC_TYPE_FCOE
])));
1271 /* Only FCOE priority.*/
1272 cos_data
->data
[1].pri_join_mask
=
1273 (1 << ttp
[LLFC_TRAFFIC_TYPE_FCOE
]);
1275 /* If there are only non-pauseable priorities,
1276 * they will all go to the same queue.
1278 bnx2x_dcbx_ets_disabled_entry_data(bp
,
1279 cos_data
, pri_join_mask
);
1281 /* priority group which is not BW limited (PG#15):*/
1282 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp
, pri_join_mask
)) {
1283 /* If there are both pauseable and non-pauseable
1284 * priorities, the pauseable priorities go to the first
1285 * queue and the non-pauseable priorities
1286 * go to the second queue.
1288 if (DCBX_PFC_PRI_GET_PAUSE(bp
, pri_join_mask
) >
1289 DCBX_PFC_PRI_GET_NON_PAUSE(bp
, pri_join_mask
)) {
1290 cos_data
->data
[0].strict
=
1291 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1292 cos_data
->data
[1].strict
=
1293 BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
1294 BNX2X_DCBX_STRICT_COS_HIGHEST
);
1296 cos_data
->data
[0].strict
=
1297 BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
1298 BNX2X_DCBX_STRICT_COS_HIGHEST
);
1299 cos_data
->data
[1].strict
=
1300 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1303 cos_data
->data
[0].pausable
= true;
1304 /* Non pause-able.*/
1305 cos_data
->data
[1].pausable
= false;
1307 /* If there are only pauseable priorities or
1308 * only non-pauseable,* the lower priorities go
1309 * to the first queue and the higher priorities go
1310 * to the second queue.
1312 cos_data
->data
[0].pausable
=
1313 cos_data
->data
[1].pausable
=
1314 IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
, pri_join_mask
);
1316 for (i
= 0 ; i
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; i
++) {
1317 pri_tested
= 1 << bp
->dcbx_port_params
.
1318 app
.traffic_type_priority
[i
];
1319 /* Remove priority tested */
1320 pri_mask_without_pri
=
1321 (pri_join_mask
& ((u8
)(~pri_tested
)));
1322 if (pri_mask_without_pri
< pri_tested
)
1326 if (i
== LLFC_DRIVER_TRAFFIC_TYPE_MAX
)
1327 BNX2X_ERR("Invalid value for pri_join_mask - could not find a priority\n");
1329 cos_data
->data
[0].pri_join_mask
= pri_mask_without_pri
;
1330 cos_data
->data
[1].pri_join_mask
= pri_tested
;
1331 /* Both queues are strict priority,
1332 * and that with the highest priority
1333 * gets the highest strict priority in the arbiter.
1335 cos_data
->data
[0].strict
=
1336 BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
1337 BNX2X_DCBX_STRICT_COS_HIGHEST
);
1338 cos_data
->data
[1].strict
=
1339 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1344 static void bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
1346 struct pg_help_data
*pg_help_data
,
1347 struct dcbx_ets_feature
*ets
,
1348 struct cos_help_data
*cos_data
,
1349 u32
*pg_pri_orginal_spread
,
1354 u8 pg
[DCBX_COS_MAX_NUM_E2
] = { 0 };
1356 /* If there are both pauseable and non-pauseable priorities,
1357 * the pauseable priorities go to the first queue and
1358 * the non-pauseable priorities go to the second queue.
1360 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp
, pri_join_mask
)) {
1361 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp
,
1362 pg_help_data
->data
[0].pg_priority
) ||
1363 IS_DCBX_PFC_PRI_MIX_PAUSE(bp
,
1364 pg_help_data
->data
[1].pg_priority
)) {
1365 /* If one PG contains both pauseable and
1366 * non-pauseable priorities then ETS is disabled.
1368 bnx2x_dcbx_separate_pauseable_from_non(bp
, cos_data
,
1369 pg_pri_orginal_spread
, ets
);
1370 bp
->dcbx_port_params
.ets
.enabled
= false;
1375 cos_data
->data
[0].pausable
= true;
1376 /* Non pauseable. */
1377 cos_data
->data
[1].pausable
= false;
1378 if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
,
1379 pg_help_data
->data
[0].pg_priority
)) {
1380 /* 0 is pauseable */
1381 cos_data
->data
[0].pri_join_mask
=
1382 pg_help_data
->data
[0].pg_priority
;
1383 pg
[0] = pg_help_data
->data
[0].pg
;
1384 cos_data
->data
[1].pri_join_mask
=
1385 pg_help_data
->data
[1].pg_priority
;
1386 pg
[1] = pg_help_data
->data
[1].pg
;
1387 } else {/* 1 is pauseable */
1388 cos_data
->data
[0].pri_join_mask
=
1389 pg_help_data
->data
[1].pg_priority
;
1390 pg
[0] = pg_help_data
->data
[1].pg
;
1391 cos_data
->data
[1].pri_join_mask
=
1392 pg_help_data
->data
[0].pg_priority
;
1393 pg
[1] = pg_help_data
->data
[0].pg
;
1396 /* If there are only pauseable priorities or
1397 * only non-pauseable, each PG goes to a queue.
1399 cos_data
->data
[0].pausable
= cos_data
->data
[1].pausable
=
1400 IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
, pri_join_mask
);
1401 cos_data
->data
[0].pri_join_mask
=
1402 pg_help_data
->data
[0].pg_priority
;
1403 pg
[0] = pg_help_data
->data
[0].pg
;
1404 cos_data
->data
[1].pri_join_mask
=
1405 pg_help_data
->data
[1].pg_priority
;
1406 pg
[1] = pg_help_data
->data
[1].pg
;
1409 /* There can be only one strict pg */
1410 for (i
= 0 ; i
< ARRAY_SIZE(pg
); i
++) {
1411 if (pg
[i
] < DCBX_MAX_NUM_PG_BW_ENTRIES
)
1412 cos_data
->data
[i
].cos_bw
=
1413 DCBX_PG_BW_GET(ets
->pg_bw_tbl
, pg
[i
]);
1415 cos_data
->data
[i
].strict
=
1416 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1420 static int bnx2x_dcbx_join_pgs(
1422 struct dcbx_ets_feature
*ets
,
1423 struct pg_help_data
*pg_help_data
,
1424 u8 required_num_of_pg
)
1426 u8 entry_joined
= pg_help_data
->num_of_pg
- 1;
1427 u8 entry_removed
= entry_joined
+ 1;
1430 if (required_num_of_pg
== 0 || ARRAY_SIZE(pg_help_data
->data
)
1431 <= pg_help_data
->num_of_pg
) {
1433 BNX2X_ERR("required_num_of_pg can't be zero\n");
1437 while (required_num_of_pg
< pg_help_data
->num_of_pg
) {
1438 entry_joined
= pg_help_data
->num_of_pg
- 2;
1439 entry_removed
= entry_joined
+ 1;
1441 entry_removed
%= ARRAY_SIZE(pg_help_data
->data
);
1443 pg_help_data
->data
[entry_joined
].pg_priority
|=
1444 pg_help_data
->data
[entry_removed
].pg_priority
;
1446 pg_help_data
->data
[entry_joined
].num_of_dif_pri
+=
1447 pg_help_data
->data
[entry_removed
].num_of_dif_pri
;
1449 if (pg_help_data
->data
[entry_joined
].pg
== DCBX_STRICT_PRI_PG
||
1450 pg_help_data
->data
[entry_removed
].pg
== DCBX_STRICT_PRI_PG
)
1451 /* Entries joined strict priority rules */
1452 pg_help_data
->data
[entry_joined
].pg
=
1455 /* Entries can be joined join BW */
1456 pg_joined
= DCBX_PG_BW_GET(ets
->pg_bw_tbl
,
1457 pg_help_data
->data
[entry_joined
].pg
) +
1458 DCBX_PG_BW_GET(ets
->pg_bw_tbl
,
1459 pg_help_data
->data
[entry_removed
].pg
);
1461 DCBX_PG_BW_SET(ets
->pg_bw_tbl
,
1462 pg_help_data
->data
[entry_joined
].pg
, pg_joined
);
1464 /* Joined the entries */
1465 pg_help_data
->num_of_pg
--;
1471 static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
1473 struct pg_help_data
*pg_help_data
,
1474 struct dcbx_ets_feature
*ets
,
1475 struct cos_help_data
*cos_data
,
1476 u32
*pg_pri_orginal_spread
,
1484 bool b_found_strict
= false;
1485 u8 num_of_pri
= LLFC_DRIVER_TRAFFIC_TYPE_MAX
;
1487 cos_data
->data
[0].pri_join_mask
= cos_data
->data
[1].pri_join_mask
= 0;
1488 /* If there are both pauseable and non-pauseable priorities,
1489 * the pauseable priorities go to the first queue and the
1490 * non-pauseable priorities go to the second queue.
1492 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp
, pri_join_mask
))
1493 bnx2x_dcbx_separate_pauseable_from_non(bp
,
1494 cos_data
, pg_pri_orginal_spread
, ets
);
1496 /* If two BW-limited PG-s were combined to one queue,
1497 * the BW is their sum.
1499 * If there are only pauseable priorities or only non-pauseable,
1500 * and there are both BW-limited and non-BW-limited PG-s,
1501 * the BW-limited PG/s go to one queue and the non-BW-limited
1502 * PG/s go to the second queue.
1504 * If there are only pauseable priorities or only non-pauseable
1505 * and all are BW limited, then two priorities go to the first
1506 * queue and one priority goes to the second queue.
1508 * We will join this two cases:
1509 * if one is BW limited it will go to the second queue
1510 * otherwise the last priority will get it
1513 cos_data
->data
[0].pausable
= cos_data
->data
[1].pausable
=
1514 IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
, pri_join_mask
);
1516 for (i
= 0 ; i
< num_of_pri
; i
++) {
1517 pri_tested
= 1 << bp
->dcbx_port_params
.
1518 app
.traffic_type_priority
[i
];
1519 pg_entry
= (u8
)pg_pri_orginal_spread
[bp
->
1520 dcbx_port_params
.app
.traffic_type_priority
[i
]];
1522 if (pg_entry
< DCBX_MAX_NUM_PG_BW_ENTRIES
) {
1525 if (i
== (num_of_pri
-1) &&
1526 false == b_found_strict
)
1527 /* last entry will be handled separately
1528 * If no priority is strict than last
1529 * entry goes to last queue.
1532 cos_data
->data
[entry
].pri_join_mask
|=
1534 bnx2x_dcbx_add_to_cos_bw(bp
,
1535 &cos_data
->data
[entry
],
1536 DCBX_PG_BW_GET(ets
->pg_bw_tbl
,
1539 b_found_strict
= true;
1540 cos_data
->data
[1].pri_join_mask
|= pri_tested
;
1541 /* If we join a group and one is strict
1544 cos_data
->data
[1].strict
=
1545 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1551 static void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x
*bp
,
1552 struct pg_help_data
*help_data
,
1553 struct dcbx_ets_feature
*ets
,
1554 struct cos_help_data
*cos_data
,
1555 u32
*pg_pri_orginal_spread
,
1559 /* default E2 settings */
1560 cos_data
->num_of_cos
= DCBX_COS_MAX_NUM_E2
;
1562 switch (help_data
->num_of_pg
) {
1564 bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(
1572 bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
1577 pg_pri_orginal_spread
,
1583 bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
1588 pg_pri_orginal_spread
,
1593 BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
1594 bnx2x_dcbx_ets_disabled_entry_data(bp
,
1595 cos_data
, pri_join_mask
);
1599 static int bnx2x_dcbx_spread_strict_pri(struct bnx2x
*bp
,
1600 struct cos_help_data
*cos_data
,
1602 u8 num_spread_of_entries
,
1605 u8 strict_pri
= BNX2X_DCBX_STRICT_COS_HIGHEST
;
1606 u8 num_of_app_pri
= MAX_PFC_PRIORITIES
;
1609 while (num_spread_of_entries
&& num_of_app_pri
> 0) {
1610 app_pri_bit
= 1 << (num_of_app_pri
- 1);
1611 if (app_pri_bit
& strict_app_pris
) {
1612 struct cos_entry_help_data
*data
= &cos_data
->
1614 num_spread_of_entries
--;
1615 if (num_spread_of_entries
== 0) {
1616 /* last entry needed put all the entries left */
1617 data
->cos_bw
= DCBX_INVALID_COS_BW
;
1618 data
->strict
= strict_pri
;
1619 data
->pri_join_mask
= strict_app_pris
;
1620 data
->pausable
= DCBX_IS_PFC_PRI_SOME_PAUSE(bp
,
1621 data
->pri_join_mask
);
1623 strict_app_pris
&= ~app_pri_bit
;
1625 data
->cos_bw
= DCBX_INVALID_COS_BW
;
1626 data
->strict
= strict_pri
;
1627 data
->pri_join_mask
= app_pri_bit
;
1628 data
->pausable
= DCBX_IS_PFC_PRI_SOME_PAUSE(bp
,
1629 data
->pri_join_mask
);
1633 BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(strict_pri
);
1640 if (num_spread_of_entries
) {
1641 BNX2X_ERR("Didn't succeed to spread strict priorities\n");
1648 static u8
bnx2x_dcbx_cee_fill_strict_pri(struct bnx2x
*bp
,
1649 struct cos_help_data
*cos_data
,
1651 u8 num_spread_of_entries
,
1654 if (bnx2x_dcbx_spread_strict_pri(bp
, cos_data
, entry
,
1655 num_spread_of_entries
,
1657 struct cos_entry_help_data
*data
= &cos_data
->
1660 data
->cos_bw
= DCBX_INVALID_COS_BW
;
1661 data
->strict
= BNX2X_DCBX_STRICT_COS_HIGHEST
;
1662 data
->pri_join_mask
= strict_app_pris
;
1663 data
->pausable
= DCBX_IS_PFC_PRI_SOME_PAUSE(bp
,
1664 data
->pri_join_mask
);
1668 return num_spread_of_entries
;
1671 static void bnx2x_dcbx_cee_fill_cos_params(struct bnx2x
*bp
,
1672 struct pg_help_data
*help_data
,
1673 struct dcbx_ets_feature
*ets
,
1674 struct cos_help_data
*cos_data
,
1678 u8 need_num_of_entries
= 0;
1683 * if the number of requested PG-s in CEE is greater than 3
1684 * then the results are not determined since this is a violation
1687 if (help_data
->num_of_pg
> DCBX_COS_MAX_NUM_E3B0
) {
1688 if (bnx2x_dcbx_join_pgs(bp
, ets
, help_data
,
1689 DCBX_COS_MAX_NUM_E3B0
)) {
1690 BNX2X_ERR("Unable to reduce the number of PGs - we will disables ETS\n");
1691 bnx2x_dcbx_ets_disabled_entry_data(bp
, cos_data
,
1697 for (i
= 0 ; i
< help_data
->num_of_pg
; i
++) {
1698 struct pg_entry_help_data
*pg
= &help_data
->data
[i
];
1699 if (pg
->pg
< DCBX_MAX_NUM_PG_BW_ENTRIES
) {
1700 struct cos_entry_help_data
*data
= &cos_data
->
1703 data
->cos_bw
= DCBX_PG_BW_GET(ets
->pg_bw_tbl
, pg
->pg
);
1704 data
->strict
= BNX2X_DCBX_STRICT_INVALID
;
1705 data
->pri_join_mask
= pg
->pg_priority
;
1706 data
->pausable
= DCBX_IS_PFC_PRI_SOME_PAUSE(bp
,
1707 data
->pri_join_mask
);
1711 need_num_of_entries
= min_t(u8
,
1712 (u8
)pg
->num_of_dif_pri
,
1713 (u8
)DCBX_COS_MAX_NUM_E3B0
-
1714 help_data
->num_of_pg
+ 1);
1716 * If there are still VOQ-s which have no associated PG,
1717 * then associate these VOQ-s to PG15. These PG-s will
1718 * be used for SP between priorities on PG15.
1720 entry
+= bnx2x_dcbx_cee_fill_strict_pri(bp
, cos_data
,
1721 entry
, need_num_of_entries
, pg
->pg_priority
);
1725 /* the entry will represent the number of COSes used */
1726 cos_data
->num_of_cos
= entry
;
1728 static void bnx2x_dcbx_fill_cos_params(struct bnx2x
*bp
,
1729 struct pg_help_data
*help_data
,
1730 struct dcbx_ets_feature
*ets
,
1731 u32
*pg_pri_orginal_spread
)
1733 struct cos_help_data cos_data
;
1735 u32 pri_join_mask
= 0;
1736 u8 num_of_dif_pri
= 0;
1738 memset(&cos_data
, 0, sizeof(cos_data
));
1740 /* Validate the pg value */
1741 for (i
= 0; i
< help_data
->num_of_pg
; i
++) {
1742 if (DCBX_STRICT_PRIORITY
!= help_data
->data
[i
].pg
&&
1743 DCBX_MAX_NUM_PG_BW_ENTRIES
<= help_data
->data
[i
].pg
)
1744 BNX2X_ERR("Invalid pg[%d] data %x\n", i
,
1745 help_data
->data
[i
].pg
);
1746 pri_join_mask
|= help_data
->data
[i
].pg_priority
;
1747 num_of_dif_pri
+= help_data
->data
[i
].num_of_dif_pri
;
1751 cos_data
.num_of_cos
= 1;
1752 for (i
= 0; i
< ARRAY_SIZE(cos_data
.data
); i
++) {
1753 cos_data
.data
[i
].pri_join_mask
= 0;
1754 cos_data
.data
[i
].pausable
= false;
1755 cos_data
.data
[i
].strict
= BNX2X_DCBX_STRICT_INVALID
;
1756 cos_data
.data
[i
].cos_bw
= DCBX_INVALID_COS_BW
;
1759 if (CHIP_IS_E3B0(bp
))
1760 bnx2x_dcbx_cee_fill_cos_params(bp
, help_data
, ets
,
1761 &cos_data
, pri_join_mask
);
1762 else /* E2 + E3A0 */
1763 bnx2x_dcbx_2cos_limit_cee_fill_cos_params(bp
,
1766 pg_pri_orginal_spread
,
1770 for (i
= 0; i
< cos_data
.num_of_cos
; i
++) {
1771 struct bnx2x_dcbx_cos_params
*p
=
1772 &bp
->dcbx_port_params
.ets
.cos_params
[i
];
1774 p
->strict
= cos_data
.data
[i
].strict
;
1775 p
->bw_tbl
= cos_data
.data
[i
].cos_bw
;
1776 p
->pri_bitmask
= cos_data
.data
[i
].pri_join_mask
;
1777 p
->pauseable
= cos_data
.data
[i
].pausable
;
1780 if (p
->bw_tbl
!= DCBX_INVALID_COS_BW
||
1781 p
->strict
!= BNX2X_DCBX_STRICT_INVALID
) {
1782 if (p
->pri_bitmask
== 0)
1783 BNX2X_ERR("Invalid pri_bitmask for %d\n", i
);
1785 if (CHIP_IS_E2(bp
) || CHIP_IS_E3A0(bp
)) {
1788 DCBX_PFC_PRI_GET_NON_PAUSE(bp
,
1789 p
->pri_bitmask
) != 0)
1790 BNX2X_ERR("Inconsistent config for pausable COS %d\n",
1793 if (!p
->pauseable
&&
1794 DCBX_PFC_PRI_GET_PAUSE(bp
,
1795 p
->pri_bitmask
) != 0)
1796 BNX2X_ERR("Inconsistent config for nonpausable COS %d\n",
1802 DP(BNX2X_MSG_DCB
, "COS %d PAUSABLE prijoinmask 0x%x\n",
1803 i
, cos_data
.data
[i
].pri_join_mask
);
1806 "COS %d NONPAUSABLE prijoinmask 0x%x\n",
1807 i
, cos_data
.data
[i
].pri_join_mask
);
1810 bp
->dcbx_port_params
.ets
.num_of_cos
= cos_data
.num_of_cos
;
1813 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x
*bp
,
1814 u32
*set_configuration_ets_pg
,
1819 for (i
= 0; i
< DCBX_MAX_NUM_PRI_PG_ENTRIES
; i
++) {
1820 set_configuration_ets_pg
[i
] = DCBX_PRI_PG_GET(pri_pg_tbl
, i
);
1822 DP(BNX2X_MSG_DCB
, "set_configuration_ets_pg[%d] = 0x%x\n",
1823 i
, set_configuration_ets_pg
[i
]);
1827 static void bnx2x_dcbx_fw_struct(struct bnx2x
*bp
,
1828 struct bnx2x_func_tx_start_params
*pfc_fw_cfg
)
1831 u8 cos
= 0, pri
= 0;
1832 struct priority_cos
*tt2cos
;
1833 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
1834 int mfw_configured
= SHMEM2_HAS(bp
, drv_flags
) &&
1835 GET_FLAGS(SHMEM2_RD(bp
, drv_flags
),
1836 1 << DRV_FLAGS_DCB_MFW_CONFIGURED
);
1838 memset(pfc_fw_cfg
, 0, sizeof(*pfc_fw_cfg
));
1840 /* to disable DCB - the structure must be zeroed */
1841 if ((bp
->dcbx_error
& DCBX_REMOTE_MIB_ERROR
) && !mfw_configured
)
1845 tt2cos
= pfc_fw_cfg
->traffic_type_to_priority_cos
;
1847 /* Fw version should be incremented each update */
1848 pfc_fw_cfg
->dcb_version
= ++bp
->dcb_version
;
1849 pfc_fw_cfg
->dcb_enabled
= 1;
1851 /* Fill priority parameters */
1852 for (pri
= 0; pri
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; pri
++) {
1853 tt2cos
[pri
].priority
= ttp
[pri
];
1854 pri_bit
= 1 << tt2cos
[pri
].priority
;
1856 /* Fill COS parameters based on COS calculated to
1857 * make it more general for future use */
1858 for (cos
= 0; cos
< bp
->dcbx_port_params
.ets
.num_of_cos
; cos
++)
1859 if (bp
->dcbx_port_params
.ets
.cos_params
[cos
].
1860 pri_bitmask
& pri_bit
)
1861 tt2cos
[pri
].cos
= cos
;
1864 /* we never want the FW to add a 0 vlan tag */
1865 pfc_fw_cfg
->dont_add_pri_0_en
= 1;
1867 bnx2x_dcbx_print_cos_params(bp
, pfc_fw_cfg
);
1870 void bnx2x_dcbx_pmf_update(struct bnx2x
*bp
)
1872 /* if we need to synchronize DCBX result from prev PMF
1873 * read it from shmem and update bp and netdev accordingly
1875 if (SHMEM2_HAS(bp
, drv_flags
) &&
1876 GET_FLAGS(SHMEM2_RD(bp
, drv_flags
), 1 << DRV_FLAGS_DCB_CONFIGURED
)) {
1877 /* Read neg results if dcbx is in the FW */
1878 if (bnx2x_dcbx_read_shmem_neg_results(bp
))
1881 bnx2x_dump_dcbx_drv_param(bp
, &bp
->dcbx_local_feat
,
1883 bnx2x_get_dcbx_drv_param(bp
, &bp
->dcbx_local_feat
,
1887 * Add new app tlvs to dcbnl
1889 bnx2x_dcbnl_update_applist(bp
, false);
1891 * Send a notification for the new negotiated parameters
1893 dcbnl_cee_notify(bp
->dev
, RTM_GETDCB
, DCB_CMD_CEE_GET
, 0, 0);
1896 * reconfigure the netdevice with the results of the new
1899 bnx2x_dcbx_update_tc_mapping(bp
);
1906 #define BNX2X_DCBX_CAPS (DCB_CAP_DCBX_LLD_MANAGED | \
1907 DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
1909 static inline bool bnx2x_dcbnl_set_valid(struct bnx2x
*bp
)
1911 /* validate dcbnl call that may change HW state:
1912 * DCB is on and DCBX mode was SUCCESSFULLY set by the user.
1914 return bp
->dcb_state
&& bp
->dcbx_mode_uset
;
1917 static u8
bnx2x_dcbnl_get_state(struct net_device
*netdev
)
1919 struct bnx2x
*bp
= netdev_priv(netdev
);
1920 DP(BNX2X_MSG_DCB
, "state = %d\n", bp
->dcb_state
);
1921 return bp
->dcb_state
;
1924 static u8
bnx2x_dcbnl_set_state(struct net_device
*netdev
, u8 state
)
1926 struct bnx2x
*bp
= netdev_priv(netdev
);
1927 DP(BNX2X_MSG_DCB
, "state = %s\n", state
? "on" : "off");
1929 /* Fail to set state to "enabled" if dcbx is disabled in nvram */
1930 if (state
&& ((bp
->dcbx_enabled
== BNX2X_DCBX_ENABLED_OFF
) ||
1931 (bp
->dcbx_enabled
== BNX2X_DCBX_ENABLED_INVALID
))) {
1932 DP(BNX2X_MSG_DCB
, "Can not set dcbx to enabled while it is disabled in nvm\n");
1936 bnx2x_dcbx_set_state(bp
, (state
? true : false), bp
->dcbx_enabled
);
1940 static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device
*netdev
,
1943 struct bnx2x
*bp
= netdev_priv(netdev
);
1944 DP(BNX2X_MSG_DCB
, "GET-PERM-ADDR\n");
1946 /* first the HW mac address */
1947 memcpy(perm_addr
, netdev
->dev_addr
, netdev
->addr_len
);
1949 if (CNIC_LOADED(bp
))
1950 /* second SAN address */
1951 memcpy(perm_addr
+netdev
->addr_len
, bp
->fip_mac
,
1955 static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device
*netdev
, int prio
,
1956 u8 prio_type
, u8 pgid
, u8 bw_pct
,
1959 struct bnx2x
*bp
= netdev_priv(netdev
);
1961 DP(BNX2X_MSG_DCB
, "prio[%d] = %d\n", prio
, pgid
);
1962 if (!bnx2x_dcbnl_set_valid(bp
) || prio
>= DCBX_MAX_NUM_PRI_PG_ENTRIES
)
1966 * bw_pct ignored - band-width percentage devision between user
1967 * priorities within the same group is not
1968 * standard and hence not supported
1970 * prio_type ignored - priority levels within the same group are not
1971 * standard and hence are not supported. According
1972 * to the standard pgid 15 is dedicated to strict
1973 * priority traffic (on the port level).
1978 bp
->dcbx_config_params
.admin_configuration_ets_pg
[prio
] = pgid
;
1979 bp
->dcbx_config_params
.admin_ets_configuration_tx_enable
= 1;
1982 static void bnx2x_dcbnl_set_pg_bwgcfg_tx(struct net_device
*netdev
,
1983 int pgid
, u8 bw_pct
)
1985 struct bnx2x
*bp
= netdev_priv(netdev
);
1986 DP(BNX2X_MSG_DCB
, "pgid[%d] = %d\n", pgid
, bw_pct
);
1988 if (!bnx2x_dcbnl_set_valid(bp
) || pgid
>= DCBX_MAX_NUM_PG_BW_ENTRIES
)
1991 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[pgid
] = bw_pct
;
1992 bp
->dcbx_config_params
.admin_ets_configuration_tx_enable
= 1;
1995 static void bnx2x_dcbnl_set_pg_tccfg_rx(struct net_device
*netdev
, int prio
,
1996 u8 prio_type
, u8 pgid
, u8 bw_pct
,
1999 struct bnx2x
*bp
= netdev_priv(netdev
);
2000 DP(BNX2X_MSG_DCB
, "Nothing to set; No RX support\n");
2003 static void bnx2x_dcbnl_set_pg_bwgcfg_rx(struct net_device
*netdev
,
2004 int pgid
, u8 bw_pct
)
2006 struct bnx2x
*bp
= netdev_priv(netdev
);
2007 DP(BNX2X_MSG_DCB
, "Nothing to set; No RX support\n");
2010 static void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device
*netdev
, int prio
,
2011 u8
*prio_type
, u8
*pgid
, u8
*bw_pct
,
2014 struct bnx2x
*bp
= netdev_priv(netdev
);
2015 DP(BNX2X_MSG_DCB
, "prio = %d\n", prio
);
2018 * bw_pct ignored - band-width percentage devision between user
2019 * priorities within the same group is not
2020 * standard and hence not supported
2022 * prio_type ignored - priority levels within the same group are not
2023 * standard and hence are not supported. According
2024 * to the standard pgid 15 is dedicated to strict
2025 * priority traffic (on the port level).
2029 *up_map
= *bw_pct
= *prio_type
= *pgid
= 0;
2031 if (!bp
->dcb_state
|| prio
>= DCBX_MAX_NUM_PRI_PG_ENTRIES
)
2034 *pgid
= DCBX_PRI_PG_GET(bp
->dcbx_local_feat
.ets
.pri_pg_tbl
, prio
);
2037 static void bnx2x_dcbnl_get_pg_bwgcfg_tx(struct net_device
*netdev
,
2038 int pgid
, u8
*bw_pct
)
2040 struct bnx2x
*bp
= netdev_priv(netdev
);
2041 DP(BNX2X_MSG_DCB
, "pgid = %d\n", pgid
);
2045 if (!bp
->dcb_state
|| pgid
>= DCBX_MAX_NUM_PG_BW_ENTRIES
)
2048 *bw_pct
= DCBX_PG_BW_GET(bp
->dcbx_local_feat
.ets
.pg_bw_tbl
, pgid
);
2051 static void bnx2x_dcbnl_get_pg_tccfg_rx(struct net_device
*netdev
, int prio
,
2052 u8
*prio_type
, u8
*pgid
, u8
*bw_pct
,
2055 struct bnx2x
*bp
= netdev_priv(netdev
);
2056 DP(BNX2X_MSG_DCB
, "Nothing to get; No RX support\n");
2058 *prio_type
= *pgid
= *bw_pct
= *up_map
= 0;
2061 static void bnx2x_dcbnl_get_pg_bwgcfg_rx(struct net_device
*netdev
,
2062 int pgid
, u8
*bw_pct
)
2064 struct bnx2x
*bp
= netdev_priv(netdev
);
2065 DP(BNX2X_MSG_DCB
, "Nothing to get; No RX support\n");
2070 static void bnx2x_dcbnl_set_pfc_cfg(struct net_device
*netdev
, int prio
,
2073 struct bnx2x
*bp
= netdev_priv(netdev
);
2074 DP(BNX2X_MSG_DCB
, "prio[%d] = %d\n", prio
, setting
);
2076 if (!bnx2x_dcbnl_set_valid(bp
) || prio
>= MAX_PFC_PRIORITIES
)
2080 bp
->dcbx_config_params
.admin_pfc_bitmap
|= (1 << prio
);
2081 bp
->dcbx_config_params
.admin_pfc_tx_enable
= 1;
2083 bp
->dcbx_config_params
.admin_pfc_bitmap
&= ~(1 << prio
);
2087 static void bnx2x_dcbnl_get_pfc_cfg(struct net_device
*netdev
, int prio
,
2090 struct bnx2x
*bp
= netdev_priv(netdev
);
2091 DP(BNX2X_MSG_DCB
, "prio = %d\n", prio
);
2095 if (!bp
->dcb_state
|| prio
>= MAX_PFC_PRIORITIES
)
2098 *setting
= (bp
->dcbx_local_feat
.pfc
.pri_en_bitmap
>> prio
) & 0x1;
2101 static u8
bnx2x_dcbnl_set_all(struct net_device
*netdev
)
2103 struct bnx2x
*bp
= netdev_priv(netdev
);
2106 DP(BNX2X_MSG_DCB
, "SET-ALL\n");
2108 if (!bnx2x_dcbnl_set_valid(bp
))
2111 if (bp
->recovery_state
!= BNX2X_RECOVERY_DONE
) {
2113 "Handling parity error recovery. Try again later\n");
2116 if (netif_running(bp
->dev
)) {
2117 bnx2x_update_drv_flags(bp
,
2118 1 << DRV_FLAGS_DCB_MFW_CONFIGURED
,
2120 bnx2x_dcbx_init(bp
, true);
2122 DP(BNX2X_MSG_DCB
, "set_dcbx_params done (%d)\n", rc
);
2129 static u8
bnx2x_dcbnl_get_cap(struct net_device
*netdev
, int capid
, u8
*cap
)
2131 struct bnx2x
*bp
= netdev_priv(netdev
);
2134 if (bp
->dcb_state
) {
2136 case DCB_CAP_ATTR_PG
:
2139 case DCB_CAP_ATTR_PFC
:
2142 case DCB_CAP_ATTR_UP2TC
:
2145 case DCB_CAP_ATTR_PG_TCS
:
2146 *cap
= 0x80; /* 8 priorities for PGs */
2148 case DCB_CAP_ATTR_PFC_TCS
:
2149 *cap
= 0x80; /* 8 priorities for PFC */
2151 case DCB_CAP_ATTR_GSP
:
2154 case DCB_CAP_ATTR_BCN
:
2157 case DCB_CAP_ATTR_DCBX
:
2158 *cap
= BNX2X_DCBX_CAPS
;
2161 BNX2X_ERR("Non valid capability ID\n");
2166 DP(BNX2X_MSG_DCB
, "DCB disabled\n");
2170 DP(BNX2X_MSG_DCB
, "capid %d:%x\n", capid
, *cap
);
2174 static int bnx2x_dcbnl_get_numtcs(struct net_device
*netdev
, int tcid
, u8
*num
)
2176 struct bnx2x
*bp
= netdev_priv(netdev
);
2179 DP(BNX2X_MSG_DCB
, "tcid %d\n", tcid
);
2181 if (bp
->dcb_state
) {
2183 case DCB_NUMTCS_ATTR_PG
:
2184 *num
= CHIP_IS_E3B0(bp
) ? DCBX_COS_MAX_NUM_E3B0
:
2185 DCBX_COS_MAX_NUM_E2
;
2187 case DCB_NUMTCS_ATTR_PFC
:
2188 *num
= CHIP_IS_E3B0(bp
) ? DCBX_COS_MAX_NUM_E3B0
:
2189 DCBX_COS_MAX_NUM_E2
;
2192 BNX2X_ERR("Non valid TC-ID\n");
2197 DP(BNX2X_MSG_DCB
, "DCB disabled\n");
2204 static int bnx2x_dcbnl_set_numtcs(struct net_device
*netdev
, int tcid
, u8 num
)
2206 struct bnx2x
*bp
= netdev_priv(netdev
);
2207 DP(BNX2X_MSG_DCB
, "num tcs = %d; Not supported\n", num
);
2211 static u8
bnx2x_dcbnl_get_pfc_state(struct net_device
*netdev
)
2213 struct bnx2x
*bp
= netdev_priv(netdev
);
2214 DP(BNX2X_MSG_DCB
, "state = %d\n", bp
->dcbx_local_feat
.pfc
.enabled
);
2219 return bp
->dcbx_local_feat
.pfc
.enabled
;
2222 static void bnx2x_dcbnl_set_pfc_state(struct net_device
*netdev
, u8 state
)
2224 struct bnx2x
*bp
= netdev_priv(netdev
);
2225 DP(BNX2X_MSG_DCB
, "state = %s\n", state
? "on" : "off");
2227 if (!bnx2x_dcbnl_set_valid(bp
))
2230 bp
->dcbx_config_params
.admin_pfc_tx_enable
=
2231 bp
->dcbx_config_params
.admin_pfc_enable
= (state
? 1 : 0);
2234 static void bnx2x_admin_app_set_ent(
2235 struct bnx2x_admin_priority_app_table
*app_ent
,
2236 u8 idtype
, u16 idval
, u8 up
)
2241 case DCB_APP_IDTYPE_ETHTYPE
:
2242 app_ent
->traffic_type
= TRAFFIC_TYPE_ETH
;
2244 case DCB_APP_IDTYPE_PORTNUM
:
2245 app_ent
->traffic_type
= TRAFFIC_TYPE_PORT
;
2248 break; /* never gets here */
2250 app_ent
->app_id
= idval
;
2251 app_ent
->priority
= up
;
2254 static bool bnx2x_admin_app_is_equal(
2255 struct bnx2x_admin_priority_app_table
*app_ent
,
2256 u8 idtype
, u16 idval
)
2258 if (!app_ent
->valid
)
2262 case DCB_APP_IDTYPE_ETHTYPE
:
2263 if (app_ent
->traffic_type
!= TRAFFIC_TYPE_ETH
)
2266 case DCB_APP_IDTYPE_PORTNUM
:
2267 if (app_ent
->traffic_type
!= TRAFFIC_TYPE_PORT
)
2273 if (app_ent
->app_id
!= idval
)
2279 static int bnx2x_set_admin_app_up(struct bnx2x
*bp
, u8 idtype
, u16 idval
, u8 up
)
2283 /* iterate over the app entries looking for idtype and idval */
2284 for (i
= 0, ff
= -1; i
< DCBX_CONFIG_MAX_APP_PROTOCOL
; i
++) {
2285 struct bnx2x_admin_priority_app_table
*app_ent
=
2286 &bp
->dcbx_config_params
.admin_priority_app_table
[i
];
2287 if (bnx2x_admin_app_is_equal(app_ent
, idtype
, idval
))
2290 if (ff
< 0 && !app_ent
->valid
)
2293 if (i
< DCBX_CONFIG_MAX_APP_PROTOCOL
)
2294 /* if found overwrite up */
2295 bp
->dcbx_config_params
.
2296 admin_priority_app_table
[i
].priority
= up
;
2298 /* not found use first-free */
2299 bnx2x_admin_app_set_ent(
2300 &bp
->dcbx_config_params
.admin_priority_app_table
[ff
],
2303 /* app table is full */
2304 BNX2X_ERR("Application table is too large\n");
2308 /* up configured, if not 0 make sure feature is enabled */
2310 bp
->dcbx_config_params
.admin_application_priority_tx_enable
= 1;
2315 static u8
bnx2x_dcbnl_set_app_up(struct net_device
*netdev
, u8 idtype
,
2318 struct bnx2x
*bp
= netdev_priv(netdev
);
2320 DP(BNX2X_MSG_DCB
, "app_type %d, app_id %x, prio bitmap %d\n",
2323 if (!bnx2x_dcbnl_set_valid(bp
)) {
2324 DP(BNX2X_MSG_DCB
, "dcbnl call not valid\n");
2330 case DCB_APP_IDTYPE_ETHTYPE
:
2331 case DCB_APP_IDTYPE_PORTNUM
:
2334 DP(BNX2X_MSG_DCB
, "Wrong ID type\n");
2337 return bnx2x_set_admin_app_up(bp
, idtype
, idval
, up
);
2340 static u8
bnx2x_dcbnl_get_dcbx(struct net_device
*netdev
)
2342 struct bnx2x
*bp
= netdev_priv(netdev
);
2345 state
= DCB_CAP_DCBX_LLD_MANAGED
| DCB_CAP_DCBX_VER_CEE
;
2347 if (bp
->dcbx_enabled
== BNX2X_DCBX_ENABLED_ON_NEG_OFF
)
2348 state
|= DCB_CAP_DCBX_STATIC
;
2353 static u8
bnx2x_dcbnl_set_dcbx(struct net_device
*netdev
, u8 state
)
2355 struct bnx2x
*bp
= netdev_priv(netdev
);
2356 DP(BNX2X_MSG_DCB
, "state = %02x\n", state
);
2360 if ((state
& BNX2X_DCBX_CAPS
) != state
) {
2361 BNX2X_ERR("Requested DCBX mode %x is beyond advertised capabilities\n",
2366 if (bp
->dcb_state
!= BNX2X_DCB_STATE_ON
) {
2367 BNX2X_ERR("DCB turned off, DCBX configuration is invalid\n");
2371 if (state
& DCB_CAP_DCBX_STATIC
)
2372 bp
->dcbx_enabled
= BNX2X_DCBX_ENABLED_ON_NEG_OFF
;
2374 bp
->dcbx_enabled
= BNX2X_DCBX_ENABLED_ON_NEG_ON
;
2376 bp
->dcbx_mode_uset
= true;
2380 static u8
bnx2x_dcbnl_get_featcfg(struct net_device
*netdev
, int featid
,
2383 struct bnx2x
*bp
= netdev_priv(netdev
);
2386 DP(BNX2X_MSG_DCB
, "featid %d\n", featid
);
2388 if (bp
->dcb_state
) {
2391 case DCB_FEATCFG_ATTR_PG
:
2392 if (bp
->dcbx_local_feat
.ets
.enabled
)
2393 *flags
|= DCB_FEATCFG_ENABLE
;
2394 if (bp
->dcbx_error
& DCBX_LOCAL_ETS_ERROR
)
2395 *flags
|= DCB_FEATCFG_ERROR
;
2397 case DCB_FEATCFG_ATTR_PFC
:
2398 if (bp
->dcbx_local_feat
.pfc
.enabled
)
2399 *flags
|= DCB_FEATCFG_ENABLE
;
2400 if (bp
->dcbx_error
& (DCBX_LOCAL_PFC_ERROR
|
2401 DCBX_LOCAL_PFC_MISMATCH
))
2402 *flags
|= DCB_FEATCFG_ERROR
;
2404 case DCB_FEATCFG_ATTR_APP
:
2405 if (bp
->dcbx_local_feat
.app
.enabled
)
2406 *flags
|= DCB_FEATCFG_ENABLE
;
2407 if (bp
->dcbx_error
& (DCBX_LOCAL_APP_ERROR
|
2408 DCBX_LOCAL_APP_MISMATCH
))
2409 *flags
|= DCB_FEATCFG_ERROR
;
2412 BNX2X_ERR("Non valid feature-ID\n");
2417 DP(BNX2X_MSG_DCB
, "DCB disabled\n");
2424 static u8
bnx2x_dcbnl_set_featcfg(struct net_device
*netdev
, int featid
,
2427 struct bnx2x
*bp
= netdev_priv(netdev
);
2430 DP(BNX2X_MSG_DCB
, "featid = %d flags = %02x\n", featid
, flags
);
2432 /* ignore the 'advertise' flag */
2433 if (bnx2x_dcbnl_set_valid(bp
)) {
2435 case DCB_FEATCFG_ATTR_PG
:
2436 bp
->dcbx_config_params
.admin_ets_enable
=
2437 flags
& DCB_FEATCFG_ENABLE
? 1 : 0;
2438 bp
->dcbx_config_params
.admin_ets_willing
=
2439 flags
& DCB_FEATCFG_WILLING
? 1 : 0;
2441 case DCB_FEATCFG_ATTR_PFC
:
2442 bp
->dcbx_config_params
.admin_pfc_enable
=
2443 flags
& DCB_FEATCFG_ENABLE
? 1 : 0;
2444 bp
->dcbx_config_params
.admin_pfc_willing
=
2445 flags
& DCB_FEATCFG_WILLING
? 1 : 0;
2447 case DCB_FEATCFG_ATTR_APP
:
2448 /* ignore enable, always enabled */
2449 bp
->dcbx_config_params
.admin_app_priority_willing
=
2450 flags
& DCB_FEATCFG_WILLING
? 1 : 0;
2453 BNX2X_ERR("Non valid feature-ID\n");
2458 DP(BNX2X_MSG_DCB
, "dcbnl call not valid\n");
2465 static int bnx2x_peer_appinfo(struct net_device
*netdev
,
2466 struct dcb_peer_app_info
*info
, u16
* app_count
)
2469 struct bnx2x
*bp
= netdev_priv(netdev
);
2471 DP(BNX2X_MSG_DCB
, "APP-INFO\n");
2473 info
->willing
= (bp
->dcbx_remote_flags
& DCBX_APP_REM_WILLING
) ?: 0;
2474 info
->error
= (bp
->dcbx_remote_flags
& DCBX_APP_RX_ERROR
) ?: 0;
2477 for (i
= 0; i
< DCBX_MAX_APP_PROTOCOL
; i
++)
2478 if (bp
->dcbx_remote_feat
.app
.app_pri_tbl
[i
].appBitfield
&
2479 DCBX_APP_ENTRY_VALID
)
2484 static int bnx2x_peer_apptable(struct net_device
*netdev
,
2485 struct dcb_app
*table
)
2488 struct bnx2x
*bp
= netdev_priv(netdev
);
2490 DP(BNX2X_MSG_DCB
, "APP-TABLE\n");
2492 for (i
= 0, j
= 0; i
< DCBX_MAX_APP_PROTOCOL
; i
++) {
2493 struct dcbx_app_priority_entry
*ent
=
2494 &bp
->dcbx_remote_feat
.app
.app_pri_tbl
[i
];
2496 if (ent
->appBitfield
& DCBX_APP_ENTRY_VALID
) {
2497 table
[j
].selector
= bnx2x_dcbx_dcbnl_app_idtype(ent
);
2498 table
[j
].priority
= bnx2x_dcbx_dcbnl_app_up(ent
);
2499 table
[j
++].protocol
= ent
->app_id
;
2505 static int bnx2x_cee_peer_getpg(struct net_device
*netdev
, struct cee_pg
*pg
)
2508 struct bnx2x
*bp
= netdev_priv(netdev
);
2510 pg
->willing
= (bp
->dcbx_remote_flags
& DCBX_ETS_REM_WILLING
) ?: 0;
2512 for (i
= 0; i
< CEE_DCBX_MAX_PGS
; i
++) {
2514 DCBX_PG_BW_GET(bp
->dcbx_remote_feat
.ets
.pg_bw_tbl
, i
);
2516 DCBX_PRI_PG_GET(bp
->dcbx_remote_feat
.ets
.pri_pg_tbl
, i
);
2521 static int bnx2x_cee_peer_getpfc(struct net_device
*netdev
,
2522 struct cee_pfc
*pfc
)
2524 struct bnx2x
*bp
= netdev_priv(netdev
);
2525 pfc
->tcs_supported
= bp
->dcbx_remote_feat
.pfc
.pfc_caps
;
2526 pfc
->pfc_en
= bp
->dcbx_remote_feat
.pfc
.pri_en_bitmap
;
2530 const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops
= {
2531 .getstate
= bnx2x_dcbnl_get_state
,
2532 .setstate
= bnx2x_dcbnl_set_state
,
2533 .getpermhwaddr
= bnx2x_dcbnl_get_perm_hw_addr
,
2534 .setpgtccfgtx
= bnx2x_dcbnl_set_pg_tccfg_tx
,
2535 .setpgbwgcfgtx
= bnx2x_dcbnl_set_pg_bwgcfg_tx
,
2536 .setpgtccfgrx
= bnx2x_dcbnl_set_pg_tccfg_rx
,
2537 .setpgbwgcfgrx
= bnx2x_dcbnl_set_pg_bwgcfg_rx
,
2538 .getpgtccfgtx
= bnx2x_dcbnl_get_pg_tccfg_tx
,
2539 .getpgbwgcfgtx
= bnx2x_dcbnl_get_pg_bwgcfg_tx
,
2540 .getpgtccfgrx
= bnx2x_dcbnl_get_pg_tccfg_rx
,
2541 .getpgbwgcfgrx
= bnx2x_dcbnl_get_pg_bwgcfg_rx
,
2542 .setpfccfg
= bnx2x_dcbnl_set_pfc_cfg
,
2543 .getpfccfg
= bnx2x_dcbnl_get_pfc_cfg
,
2544 .setall
= bnx2x_dcbnl_set_all
,
2545 .getcap
= bnx2x_dcbnl_get_cap
,
2546 .getnumtcs
= bnx2x_dcbnl_get_numtcs
,
2547 .setnumtcs
= bnx2x_dcbnl_set_numtcs
,
2548 .getpfcstate
= bnx2x_dcbnl_get_pfc_state
,
2549 .setpfcstate
= bnx2x_dcbnl_set_pfc_state
,
2550 .setapp
= bnx2x_dcbnl_set_app_up
,
2551 .getdcbx
= bnx2x_dcbnl_get_dcbx
,
2552 .setdcbx
= bnx2x_dcbnl_set_dcbx
,
2553 .getfeatcfg
= bnx2x_dcbnl_get_featcfg
,
2554 .setfeatcfg
= bnx2x_dcbnl_set_featcfg
,
2555 .peer_getappinfo
= bnx2x_peer_appinfo
,
2556 .peer_getapptable
= bnx2x_peer_apptable
,
2557 .cee_peer_getpg
= bnx2x_cee_peer_getpg
,
2558 .cee_peer_getpfc
= bnx2x_cee_peer_getpfc
,
2561 #endif /* BCM_DCBNL */