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 int bnx2x_dcbx_stop_hw_tx(struct bnx2x
*bp
);
34 static void bnx2x_pfc_set_pfc(struct bnx2x
*bp
);
35 static void bnx2x_dcbx_update_ets_params(struct bnx2x
*bp
);
36 static int bnx2x_dcbx_resume_hw_tx(struct bnx2x
*bp
);
37 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x
*bp
,
38 u32
*set_configuration_ets_pg
,
40 static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x
*bp
,
41 u32
*pg_pri_orginal_spread
,
42 struct pg_help_data
*help_data
);
43 static void bnx2x_dcbx_fill_cos_params(struct bnx2x
*bp
,
44 struct pg_help_data
*help_data
,
45 struct dcbx_ets_feature
*ets
,
46 u32
*pg_pri_orginal_spread
);
47 static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x
*bp
,
48 struct cos_help_data
*cos_data
,
49 u32
*pg_pri_orginal_spread
,
50 struct dcbx_ets_feature
*ets
);
51 static void bnx2x_dcbx_fw_struct(struct bnx2x
*bp
,
52 struct bnx2x_func_tx_start_params
*);
54 /* helpers: read/write len bytes from addr into buff by REG_RD/REG_WR */
55 static void bnx2x_read_data(struct bnx2x
*bp
, u32
*buff
,
59 for (i
= 0; i
< len
; i
+= 4, buff
++)
60 *buff
= REG_RD(bp
, addr
+ i
);
63 static void bnx2x_write_data(struct bnx2x
*bp
, u32
*buff
,
67 for (i
= 0; i
< len
; i
+= 4, buff
++)
68 REG_WR(bp
, addr
+ i
, *buff
);
71 static void bnx2x_pfc_set(struct bnx2x
*bp
)
73 struct bnx2x_nig_brb_pfc_port_params pfc_params
= {0};
77 pfc_params
.num_of_rx_cos_priority_mask
=
78 bp
->dcbx_port_params
.ets
.num_of_cos
;
80 /* Tx COS configuration */
81 for (i
= 0; i
< bp
->dcbx_port_params
.ets
.num_of_cos
; i
++)
83 * We configure only the pauseable bits (non pauseable aren't
84 * configured at all) it's done to avoid false pauses from
87 pfc_params
.rx_cos_priority_mask
[i
] =
88 bp
->dcbx_port_params
.ets
.cos_params
[i
].pri_bitmask
89 & DCBX_PFC_PRI_PAUSE_MASK(bp
);
92 * Rx COS configuration
93 * Changing PFC RX configuration .
94 * In RX COS0 will always be configured to lossless and COS1 to lossy
96 for (i
= 0 ; i
< MAX_PFC_PRIORITIES
; i
++) {
99 if (!(pri_bit
& DCBX_PFC_PRI_PAUSE_MASK(bp
)))
103 pfc_params
.pkt_priority_to_cos
= val
;
106 pfc_params
.llfc_low_priority_classes
= DCBX_PFC_PRI_PAUSE_MASK(bp
);
108 pfc_params
.llfc_high_priority_classes
= 0;
110 bnx2x_acquire_phy_lock(bp
);
111 bp
->link_params
.feature_config_flags
|= FEATURE_CONFIG_PFC_ENABLED
;
112 bnx2x_update_pfc(&bp
->link_params
, &bp
->link_vars
, &pfc_params
);
113 bnx2x_release_phy_lock(bp
);
116 static void bnx2x_pfc_clear(struct bnx2x
*bp
)
118 struct bnx2x_nig_brb_pfc_port_params nig_params
= {0};
119 nig_params
.pause_enable
= 1;
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
);
126 static void bnx2x_dump_dcbx_drv_param(struct bnx2x
*bp
,
127 struct dcbx_features
*features
,
131 DP(NETIF_MSG_LINK
, "local_mib.error %x\n", error
);
135 "local_mib.features.ets.enabled %x\n", features
->ets
.enabled
);
136 for (i
= 0; i
< DCBX_MAX_NUM_PG_BW_ENTRIES
; i
++)
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
++)
142 "local_mib.features.ets.pri_pg_tbl[%d] %d\n", i
,
143 DCBX_PRI_PG_GET(features
->ets
.pri_pg_tbl
, i
));
146 DP(BNX2X_MSG_DCB
, "dcbx_features.pfc.pri_en_bitmap %x\n",
147 features
->pfc
.pri_en_bitmap
);
148 DP(BNX2X_MSG_DCB
, "dcbx_features.pfc.pfc_caps %x\n",
149 features
->pfc
.pfc_caps
);
150 DP(BNX2X_MSG_DCB
, "dcbx_features.pfc.enabled %x\n",
151 features
->pfc
.enabled
);
153 DP(BNX2X_MSG_DCB
, "dcbx_features.app.default_pri %x\n",
154 features
->app
.default_pri
);
155 DP(BNX2X_MSG_DCB
, "dcbx_features.app.tc_supported %x\n",
156 features
->app
.tc_supported
);
157 DP(BNX2X_MSG_DCB
, "dcbx_features.app.enabled %x\n",
158 features
->app
.enabled
);
159 for (i
= 0; i
< DCBX_MAX_APP_PROTOCOL
; i
++) {
161 "dcbx_features.app.app_pri_tbl[%x].app_id %x\n",
162 i
, features
->app
.app_pri_tbl
[i
].app_id
);
164 "dcbx_features.app.app_pri_tbl[%x].pri_bitmap %x\n",
165 i
, features
->app
.app_pri_tbl
[i
].pri_bitmap
);
167 "dcbx_features.app.app_pri_tbl[%x].appBitfield %x\n",
168 i
, features
->app
.app_pri_tbl
[i
].appBitfield
);
172 static void bnx2x_dcbx_get_ap_priority(struct bnx2x
*bp
,
176 u32 pri
= MAX_PFC_PRIORITIES
;
177 u32 index
= MAX_PFC_PRIORITIES
- 1;
179 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
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
))
189 if (pri
< MAX_PFC_PRIORITIES
)
190 ttp
[llfc_traf_type
] = max_t(u32
, ttp
[llfc_traf_type
], pri
);
193 static void bnx2x_dcbx_get_ap_feature(struct bnx2x
*bp
,
194 struct dcbx_app_priority_feature
*app
,
197 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
199 if (GET_FLAGS(error
, DCBX_LOCAL_APP_ERROR
))
200 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_APP_ERROR\n");
202 if (GET_FLAGS(error
, DCBX_LOCAL_APP_MISMATCH
))
203 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_APP_MISMATCH\n");
205 if (GET_FLAGS(error
, DCBX_REMOTE_APP_TLV_NOT_FOUND
))
206 DP(BNX2X_MSG_DCB
, "DCBX_REMOTE_APP_TLV_NOT_FOUND\n");
208 !GET_FLAGS(error
, DCBX_LOCAL_APP_ERROR
| DCBX_LOCAL_APP_MISMATCH
|
209 DCBX_REMOTE_APP_TLV_NOT_FOUND
)) {
211 bp
->dcbx_port_params
.app
.enabled
= true;
213 for (index
= 0 ; index
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; index
++)
216 if (app
->default_pri
< MAX_PFC_PRIORITIES
)
217 ttp
[LLFC_TRAFFIC_TYPE_NW
] = app
->default_pri
;
219 for (index
= 0 ; index
< DCBX_MAX_APP_PROTOCOL
; index
++) {
220 struct dcbx_app_priority_entry
*entry
=
223 if (GET_FLAGS(entry
[index
].appBitfield
,
224 DCBX_APP_SF_ETH_TYPE
) &&
225 ETH_TYPE_FCOE
== entry
[index
].app_id
)
226 bnx2x_dcbx_get_ap_priority(bp
,
227 entry
[index
].pri_bitmap
,
228 LLFC_TRAFFIC_TYPE_FCOE
);
230 if (GET_FLAGS(entry
[index
].appBitfield
,
232 TCP_PORT_ISCSI
== entry
[index
].app_id
)
233 bnx2x_dcbx_get_ap_priority(bp
,
234 entry
[index
].pri_bitmap
,
235 LLFC_TRAFFIC_TYPE_ISCSI
);
238 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_APP_DISABLED\n");
239 bp
->dcbx_port_params
.app
.enabled
= false;
240 for (index
= 0 ; index
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; index
++)
241 ttp
[index
] = INVALID_TRAFFIC_TYPE_PRIORITY
;
245 static void bnx2x_dcbx_get_ets_feature(struct bnx2x
*bp
,
246 struct dcbx_ets_feature
*ets
,
249 u32 pg_pri_orginal_spread
[DCBX_MAX_NUM_PG_BW_ENTRIES
] = {0};
250 struct pg_help_data pg_help_data
;
251 struct bnx2x_dcbx_cos_params
*cos_params
=
252 bp
->dcbx_port_params
.ets
.cos_params
;
254 memset(&pg_help_data
, 0, sizeof(struct pg_help_data
));
256 if (GET_FLAGS(error
, DCBX_LOCAL_ETS_ERROR
))
257 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_ETS_ERROR\n");
259 if (GET_FLAGS(error
, DCBX_REMOTE_ETS_TLV_NOT_FOUND
))
260 DP(BNX2X_MSG_DCB
, "DCBX_REMOTE_ETS_TLV_NOT_FOUND\n");
262 /* Clean up old settings of ets on COS */
263 for (i
= 0; i
< ARRAY_SIZE(bp
->dcbx_port_params
.ets
.cos_params
) ; i
++) {
264 cos_params
[i
].pauseable
= false;
265 cos_params
[i
].strict
= BNX2X_DCBX_STRICT_INVALID
;
266 cos_params
[i
].bw_tbl
= DCBX_INVALID_COS_BW
;
267 cos_params
[i
].pri_bitmask
= 0;
270 if (bp
->dcbx_port_params
.app
.enabled
&& ets
->enabled
&&
272 DCBX_LOCAL_ETS_ERROR
| DCBX_REMOTE_ETS_TLV_NOT_FOUND
)) {
273 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_ETS_ENABLE\n");
274 bp
->dcbx_port_params
.ets
.enabled
= true;
276 bnx2x_dcbx_get_ets_pri_pg_tbl(bp
,
277 pg_pri_orginal_spread
,
280 bnx2x_dcbx_get_num_pg_traf_type(bp
,
281 pg_pri_orginal_spread
,
284 bnx2x_dcbx_fill_cos_params(bp
, &pg_help_data
,
285 ets
, pg_pri_orginal_spread
);
288 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_ETS_DISABLED\n");
289 bp
->dcbx_port_params
.ets
.enabled
= false;
290 ets
->pri_pg_tbl
[0] = 0;
292 for (i
= 0; i
< DCBX_MAX_NUM_PRI_PG_ENTRIES
; i
++)
293 DCBX_PG_BW_SET(ets
->pg_bw_tbl
, i
, 1);
297 static void bnx2x_dcbx_get_pfc_feature(struct bnx2x
*bp
,
298 struct dcbx_pfc_feature
*pfc
, u32 error
)
300 if (GET_FLAGS(error
, DCBX_LOCAL_PFC_ERROR
))
301 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_PFC_ERROR\n");
303 if (GET_FLAGS(error
, DCBX_REMOTE_PFC_TLV_NOT_FOUND
))
304 DP(BNX2X_MSG_DCB
, "DCBX_REMOTE_PFC_TLV_NOT_FOUND\n");
305 if (bp
->dcbx_port_params
.app
.enabled
&& pfc
->enabled
&&
306 !GET_FLAGS(error
, DCBX_LOCAL_PFC_ERROR
| DCBX_LOCAL_PFC_MISMATCH
|
307 DCBX_REMOTE_PFC_TLV_NOT_FOUND
)) {
308 bp
->dcbx_port_params
.pfc
.enabled
= true;
309 bp
->dcbx_port_params
.pfc
.priority_non_pauseable_mask
=
310 ~(pfc
->pri_en_bitmap
);
312 DP(BNX2X_MSG_DCB
, "DCBX_LOCAL_PFC_DISABLED\n");
313 bp
->dcbx_port_params
.pfc
.enabled
= false;
314 bp
->dcbx_port_params
.pfc
.priority_non_pauseable_mask
= 0;
318 /* maps unmapped priorities to to the same COS as L2 */
319 static void bnx2x_dcbx_map_nw(struct bnx2x
*bp
)
322 u32 unmapped
= (1 << MAX_PFC_PRIORITIES
) - 1; /* all ones */
323 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
324 u32 nw_prio
= 1 << ttp
[LLFC_TRAFFIC_TYPE_NW
];
325 struct bnx2x_dcbx_cos_params
*cos_params
=
326 bp
->dcbx_port_params
.ets
.cos_params
;
328 /* get unmapped priorities by clearing mapped bits */
329 for (i
= 0; i
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; i
++)
330 unmapped
&= ~(1 << ttp
[i
]);
332 /* find cos for nw prio and extend it with unmapped */
333 for (i
= 0; i
< ARRAY_SIZE(bp
->dcbx_port_params
.ets
.cos_params
); i
++) {
334 if (cos_params
[i
].pri_bitmask
& nw_prio
) {
335 /* extend the bitmask with unmapped */
337 "cos %d extended with 0x%08x\n", i
, unmapped
);
338 cos_params
[i
].pri_bitmask
|= unmapped
;
344 static void bnx2x_get_dcbx_drv_param(struct bnx2x
*bp
,
345 struct dcbx_features
*features
,
348 bnx2x_dcbx_get_ap_feature(bp
, &features
->app
, error
);
350 bnx2x_dcbx_get_pfc_feature(bp
, &features
->pfc
, error
);
352 bnx2x_dcbx_get_ets_feature(bp
, &features
->ets
, error
);
354 bnx2x_dcbx_map_nw(bp
);
357 #define DCBX_LOCAL_MIB_MAX_TRY_READ (100)
358 static int bnx2x_dcbx_read_mib(struct bnx2x
*bp
,
363 int max_try_read
= 0;
364 u32 mib_size
, prefix_seq_num
, suffix_seq_num
;
365 struct lldp_remote_mib
*remote_mib
;
366 struct lldp_local_mib
*local_mib
;
368 switch (read_mib_type
) {
369 case DCBX_READ_LOCAL_MIB
:
370 mib_size
= sizeof(struct lldp_local_mib
);
372 case DCBX_READ_REMOTE_MIB
:
373 mib_size
= sizeof(struct lldp_remote_mib
);
379 offset
+= BP_PORT(bp
) * mib_size
;
382 bnx2x_read_data(bp
, base_mib_addr
, offset
, mib_size
);
386 switch (read_mib_type
) {
387 case DCBX_READ_LOCAL_MIB
:
388 local_mib
= (struct lldp_local_mib
*) base_mib_addr
;
389 prefix_seq_num
= local_mib
->prefix_seq_num
;
390 suffix_seq_num
= local_mib
->suffix_seq_num
;
392 case DCBX_READ_REMOTE_MIB
:
393 remote_mib
= (struct lldp_remote_mib
*) base_mib_addr
;
394 prefix_seq_num
= remote_mib
->prefix_seq_num
;
395 suffix_seq_num
= remote_mib
->suffix_seq_num
;
400 } while ((prefix_seq_num
!= suffix_seq_num
) &&
401 (max_try_read
< DCBX_LOCAL_MIB_MAX_TRY_READ
));
403 if (max_try_read
>= DCBX_LOCAL_MIB_MAX_TRY_READ
) {
404 BNX2X_ERR("MIB could not be read\n");
411 static void bnx2x_pfc_set_pfc(struct bnx2x
*bp
)
413 int mfw_configured
= SHMEM2_HAS(bp
, drv_flags
) &&
414 GET_FLAGS(SHMEM2_RD(bp
, drv_flags
),
415 1 << DRV_FLAGS_DCB_MFW_CONFIGURED
);
417 if (bp
->dcbx_port_params
.pfc
.enabled
&&
418 (!(bp
->dcbx_error
& DCBX_REMOTE_MIB_ERROR
) || mfw_configured
))
420 * 1. Fills up common PFC structures if required
421 * 2. Configure NIG, MAC and BRB via the elink
428 static int bnx2x_dcbx_stop_hw_tx(struct bnx2x
*bp
)
430 struct bnx2x_func_state_params func_params
= {NULL
};
432 func_params
.f_obj
= &bp
->func_obj
;
433 func_params
.cmd
= BNX2X_F_CMD_TX_STOP
;
435 DP(BNX2X_MSG_DCB
, "STOP TRAFFIC\n");
436 return bnx2x_func_state_change(bp
, &func_params
);
439 static int bnx2x_dcbx_resume_hw_tx(struct bnx2x
*bp
)
441 struct bnx2x_func_state_params func_params
= {NULL
};
442 struct bnx2x_func_tx_start_params
*tx_params
=
443 &func_params
.params
.tx_start
;
445 func_params
.f_obj
= &bp
->func_obj
;
446 func_params
.cmd
= BNX2X_F_CMD_TX_START
;
448 bnx2x_dcbx_fw_struct(bp
, tx_params
);
450 DP(BNX2X_MSG_DCB
, "START TRAFFIC\n");
451 return bnx2x_func_state_change(bp
, &func_params
);
454 static void bnx2x_dcbx_2cos_limit_update_ets_config(struct bnx2x
*bp
)
456 struct bnx2x_dcbx_pg_params
*ets
= &(bp
->dcbx_port_params
.ets
);
459 if (ets
->num_of_cos
== 0 || ets
->num_of_cos
> DCBX_COS_MAX_NUM_E2
) {
460 BNX2X_ERR("Illegal number of COSes %d\n", ets
->num_of_cos
);
464 /* valid COS entries */
465 if (ets
->num_of_cos
== 1) /* no ETS */
469 if (((BNX2X_DCBX_STRICT_INVALID
== ets
->cos_params
[0].strict
) &&
470 (DCBX_INVALID_COS_BW
== ets
->cos_params
[0].bw_tbl
)) ||
471 ((BNX2X_DCBX_STRICT_INVALID
== ets
->cos_params
[1].strict
) &&
472 (DCBX_INVALID_COS_BW
== ets
->cos_params
[1].bw_tbl
))) {
473 BNX2X_ERR("all COS should have at least bw_limit or strict"
474 "ets->cos_params[0].strict= %x"
475 "ets->cos_params[0].bw_tbl= %x"
476 "ets->cos_params[1].strict= %x"
477 "ets->cos_params[1].bw_tbl= %x",
478 ets
->cos_params
[0].strict
,
479 ets
->cos_params
[0].bw_tbl
,
480 ets
->cos_params
[1].strict
,
481 ets
->cos_params
[1].bw_tbl
);
484 /* If we join a group and there is bw_tbl and strict then bw rules */
485 if ((DCBX_INVALID_COS_BW
!= ets
->cos_params
[0].bw_tbl
) &&
486 (DCBX_INVALID_COS_BW
!= ets
->cos_params
[1].bw_tbl
)) {
487 u32 bw_tbl_0
= ets
->cos_params
[0].bw_tbl
;
488 u32 bw_tbl_1
= ets
->cos_params
[1].bw_tbl
;
489 /* Do not allow 0-100 configuration
490 * since PBF does not support it
496 } else if (bw_tbl_1
== 0) {
501 bnx2x_ets_bw_limit(&bp
->link_params
, bw_tbl_0
, bw_tbl_1
);
503 if (ets
->cos_params
[0].strict
== BNX2X_DCBX_STRICT_COS_HIGHEST
)
504 rc
= bnx2x_ets_strict(&bp
->link_params
, 0);
505 else if (ets
->cos_params
[1].strict
506 == BNX2X_DCBX_STRICT_COS_HIGHEST
)
507 rc
= bnx2x_ets_strict(&bp
->link_params
, 1);
509 BNX2X_ERR("update_ets_params failed\n");
514 * In E3B0 the configuration may have more than 2 COS.
516 static void bnx2x_dcbx_update_ets_config(struct bnx2x
*bp
)
518 struct bnx2x_dcbx_pg_params
*ets
= &(bp
->dcbx_port_params
.ets
);
519 struct bnx2x_ets_params ets_params
= { 0 };
522 ets_params
.num_of_cos
= ets
->num_of_cos
;
524 for (i
= 0; i
< ets
->num_of_cos
; i
++) {
526 if (ets
->cos_params
[i
].strict
!= BNX2X_DCBX_STRICT_INVALID
) {
527 if (ets
->cos_params
[i
].bw_tbl
!= DCBX_INVALID_COS_BW
) {
528 BNX2X_ERR("COS can't be not BW and not SP\n");
532 ets_params
.cos
[i
].state
= bnx2x_cos_state_strict
;
533 ets_params
.cos
[i
].params
.sp_params
.pri
=
534 ets
->cos_params
[i
].strict
;
535 } else { /* COS is BW */
536 if (ets
->cos_params
[i
].bw_tbl
== DCBX_INVALID_COS_BW
) {
537 BNX2X_ERR("COS can't be not BW and not SP\n");
540 ets_params
.cos
[i
].state
= bnx2x_cos_state_bw
;
541 ets_params
.cos
[i
].params
.bw_params
.bw
=
542 (u8
)ets
->cos_params
[i
].bw_tbl
;
546 /* Configure the ETS in HW */
547 if (bnx2x_ets_e3b0_config(&bp
->link_params
, &bp
->link_vars
,
549 BNX2X_ERR("bnx2x_ets_e3b0_config failed\n");
550 bnx2x_ets_disabled(&bp
->link_params
, &bp
->link_vars
);
554 static void bnx2x_dcbx_update_ets_params(struct bnx2x
*bp
)
556 int mfw_configured
= SHMEM2_HAS(bp
, drv_flags
) &&
557 GET_FLAGS(SHMEM2_RD(bp
, drv_flags
),
558 1 << DRV_FLAGS_DCB_MFW_CONFIGURED
);
560 bnx2x_ets_disabled(&bp
->link_params
, &bp
->link_vars
);
562 if (!bp
->dcbx_port_params
.ets
.enabled
||
563 ((bp
->dcbx_error
& DCBX_REMOTE_MIB_ERROR
) && !mfw_configured
))
566 if (CHIP_IS_E3B0(bp
))
567 bnx2x_dcbx_update_ets_config(bp
);
569 bnx2x_dcbx_2cos_limit_update_ets_config(bp
);
573 static int bnx2x_dcbx_read_shmem_remote_mib(struct bnx2x
*bp
)
575 struct lldp_remote_mib remote_mib
= {0};
576 u32 dcbx_remote_mib_offset
= SHMEM2_RD(bp
, dcbx_remote_mib_offset
);
579 DP(BNX2X_MSG_DCB
, "dcbx_remote_mib_offset 0x%x\n",
580 dcbx_remote_mib_offset
);
582 if (SHMEM_DCBX_REMOTE_MIB_NONE
== dcbx_remote_mib_offset
) {
583 BNX2X_ERR("FW doesn't support dcbx_remote_mib_offset\n");
587 rc
= bnx2x_dcbx_read_mib(bp
, (u32
*)&remote_mib
, dcbx_remote_mib_offset
,
588 DCBX_READ_REMOTE_MIB
);
591 BNX2X_ERR("Failed to read remote mib from FW\n");
595 /* save features and flags */
596 bp
->dcbx_remote_feat
= remote_mib
.features
;
597 bp
->dcbx_remote_flags
= remote_mib
.flags
;
602 static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x
*bp
)
604 struct lldp_local_mib local_mib
= {0};
605 u32 dcbx_neg_res_offset
= SHMEM2_RD(bp
, dcbx_neg_res_offset
);
608 DP(BNX2X_MSG_DCB
, "dcbx_neg_res_offset 0x%x\n", dcbx_neg_res_offset
);
610 if (SHMEM_DCBX_NEG_RES_NONE
== dcbx_neg_res_offset
) {
611 BNX2X_ERR("FW doesn't support dcbx_neg_res_offset\n");
615 rc
= bnx2x_dcbx_read_mib(bp
, (u32
*)&local_mib
, dcbx_neg_res_offset
,
616 DCBX_READ_LOCAL_MIB
);
619 BNX2X_ERR("Failed to read local mib from FW\n");
623 /* save features and error */
624 bp
->dcbx_local_feat
= local_mib
.features
;
625 bp
->dcbx_error
= local_mib
.error
;
631 u8
bnx2x_dcbx_dcbnl_app_up(struct dcbx_app_priority_entry
*ent
)
635 /* Choose the highest priority */
636 for (pri
= MAX_PFC_PRIORITIES
- 1; pri
> 0; pri
--)
637 if (ent
->pri_bitmap
& (1 << pri
))
643 u8
bnx2x_dcbx_dcbnl_app_idtype(struct dcbx_app_priority_entry
*ent
)
645 return ((ent
->appBitfield
& DCBX_APP_ENTRY_SF_MASK
) ==
646 DCBX_APP_SF_PORT
) ? DCB_APP_IDTYPE_PORTNUM
:
647 DCB_APP_IDTYPE_ETHTYPE
;
650 int bnx2x_dcbnl_update_applist(struct bnx2x
*bp
, bool delall
)
654 for (i
= 0; i
< DCBX_MAX_APP_PROTOCOL
&& err
== 0; i
++) {
655 struct dcbx_app_priority_entry
*ent
=
656 &bp
->dcbx_local_feat
.app
.app_pri_tbl
[i
];
658 if (ent
->appBitfield
& DCBX_APP_ENTRY_VALID
) {
659 u8 up
= bnx2x_dcbx_dcbnl_app_up(ent
);
661 /* avoid invalid user-priority */
664 app
.selector
= bnx2x_dcbx_dcbnl_app_idtype(ent
);
665 app
.protocol
= ent
->app_id
;
666 app
.priority
= delall
? 0 : up
;
667 err
= dcb_setapp(bp
->dev
, &app
);
675 static inline void bnx2x_dcbx_update_tc_mapping(struct bnx2x
*bp
)
678 for (cos
= 0; cos
< bp
->dcbx_port_params
.ets
.num_of_cos
; cos
++) {
679 for (prio
= 0; prio
< BNX2X_MAX_PRIORITY
; prio
++) {
680 if (bp
->dcbx_port_params
.ets
.cos_params
[cos
].pri_bitmask
682 bp
->prio_to_cos
[prio
] = cos
;
684 "tx_mapping %d --> %d\n", prio
, cos
);
689 /* setup tc must be called under rtnl lock, but we can't take it here
690 * as we are handling an attention on a work queue which must be
691 * flushed at some rtnl-locked contexts (e.g. if down)
693 if (!test_and_set_bit(BNX2X_SP_RTNL_SETUP_TC
, &bp
->sp_rtnl_state
))
694 schedule_delayed_work(&bp
->sp_rtnl_task
, 0);
697 void bnx2x_dcbx_set_params(struct bnx2x
*bp
, u32 state
)
700 case BNX2X_DCBX_STATE_NEG_RECEIVED
:
702 DP(BNX2X_MSG_DCB
, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
705 * Delete app tlvs from dcbnl before reading new
706 * negotiation results
708 bnx2x_dcbnl_update_applist(bp
, true);
710 /* Read remote mib if dcbx is in the FW */
711 if (bnx2x_dcbx_read_shmem_remote_mib(bp
))
714 /* Read neg results if dcbx is in the FW */
715 if (bnx2x_dcbx_read_shmem_neg_results(bp
))
718 bnx2x_dump_dcbx_drv_param(bp
, &bp
->dcbx_local_feat
,
721 bnx2x_get_dcbx_drv_param(bp
, &bp
->dcbx_local_feat
,
724 /* mark DCBX result for PMF migration */
725 bnx2x_update_drv_flags(bp
,
726 1 << DRV_FLAGS_DCB_CONFIGURED
,
730 * Add new app tlvs to dcbnl
732 bnx2x_dcbnl_update_applist(bp
, false);
735 * reconfigure the netdevice with the results of the new
738 bnx2x_dcbx_update_tc_mapping(bp
);
741 * allow other functions to update their netdevices
745 bnx2x_link_sync_notify(bp
);
747 bnx2x_dcbx_stop_hw_tx(bp
);
751 case BNX2X_DCBX_STATE_TX_PAUSED
:
752 DP(BNX2X_MSG_DCB
, "BNX2X_DCBX_STATE_TX_PAUSED\n");
753 bnx2x_pfc_set_pfc(bp
);
755 bnx2x_dcbx_update_ets_params(bp
);
757 /* ets may affect cmng configuration: reinit it in hw */
758 bnx2x_set_local_cmng(bp
);
760 bnx2x_dcbx_resume_hw_tx(bp
);
763 case BNX2X_DCBX_STATE_TX_RELEASED
:
764 DP(BNX2X_MSG_DCB
, "BNX2X_DCBX_STATE_TX_RELEASED\n");
765 bnx2x_fw_command(bp
, DRV_MSG_CODE_DCBX_PMF_DRV_OK
, 0);
768 * Send a notification for the new negotiated parameters
770 dcbnl_cee_notify(bp
->dev
, RTM_GETDCB
, DCB_CMD_CEE_GET
, 0, 0);
774 BNX2X_ERR("Unknown DCBX_STATE\n");
778 #define LLDP_ADMIN_MIB_OFFSET(bp) (PORT_MAX*sizeof(struct lldp_params) + \
779 BP_PORT(bp)*sizeof(struct lldp_admin_mib))
781 static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x
*bp
,
782 u32 dcbx_lldp_params_offset
)
784 struct lldp_admin_mib admin_mib
;
785 u32 i
, other_traf_type
= PREDEFINED_APP_IDX_MAX
, traf_type
= 0;
786 u32 offset
= dcbx_lldp_params_offset
+ LLDP_ADMIN_MIB_OFFSET(bp
);
789 struct dcbx_features
*af
= &admin_mib
.features
;
790 struct bnx2x_config_dcbx_params
*dp
= &bp
->dcbx_config_params
;
792 memset(&admin_mib
, 0, sizeof(struct lldp_admin_mib
));
794 /* Read the data first */
795 bnx2x_read_data(bp
, (u32
*)&admin_mib
, offset
,
796 sizeof(struct lldp_admin_mib
));
798 if (bp
->dcbx_enabled
== BNX2X_DCBX_ENABLED_ON_NEG_ON
)
799 SET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_DCBX_ENABLED
);
801 RESET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_DCBX_ENABLED
);
803 if (dp
->overwrite_settings
== BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE
) {
805 RESET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_CEE_VERSION_MASK
);
806 admin_mib
.ver_cfg_flags
|=
807 (dp
->admin_dcbx_version
<< DCBX_CEE_VERSION_SHIFT
) &
808 DCBX_CEE_VERSION_MASK
;
810 af
->ets
.enabled
= (u8
)dp
->admin_ets_enable
;
812 af
->pfc
.enabled
= (u8
)dp
->admin_pfc_enable
;
814 /* FOR IEEE dp->admin_tc_supported_tx_enable */
815 if (dp
->admin_ets_configuration_tx_enable
)
816 SET_FLAGS(admin_mib
.ver_cfg_flags
,
817 DCBX_ETS_CONFIG_TX_ENABLED
);
819 RESET_FLAGS(admin_mib
.ver_cfg_flags
,
820 DCBX_ETS_CONFIG_TX_ENABLED
);
821 /* For IEEE admin_ets_recommendation_tx_enable */
822 if (dp
->admin_pfc_tx_enable
)
823 SET_FLAGS(admin_mib
.ver_cfg_flags
,
824 DCBX_PFC_CONFIG_TX_ENABLED
);
826 RESET_FLAGS(admin_mib
.ver_cfg_flags
,
827 DCBX_PFC_CONFIG_TX_ENABLED
);
829 if (dp
->admin_application_priority_tx_enable
)
830 SET_FLAGS(admin_mib
.ver_cfg_flags
,
831 DCBX_APP_CONFIG_TX_ENABLED
);
833 RESET_FLAGS(admin_mib
.ver_cfg_flags
,
834 DCBX_APP_CONFIG_TX_ENABLED
);
836 if (dp
->admin_ets_willing
)
837 SET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_ETS_WILLING
);
839 RESET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_ETS_WILLING
);
840 /* For IEEE admin_ets_reco_valid */
841 if (dp
->admin_pfc_willing
)
842 SET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_PFC_WILLING
);
844 RESET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_PFC_WILLING
);
846 if (dp
->admin_app_priority_willing
)
847 SET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_APP_WILLING
);
849 RESET_FLAGS(admin_mib
.ver_cfg_flags
, DCBX_APP_WILLING
);
851 for (i
= 0 ; i
< DCBX_MAX_NUM_PG_BW_ENTRIES
; i
++) {
852 DCBX_PG_BW_SET(af
->ets
.pg_bw_tbl
, i
,
853 (u8
)dp
->admin_configuration_bw_precentage
[i
]);
855 DP(BNX2X_MSG_DCB
, "pg_bw_tbl[%d] = %02x\n",
856 i
, DCBX_PG_BW_GET(af
->ets
.pg_bw_tbl
, i
));
859 for (i
= 0; i
< DCBX_MAX_NUM_PRI_PG_ENTRIES
; i
++) {
860 DCBX_PRI_PG_SET(af
->ets
.pri_pg_tbl
, i
,
861 (u8
)dp
->admin_configuration_ets_pg
[i
]);
863 DP(BNX2X_MSG_DCB
, "pri_pg_tbl[%d] = %02x\n",
864 i
, DCBX_PRI_PG_GET(af
->ets
.pri_pg_tbl
, i
));
867 /*For IEEE admin_recommendation_bw_percentage
868 *For IEEE admin_recommendation_ets_pg */
869 af
->pfc
.pri_en_bitmap
= (u8
)dp
->admin_pfc_bitmap
;
870 for (i
= 0; i
< DCBX_CONFIG_MAX_APP_PROTOCOL
; i
++) {
871 if (dp
->admin_priority_app_table
[i
].valid
) {
872 struct bnx2x_admin_priority_app_table
*table
=
873 dp
->admin_priority_app_table
;
874 if ((ETH_TYPE_FCOE
== table
[i
].app_id
) &&
875 (TRAFFIC_TYPE_ETH
== table
[i
].traffic_type
))
876 traf_type
= FCOE_APP_IDX
;
877 else if ((TCP_PORT_ISCSI
== table
[i
].app_id
) &&
878 (TRAFFIC_TYPE_PORT
== table
[i
].traffic_type
))
879 traf_type
= ISCSI_APP_IDX
;
881 traf_type
= other_traf_type
++;
883 af
->app
.app_pri_tbl
[traf_type
].app_id
=
886 af
->app
.app_pri_tbl
[traf_type
].pri_bitmap
=
887 (u8
)(1 << table
[i
].priority
);
889 af
->app
.app_pri_tbl
[traf_type
].appBitfield
=
890 (DCBX_APP_ENTRY_VALID
);
892 af
->app
.app_pri_tbl
[traf_type
].appBitfield
|=
893 (TRAFFIC_TYPE_ETH
== table
[i
].traffic_type
) ?
894 DCBX_APP_SF_ETH_TYPE
: DCBX_APP_SF_PORT
;
898 af
->app
.default_pri
= (u8
)dp
->admin_default_priority
;
901 /* Write the data. */
902 bnx2x_write_data(bp
, (u32
*)&admin_mib
, offset
,
903 sizeof(struct lldp_admin_mib
));
906 void bnx2x_dcbx_set_state(struct bnx2x
*bp
, bool dcb_on
, u32 dcbx_enabled
)
908 if (!CHIP_IS_E1x(bp
)) {
909 bp
->dcb_state
= dcb_on
;
910 bp
->dcbx_enabled
= dcbx_enabled
;
912 bp
->dcb_state
= false;
913 bp
->dcbx_enabled
= BNX2X_DCBX_ENABLED_INVALID
;
915 DP(BNX2X_MSG_DCB
, "DCB state [%s:%s]\n",
916 dcb_on
? "ON" : "OFF",
917 dcbx_enabled
== BNX2X_DCBX_ENABLED_OFF
? "user-mode" :
918 dcbx_enabled
== BNX2X_DCBX_ENABLED_ON_NEG_OFF
? "on-chip static" :
919 dcbx_enabled
== BNX2X_DCBX_ENABLED_ON_NEG_ON
?
920 "on-chip with negotiation" : "invalid");
923 void bnx2x_dcbx_init_params(struct bnx2x
*bp
)
925 bp
->dcbx_config_params
.admin_dcbx_version
= 0x0; /* 0 - CEE; 1 - IEEE */
926 bp
->dcbx_config_params
.admin_ets_willing
= 1;
927 bp
->dcbx_config_params
.admin_pfc_willing
= 1;
928 bp
->dcbx_config_params
.overwrite_settings
= 1;
929 bp
->dcbx_config_params
.admin_ets_enable
= 1;
930 bp
->dcbx_config_params
.admin_pfc_enable
= 1;
931 bp
->dcbx_config_params
.admin_tc_supported_tx_enable
= 1;
932 bp
->dcbx_config_params
.admin_ets_configuration_tx_enable
= 1;
933 bp
->dcbx_config_params
.admin_pfc_tx_enable
= 1;
934 bp
->dcbx_config_params
.admin_application_priority_tx_enable
= 1;
935 bp
->dcbx_config_params
.admin_ets_reco_valid
= 1;
936 bp
->dcbx_config_params
.admin_app_priority_willing
= 1;
937 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[0] = 100;
938 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[1] = 0;
939 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[2] = 0;
940 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[3] = 0;
941 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[4] = 0;
942 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[5] = 0;
943 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[6] = 0;
944 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[7] = 0;
945 bp
->dcbx_config_params
.admin_configuration_ets_pg
[0] = 0;
946 bp
->dcbx_config_params
.admin_configuration_ets_pg
[1] = 0;
947 bp
->dcbx_config_params
.admin_configuration_ets_pg
[2] = 0;
948 bp
->dcbx_config_params
.admin_configuration_ets_pg
[3] = 0;
949 bp
->dcbx_config_params
.admin_configuration_ets_pg
[4] = 0;
950 bp
->dcbx_config_params
.admin_configuration_ets_pg
[5] = 0;
951 bp
->dcbx_config_params
.admin_configuration_ets_pg
[6] = 0;
952 bp
->dcbx_config_params
.admin_configuration_ets_pg
[7] = 0;
953 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[0] = 100;
954 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[1] = 0;
955 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[2] = 0;
956 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[3] = 0;
957 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[4] = 0;
958 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[5] = 0;
959 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[6] = 0;
960 bp
->dcbx_config_params
.admin_recommendation_bw_precentage
[7] = 0;
961 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[0] = 0;
962 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[1] = 1;
963 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[2] = 2;
964 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[3] = 3;
965 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[4] = 4;
966 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[5] = 5;
967 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[6] = 6;
968 bp
->dcbx_config_params
.admin_recommendation_ets_pg
[7] = 7;
969 bp
->dcbx_config_params
.admin_pfc_bitmap
= 0x0;
970 bp
->dcbx_config_params
.admin_priority_app_table
[0].valid
= 0;
971 bp
->dcbx_config_params
.admin_priority_app_table
[1].valid
= 0;
972 bp
->dcbx_config_params
.admin_priority_app_table
[2].valid
= 0;
973 bp
->dcbx_config_params
.admin_priority_app_table
[3].valid
= 0;
974 bp
->dcbx_config_params
.admin_default_priority
= 0;
977 void bnx2x_dcbx_init(struct bnx2x
*bp
, bool update_shmem
)
979 u32 dcbx_lldp_params_offset
= SHMEM_LLDP_DCBX_PARAMS_NONE
;
981 /* only PMF can send ADMIN msg to MFW in old MFW versions */
982 if ((!bp
->port
.pmf
) && (!(bp
->flags
& BC_SUPPORTS_DCBX_MSG_NON_PMF
)))
985 if (bp
->dcbx_enabled
<= 0)
989 * chip of good for dcbx version,
991 * shmem2 contains DCBX support fields
993 DP(BNX2X_MSG_DCB
, "dcb_state %d bp->port.pmf %d\n",
994 bp
->dcb_state
, bp
->port
.pmf
);
996 if (bp
->dcb_state
== BNX2X_DCB_STATE_ON
&&
997 SHMEM2_HAS(bp
, dcbx_lldp_params_offset
)) {
998 dcbx_lldp_params_offset
=
999 SHMEM2_RD(bp
, dcbx_lldp_params_offset
);
1001 DP(BNX2X_MSG_DCB
, "dcbx_lldp_params_offset 0x%x\n",
1002 dcbx_lldp_params_offset
);
1004 bnx2x_update_drv_flags(bp
, 1 << DRV_FLAGS_DCB_CONFIGURED
, 0);
1006 if (SHMEM_LLDP_DCBX_PARAMS_NONE
!= dcbx_lldp_params_offset
) {
1007 /* need HW lock to avoid scenario of two drivers
1008 * writing in parallel to shmem
1010 bnx2x_acquire_hw_lock(bp
,
1011 HW_LOCK_RESOURCE_DCBX_ADMIN_MIB
);
1013 bnx2x_dcbx_admin_mib_updated_params(bp
,
1014 dcbx_lldp_params_offset
);
1016 /* Let HW start negotiation */
1017 bnx2x_fw_command(bp
,
1018 DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG
, 0);
1019 /* release HW lock only after MFW acks that it finished
1020 * reading values from shmem
1022 bnx2x_release_hw_lock(bp
,
1023 HW_LOCK_RESOURCE_DCBX_ADMIN_MIB
);
1028 bnx2x_dcbx_print_cos_params(struct bnx2x
*bp
,
1029 struct bnx2x_func_tx_start_params
*pfc_fw_cfg
)
1035 "pfc_fw_cfg->dcb_version %x\n", pfc_fw_cfg
->dcb_version
);
1037 "pdev->params.dcbx_port_params.pfc.priority_non_pauseable_mask %x\n",
1038 bp
->dcbx_port_params
.pfc
.priority_non_pauseable_mask
);
1040 for (cos
= 0 ; cos
< bp
->dcbx_port_params
.ets
.num_of_cos
; cos
++) {
1042 "pdev->params.dcbx_port_params.ets.cos_params[%d].pri_bitmask %x\n",
1043 cos
, bp
->dcbx_port_params
.ets
.cos_params
[cos
].pri_bitmask
);
1046 "pdev->params.dcbx_port_params.ets.cos_params[%d].bw_tbl %x\n",
1047 cos
, bp
->dcbx_port_params
.ets
.cos_params
[cos
].bw_tbl
);
1050 "pdev->params.dcbx_port_params.ets.cos_params[%d].strict %x\n",
1051 cos
, bp
->dcbx_port_params
.ets
.cos_params
[cos
].strict
);
1054 "pdev->params.dcbx_port_params.ets.cos_params[%d].pauseable %x\n",
1055 cos
, bp
->dcbx_port_params
.ets
.cos_params
[cos
].pauseable
);
1058 for (pri
= 0; pri
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; pri
++) {
1060 "pfc_fw_cfg->traffic_type_to_priority_cos[%d].priority %x\n",
1061 pri
, pfc_fw_cfg
->traffic_type_to_priority_cos
[pri
].priority
);
1064 "pfc_fw_cfg->traffic_type_to_priority_cos[%d].cos %x\n",
1065 pri
, pfc_fw_cfg
->traffic_type_to_priority_cos
[pri
].cos
);
1069 /* fills help_data according to pg_info */
1070 static void bnx2x_dcbx_get_num_pg_traf_type(struct bnx2x
*bp
,
1071 u32
*pg_pri_orginal_spread
,
1072 struct pg_help_data
*help_data
)
1074 bool pg_found
= false;
1075 u32 i
, traf_type
, add_traf_type
, add_pg
;
1076 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
1077 struct pg_entry_help_data
*data
= help_data
->data
; /*shortcut*/
1079 /* Set to invalid */
1080 for (i
= 0; i
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; i
++)
1081 data
[i
].pg
= DCBX_ILLEGAL_PG
;
1083 for (add_traf_type
= 0;
1084 add_traf_type
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; add_traf_type
++) {
1086 if (ttp
[add_traf_type
] < MAX_PFC_PRIORITIES
) {
1087 add_pg
= (u8
)pg_pri_orginal_spread
[ttp
[add_traf_type
]];
1089 traf_type
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
;
1091 if (data
[traf_type
].pg
== add_pg
) {
1092 if (!(data
[traf_type
].pg_priority
&
1093 (1 << ttp
[add_traf_type
])))
1096 data
[traf_type
].pg_priority
|=
1097 (1 << ttp
[add_traf_type
]);
1102 if (false == pg_found
) {
1103 data
[help_data
->num_of_pg
].pg
= add_pg
;
1104 data
[help_data
->num_of_pg
].pg_priority
=
1105 (1 << ttp
[add_traf_type
]);
1106 data
[help_data
->num_of_pg
].num_of_dif_pri
= 1;
1107 help_data
->num_of_pg
++;
1111 "add_traf_type %d pg_found %s num_of_pg %d\n",
1112 add_traf_type
, (false == pg_found
) ? "NO" : "YES",
1113 help_data
->num_of_pg
);
1117 static void bnx2x_dcbx_ets_disabled_entry_data(struct bnx2x
*bp
,
1118 struct cos_help_data
*cos_data
,
1121 /* Only one priority than only one COS */
1122 cos_data
->data
[0].pausable
=
1123 IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
, pri_join_mask
);
1124 cos_data
->data
[0].pri_join_mask
= pri_join_mask
;
1125 cos_data
->data
[0].cos_bw
= 100;
1126 cos_data
->num_of_cos
= 1;
1129 static inline void bnx2x_dcbx_add_to_cos_bw(struct bnx2x
*bp
,
1130 struct cos_entry_help_data
*data
,
1133 if (data
->cos_bw
== DCBX_INVALID_COS_BW
)
1134 data
->cos_bw
= pg_bw
;
1136 data
->cos_bw
+= pg_bw
;
1139 static void bnx2x_dcbx_separate_pauseable_from_non(struct bnx2x
*bp
,
1140 struct cos_help_data
*cos_data
,
1141 u32
*pg_pri_orginal_spread
,
1142 struct dcbx_ets_feature
*ets
)
1148 u8 num_of_pri
= LLFC_DRIVER_TRAFFIC_TYPE_MAX
;
1150 cos_data
->data
[0].pausable
= true;
1151 cos_data
->data
[1].pausable
= false;
1152 cos_data
->data
[0].pri_join_mask
= cos_data
->data
[1].pri_join_mask
= 0;
1154 for (i
= 0 ; i
< num_of_pri
; i
++) {
1155 pri_tested
= 1 << bp
->dcbx_port_params
.
1156 app
.traffic_type_priority
[i
];
1158 if (pri_tested
& DCBX_PFC_PRI_NON_PAUSE_MASK(bp
)) {
1159 cos_data
->data
[1].pri_join_mask
|= pri_tested
;
1162 cos_data
->data
[0].pri_join_mask
|= pri_tested
;
1165 pg_entry
= (u8
)pg_pri_orginal_spread
[bp
->dcbx_port_params
.
1166 app
.traffic_type_priority
[i
]];
1167 /* There can be only one strict pg */
1168 if (pg_entry
< DCBX_MAX_NUM_PG_BW_ENTRIES
)
1169 bnx2x_dcbx_add_to_cos_bw(bp
, &cos_data
->data
[entry
],
1170 DCBX_PG_BW_GET(ets
->pg_bw_tbl
, pg_entry
));
1172 /* If we join a group and one is strict
1175 cos_data
->data
[entry
].strict
=
1176 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1178 if ((0 == cos_data
->data
[0].pri_join_mask
) &&
1179 (0 == cos_data
->data
[1].pri_join_mask
))
1180 BNX2X_ERR("dcbx error: Both groups must have priorities\n");
1184 #define POWER_OF_2(x) ((0 != x) && (0 == (x & (x-1))))
1187 static void bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(struct bnx2x
*bp
,
1188 struct pg_help_data
*pg_help_data
,
1189 struct cos_help_data
*cos_data
,
1195 u32 pri_mask_without_pri
= 0;
1196 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
1198 if (num_of_dif_pri
== 1) {
1199 bnx2x_dcbx_ets_disabled_entry_data(bp
, cos_data
, pri_join_mask
);
1202 /* single priority group */
1203 if (pg_help_data
->data
[0].pg
< DCBX_MAX_NUM_PG_BW_ENTRIES
) {
1204 /* If there are both pauseable and non-pauseable priorities,
1205 * the pauseable priorities go to the first queue and
1206 * the non-pauseable priorities go to the second queue.
1208 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp
, pri_join_mask
)) {
1210 cos_data
->data
[0].pausable
= true;
1212 cos_data
->data
[1].pausable
= false;
1214 if (2 == num_of_dif_pri
) {
1215 cos_data
->data
[0].cos_bw
= 50;
1216 cos_data
->data
[1].cos_bw
= 50;
1219 if (3 == num_of_dif_pri
) {
1220 if (POWER_OF_2(DCBX_PFC_PRI_GET_PAUSE(bp
,
1222 cos_data
->data
[0].cos_bw
= 33;
1223 cos_data
->data
[1].cos_bw
= 67;
1225 cos_data
->data
[0].cos_bw
= 67;
1226 cos_data
->data
[1].cos_bw
= 33;
1230 } else if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
, pri_join_mask
)) {
1231 /* If there are only pauseable priorities,
1232 * then one/two priorities go to the first queue
1233 * and one priority goes to the second queue.
1235 if (2 == num_of_dif_pri
) {
1236 cos_data
->data
[0].cos_bw
= 50;
1237 cos_data
->data
[1].cos_bw
= 50;
1239 cos_data
->data
[0].cos_bw
= 67;
1240 cos_data
->data
[1].cos_bw
= 33;
1242 cos_data
->data
[1].pausable
= true;
1243 cos_data
->data
[0].pausable
= true;
1244 /* All priorities except FCOE */
1245 cos_data
->data
[0].pri_join_mask
= (pri_join_mask
&
1246 ((u8
)~(1 << ttp
[LLFC_TRAFFIC_TYPE_FCOE
])));
1247 /* Only FCOE priority.*/
1248 cos_data
->data
[1].pri_join_mask
=
1249 (1 << ttp
[LLFC_TRAFFIC_TYPE_FCOE
]);
1251 /* If there are only non-pauseable priorities,
1252 * they will all go to the same queue.
1254 bnx2x_dcbx_ets_disabled_entry_data(bp
,
1255 cos_data
, pri_join_mask
);
1257 /* priority group which is not BW limited (PG#15):*/
1258 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp
, pri_join_mask
)) {
1259 /* If there are both pauseable and non-pauseable
1260 * priorities, the pauseable priorities go to the first
1261 * queue and the non-pauseable priorities
1262 * go to the second queue.
1264 if (DCBX_PFC_PRI_GET_PAUSE(bp
, pri_join_mask
) >
1265 DCBX_PFC_PRI_GET_NON_PAUSE(bp
, pri_join_mask
)) {
1266 cos_data
->data
[0].strict
=
1267 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1268 cos_data
->data
[1].strict
=
1269 BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
1270 BNX2X_DCBX_STRICT_COS_HIGHEST
);
1272 cos_data
->data
[0].strict
=
1273 BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
1274 BNX2X_DCBX_STRICT_COS_HIGHEST
);
1275 cos_data
->data
[1].strict
=
1276 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1279 cos_data
->data
[0].pausable
= true;
1280 /* Non pause-able.*/
1281 cos_data
->data
[1].pausable
= false;
1283 /* If there are only pauseable priorities or
1284 * only non-pauseable,* the lower priorities go
1285 * to the first queue and the higher priorities go
1286 * to the second queue.
1288 cos_data
->data
[0].pausable
=
1289 cos_data
->data
[1].pausable
=
1290 IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
, pri_join_mask
);
1292 for (i
= 0 ; i
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; i
++) {
1293 pri_tested
= 1 << bp
->dcbx_port_params
.
1294 app
.traffic_type_priority
[i
];
1295 /* Remove priority tested */
1296 pri_mask_without_pri
=
1297 (pri_join_mask
& ((u8
)(~pri_tested
)));
1298 if (pri_mask_without_pri
< pri_tested
)
1302 if (i
== LLFC_DRIVER_TRAFFIC_TYPE_MAX
)
1303 BNX2X_ERR("Invalid value for pri_join_mask - could not find a priority\n");
1305 cos_data
->data
[0].pri_join_mask
= pri_mask_without_pri
;
1306 cos_data
->data
[1].pri_join_mask
= pri_tested
;
1307 /* Both queues are strict priority,
1308 * and that with the highest priority
1309 * gets the highest strict priority in the arbiter.
1311 cos_data
->data
[0].strict
=
1312 BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(
1313 BNX2X_DCBX_STRICT_COS_HIGHEST
);
1314 cos_data
->data
[1].strict
=
1315 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1320 static void bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
1322 struct pg_help_data
*pg_help_data
,
1323 struct dcbx_ets_feature
*ets
,
1324 struct cos_help_data
*cos_data
,
1325 u32
*pg_pri_orginal_spread
,
1330 u8 pg
[DCBX_COS_MAX_NUM_E2
] = { 0 };
1332 /* If there are both pauseable and non-pauseable priorities,
1333 * the pauseable priorities go to the first queue and
1334 * the non-pauseable priorities go to the second queue.
1336 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp
, pri_join_mask
)) {
1337 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp
,
1338 pg_help_data
->data
[0].pg_priority
) ||
1339 IS_DCBX_PFC_PRI_MIX_PAUSE(bp
,
1340 pg_help_data
->data
[1].pg_priority
)) {
1341 /* If one PG contains both pauseable and
1342 * non-pauseable priorities then ETS is disabled.
1344 bnx2x_dcbx_separate_pauseable_from_non(bp
, cos_data
,
1345 pg_pri_orginal_spread
, ets
);
1346 bp
->dcbx_port_params
.ets
.enabled
= false;
1351 cos_data
->data
[0].pausable
= true;
1352 /* Non pauseable. */
1353 cos_data
->data
[1].pausable
= false;
1354 if (IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
,
1355 pg_help_data
->data
[0].pg_priority
)) {
1356 /* 0 is pauseable */
1357 cos_data
->data
[0].pri_join_mask
=
1358 pg_help_data
->data
[0].pg_priority
;
1359 pg
[0] = pg_help_data
->data
[0].pg
;
1360 cos_data
->data
[1].pri_join_mask
=
1361 pg_help_data
->data
[1].pg_priority
;
1362 pg
[1] = pg_help_data
->data
[1].pg
;
1363 } else {/* 1 is pauseable */
1364 cos_data
->data
[0].pri_join_mask
=
1365 pg_help_data
->data
[1].pg_priority
;
1366 pg
[0] = pg_help_data
->data
[1].pg
;
1367 cos_data
->data
[1].pri_join_mask
=
1368 pg_help_data
->data
[0].pg_priority
;
1369 pg
[1] = pg_help_data
->data
[0].pg
;
1372 /* If there are only pauseable priorities or
1373 * only non-pauseable, each PG goes to a queue.
1375 cos_data
->data
[0].pausable
= cos_data
->data
[1].pausable
=
1376 IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
, pri_join_mask
);
1377 cos_data
->data
[0].pri_join_mask
=
1378 pg_help_data
->data
[0].pg_priority
;
1379 pg
[0] = pg_help_data
->data
[0].pg
;
1380 cos_data
->data
[1].pri_join_mask
=
1381 pg_help_data
->data
[1].pg_priority
;
1382 pg
[1] = pg_help_data
->data
[1].pg
;
1385 /* There can be only one strict pg */
1386 for (i
= 0 ; i
< ARRAY_SIZE(pg
); i
++) {
1387 if (pg
[i
] < DCBX_MAX_NUM_PG_BW_ENTRIES
)
1388 cos_data
->data
[i
].cos_bw
=
1389 DCBX_PG_BW_GET(ets
->pg_bw_tbl
, pg
[i
]);
1391 cos_data
->data
[i
].strict
=
1392 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1396 static int bnx2x_dcbx_join_pgs(
1398 struct dcbx_ets_feature
*ets
,
1399 struct pg_help_data
*pg_help_data
,
1400 u8 required_num_of_pg
)
1402 u8 entry_joined
= pg_help_data
->num_of_pg
- 1;
1403 u8 entry_removed
= entry_joined
+ 1;
1406 if (required_num_of_pg
== 0 || ARRAY_SIZE(pg_help_data
->data
)
1407 <= pg_help_data
->num_of_pg
) {
1409 BNX2X_ERR("required_num_of_pg can't be zero\n");
1413 while (required_num_of_pg
< pg_help_data
->num_of_pg
) {
1414 entry_joined
= pg_help_data
->num_of_pg
- 2;
1415 entry_removed
= entry_joined
+ 1;
1417 entry_removed
%= ARRAY_SIZE(pg_help_data
->data
);
1419 pg_help_data
->data
[entry_joined
].pg_priority
|=
1420 pg_help_data
->data
[entry_removed
].pg_priority
;
1422 pg_help_data
->data
[entry_joined
].num_of_dif_pri
+=
1423 pg_help_data
->data
[entry_removed
].num_of_dif_pri
;
1425 if (pg_help_data
->data
[entry_joined
].pg
== DCBX_STRICT_PRI_PG
||
1426 pg_help_data
->data
[entry_removed
].pg
== DCBX_STRICT_PRI_PG
)
1427 /* Entries joined strict priority rules */
1428 pg_help_data
->data
[entry_joined
].pg
=
1431 /* Entries can be joined join BW */
1432 pg_joined
= DCBX_PG_BW_GET(ets
->pg_bw_tbl
,
1433 pg_help_data
->data
[entry_joined
].pg
) +
1434 DCBX_PG_BW_GET(ets
->pg_bw_tbl
,
1435 pg_help_data
->data
[entry_removed
].pg
);
1437 DCBX_PG_BW_SET(ets
->pg_bw_tbl
,
1438 pg_help_data
->data
[entry_joined
].pg
, pg_joined
);
1440 /* Joined the entries */
1441 pg_help_data
->num_of_pg
--;
1447 static void bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
1449 struct pg_help_data
*pg_help_data
,
1450 struct dcbx_ets_feature
*ets
,
1451 struct cos_help_data
*cos_data
,
1452 u32
*pg_pri_orginal_spread
,
1460 bool b_found_strict
= false;
1461 u8 num_of_pri
= LLFC_DRIVER_TRAFFIC_TYPE_MAX
;
1463 cos_data
->data
[0].pri_join_mask
= cos_data
->data
[1].pri_join_mask
= 0;
1464 /* If there are both pauseable and non-pauseable priorities,
1465 * the pauseable priorities go to the first queue and the
1466 * non-pauseable priorities go to the second queue.
1468 if (IS_DCBX_PFC_PRI_MIX_PAUSE(bp
, pri_join_mask
))
1469 bnx2x_dcbx_separate_pauseable_from_non(bp
,
1470 cos_data
, pg_pri_orginal_spread
, ets
);
1472 /* If two BW-limited PG-s were combined to one queue,
1473 * the BW is their sum.
1475 * If there are only pauseable priorities or only non-pauseable,
1476 * and there are both BW-limited and non-BW-limited PG-s,
1477 * the BW-limited PG/s go to one queue and the non-BW-limited
1478 * PG/s go to the second queue.
1480 * If there are only pauseable priorities or only non-pauseable
1481 * and all are BW limited, then two priorities go to the first
1482 * queue and one priority goes to the second queue.
1484 * We will join this two cases:
1485 * if one is BW limited it will go to the second queue
1486 * otherwise the last priority will get it
1489 cos_data
->data
[0].pausable
= cos_data
->data
[1].pausable
=
1490 IS_DCBX_PFC_PRI_ONLY_PAUSE(bp
, pri_join_mask
);
1492 for (i
= 0 ; i
< num_of_pri
; i
++) {
1493 pri_tested
= 1 << bp
->dcbx_port_params
.
1494 app
.traffic_type_priority
[i
];
1495 pg_entry
= (u8
)pg_pri_orginal_spread
[bp
->
1496 dcbx_port_params
.app
.traffic_type_priority
[i
]];
1498 if (pg_entry
< DCBX_MAX_NUM_PG_BW_ENTRIES
) {
1501 if (i
== (num_of_pri
-1) &&
1502 false == b_found_strict
)
1503 /* last entry will be handled separately
1504 * If no priority is strict than last
1505 * entry goes to last queue.
1508 cos_data
->data
[entry
].pri_join_mask
|=
1510 bnx2x_dcbx_add_to_cos_bw(bp
,
1511 &cos_data
->data
[entry
],
1512 DCBX_PG_BW_GET(ets
->pg_bw_tbl
,
1515 b_found_strict
= true;
1516 cos_data
->data
[1].pri_join_mask
|= pri_tested
;
1517 /* If we join a group and one is strict
1520 cos_data
->data
[1].strict
=
1521 BNX2X_DCBX_STRICT_COS_HIGHEST
;
1527 static void bnx2x_dcbx_2cos_limit_cee_fill_cos_params(struct bnx2x
*bp
,
1528 struct pg_help_data
*help_data
,
1529 struct dcbx_ets_feature
*ets
,
1530 struct cos_help_data
*cos_data
,
1531 u32
*pg_pri_orginal_spread
,
1535 /* default E2 settings */
1536 cos_data
->num_of_cos
= DCBX_COS_MAX_NUM_E2
;
1538 switch (help_data
->num_of_pg
) {
1540 bnx2x_dcbx_2cos_limit_cee_single_pg_to_cos_params(
1548 bnx2x_dcbx_2cos_limit_cee_two_pg_to_cos_params(
1553 pg_pri_orginal_spread
,
1559 bnx2x_dcbx_2cos_limit_cee_three_pg_to_cos_params(
1564 pg_pri_orginal_spread
,
1569 BNX2X_ERR("Wrong pg_help_data.num_of_pg\n");
1570 bnx2x_dcbx_ets_disabled_entry_data(bp
,
1571 cos_data
, pri_join_mask
);
1575 static int bnx2x_dcbx_spread_strict_pri(struct bnx2x
*bp
,
1576 struct cos_help_data
*cos_data
,
1578 u8 num_spread_of_entries
,
1581 u8 strict_pri
= BNX2X_DCBX_STRICT_COS_HIGHEST
;
1582 u8 num_of_app_pri
= MAX_PFC_PRIORITIES
;
1585 while (num_spread_of_entries
&& num_of_app_pri
> 0) {
1586 app_pri_bit
= 1 << (num_of_app_pri
- 1);
1587 if (app_pri_bit
& strict_app_pris
) {
1588 struct cos_entry_help_data
*data
= &cos_data
->
1590 num_spread_of_entries
--;
1591 if (num_spread_of_entries
== 0) {
1592 /* last entry needed put all the entries left */
1593 data
->cos_bw
= DCBX_INVALID_COS_BW
;
1594 data
->strict
= strict_pri
;
1595 data
->pri_join_mask
= strict_app_pris
;
1596 data
->pausable
= DCBX_IS_PFC_PRI_SOME_PAUSE(bp
,
1597 data
->pri_join_mask
);
1599 strict_app_pris
&= ~app_pri_bit
;
1601 data
->cos_bw
= DCBX_INVALID_COS_BW
;
1602 data
->strict
= strict_pri
;
1603 data
->pri_join_mask
= app_pri_bit
;
1604 data
->pausable
= DCBX_IS_PFC_PRI_SOME_PAUSE(bp
,
1605 data
->pri_join_mask
);
1609 BNX2X_DCBX_STRICT_COS_NEXT_LOWER_PRI(strict_pri
);
1616 if (num_spread_of_entries
) {
1617 BNX2X_ERR("Didn't succeed to spread strict priorities\n");
1624 static u8
bnx2x_dcbx_cee_fill_strict_pri(struct bnx2x
*bp
,
1625 struct cos_help_data
*cos_data
,
1627 u8 num_spread_of_entries
,
1630 if (bnx2x_dcbx_spread_strict_pri(bp
, cos_data
, entry
,
1631 num_spread_of_entries
,
1633 struct cos_entry_help_data
*data
= &cos_data
->
1636 data
->cos_bw
= DCBX_INVALID_COS_BW
;
1637 data
->strict
= BNX2X_DCBX_STRICT_COS_HIGHEST
;
1638 data
->pri_join_mask
= strict_app_pris
;
1639 data
->pausable
= DCBX_IS_PFC_PRI_SOME_PAUSE(bp
,
1640 data
->pri_join_mask
);
1644 return num_spread_of_entries
;
1647 static void bnx2x_dcbx_cee_fill_cos_params(struct bnx2x
*bp
,
1648 struct pg_help_data
*help_data
,
1649 struct dcbx_ets_feature
*ets
,
1650 struct cos_help_data
*cos_data
,
1654 u8 need_num_of_entries
= 0;
1659 * if the number of requested PG-s in CEE is greater than 3
1660 * then the results are not determined since this is a violation
1663 if (help_data
->num_of_pg
> DCBX_COS_MAX_NUM_E3B0
) {
1664 if (bnx2x_dcbx_join_pgs(bp
, ets
, help_data
,
1665 DCBX_COS_MAX_NUM_E3B0
)) {
1666 BNX2X_ERR("Unable to reduce the number of PGs - we will disables ETS\n");
1667 bnx2x_dcbx_ets_disabled_entry_data(bp
, cos_data
,
1673 for (i
= 0 ; i
< help_data
->num_of_pg
; i
++) {
1674 struct pg_entry_help_data
*pg
= &help_data
->data
[i
];
1675 if (pg
->pg
< DCBX_MAX_NUM_PG_BW_ENTRIES
) {
1676 struct cos_entry_help_data
*data
= &cos_data
->
1679 data
->cos_bw
= DCBX_PG_BW_GET(ets
->pg_bw_tbl
, pg
->pg
);
1680 data
->strict
= BNX2X_DCBX_STRICT_INVALID
;
1681 data
->pri_join_mask
= pg
->pg_priority
;
1682 data
->pausable
= DCBX_IS_PFC_PRI_SOME_PAUSE(bp
,
1683 data
->pri_join_mask
);
1687 need_num_of_entries
= min_t(u8
,
1688 (u8
)pg
->num_of_dif_pri
,
1689 (u8
)DCBX_COS_MAX_NUM_E3B0
-
1690 help_data
->num_of_pg
+ 1);
1692 * If there are still VOQ-s which have no associated PG,
1693 * then associate these VOQ-s to PG15. These PG-s will
1694 * be used for SP between priorities on PG15.
1696 entry
+= bnx2x_dcbx_cee_fill_strict_pri(bp
, cos_data
,
1697 entry
, need_num_of_entries
, pg
->pg_priority
);
1701 /* the entry will represent the number of COSes used */
1702 cos_data
->num_of_cos
= entry
;
1704 static void bnx2x_dcbx_fill_cos_params(struct bnx2x
*bp
,
1705 struct pg_help_data
*help_data
,
1706 struct dcbx_ets_feature
*ets
,
1707 u32
*pg_pri_orginal_spread
)
1709 struct cos_help_data cos_data
;
1711 u32 pri_join_mask
= 0;
1712 u8 num_of_dif_pri
= 0;
1714 memset(&cos_data
, 0, sizeof(cos_data
));
1716 /* Validate the pg value */
1717 for (i
= 0; i
< help_data
->num_of_pg
; i
++) {
1718 if (DCBX_STRICT_PRIORITY
!= help_data
->data
[i
].pg
&&
1719 DCBX_MAX_NUM_PG_BW_ENTRIES
<= help_data
->data
[i
].pg
)
1720 BNX2X_ERR("Invalid pg[%d] data %x\n", i
,
1721 help_data
->data
[i
].pg
);
1722 pri_join_mask
|= help_data
->data
[i
].pg_priority
;
1723 num_of_dif_pri
+= help_data
->data
[i
].num_of_dif_pri
;
1727 cos_data
.num_of_cos
= 1;
1728 for (i
= 0; i
< ARRAY_SIZE(cos_data
.data
); i
++) {
1729 cos_data
.data
[i
].pri_join_mask
= 0;
1730 cos_data
.data
[i
].pausable
= false;
1731 cos_data
.data
[i
].strict
= BNX2X_DCBX_STRICT_INVALID
;
1732 cos_data
.data
[i
].cos_bw
= DCBX_INVALID_COS_BW
;
1735 if (CHIP_IS_E3B0(bp
))
1736 bnx2x_dcbx_cee_fill_cos_params(bp
, help_data
, ets
,
1737 &cos_data
, pri_join_mask
);
1738 else /* E2 + E3A0 */
1739 bnx2x_dcbx_2cos_limit_cee_fill_cos_params(bp
,
1742 pg_pri_orginal_spread
,
1746 for (i
= 0; i
< cos_data
.num_of_cos
; i
++) {
1747 struct bnx2x_dcbx_cos_params
*p
=
1748 &bp
->dcbx_port_params
.ets
.cos_params
[i
];
1750 p
->strict
= cos_data
.data
[i
].strict
;
1751 p
->bw_tbl
= cos_data
.data
[i
].cos_bw
;
1752 p
->pri_bitmask
= cos_data
.data
[i
].pri_join_mask
;
1753 p
->pauseable
= cos_data
.data
[i
].pausable
;
1756 if (p
->bw_tbl
!= DCBX_INVALID_COS_BW
||
1757 p
->strict
!= BNX2X_DCBX_STRICT_INVALID
) {
1758 if (p
->pri_bitmask
== 0)
1759 BNX2X_ERR("Invalid pri_bitmask for %d\n", i
);
1761 if (CHIP_IS_E2(bp
) || CHIP_IS_E3A0(bp
)) {
1764 DCBX_PFC_PRI_GET_NON_PAUSE(bp
,
1765 p
->pri_bitmask
) != 0)
1766 BNX2X_ERR("Inconsistent config for pausable COS %d\n",
1769 if (!p
->pauseable
&&
1770 DCBX_PFC_PRI_GET_PAUSE(bp
,
1771 p
->pri_bitmask
) != 0)
1772 BNX2X_ERR("Inconsistent config for nonpausable COS %d\n",
1778 DP(BNX2X_MSG_DCB
, "COS %d PAUSABLE prijoinmask 0x%x\n",
1779 i
, cos_data
.data
[i
].pri_join_mask
);
1782 "COS %d NONPAUSABLE prijoinmask 0x%x\n",
1783 i
, cos_data
.data
[i
].pri_join_mask
);
1786 bp
->dcbx_port_params
.ets
.num_of_cos
= cos_data
.num_of_cos
;
1789 static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x
*bp
,
1790 u32
*set_configuration_ets_pg
,
1795 for (i
= 0; i
< DCBX_MAX_NUM_PRI_PG_ENTRIES
; i
++) {
1796 set_configuration_ets_pg
[i
] = DCBX_PRI_PG_GET(pri_pg_tbl
, i
);
1798 DP(BNX2X_MSG_DCB
, "set_configuration_ets_pg[%d] = 0x%x\n",
1799 i
, set_configuration_ets_pg
[i
]);
1803 static void bnx2x_dcbx_fw_struct(struct bnx2x
*bp
,
1804 struct bnx2x_func_tx_start_params
*pfc_fw_cfg
)
1807 u8 cos
= 0, pri
= 0;
1808 struct priority_cos
*tt2cos
;
1809 u32
*ttp
= bp
->dcbx_port_params
.app
.traffic_type_priority
;
1810 int mfw_configured
= SHMEM2_HAS(bp
, drv_flags
) &&
1811 GET_FLAGS(SHMEM2_RD(bp
, drv_flags
),
1812 1 << DRV_FLAGS_DCB_MFW_CONFIGURED
);
1814 memset(pfc_fw_cfg
, 0, sizeof(*pfc_fw_cfg
));
1816 /* to disable DCB - the structure must be zeroed */
1817 if ((bp
->dcbx_error
& DCBX_REMOTE_MIB_ERROR
) && !mfw_configured
)
1821 tt2cos
= pfc_fw_cfg
->traffic_type_to_priority_cos
;
1823 /* Fw version should be incremented each update */
1824 pfc_fw_cfg
->dcb_version
= ++bp
->dcb_version
;
1825 pfc_fw_cfg
->dcb_enabled
= 1;
1827 /* Fill priority parameters */
1828 for (pri
= 0; pri
< LLFC_DRIVER_TRAFFIC_TYPE_MAX
; pri
++) {
1829 tt2cos
[pri
].priority
= ttp
[pri
];
1830 pri_bit
= 1 << tt2cos
[pri
].priority
;
1832 /* Fill COS parameters based on COS calculated to
1833 * make it more general for future use */
1834 for (cos
= 0; cos
< bp
->dcbx_port_params
.ets
.num_of_cos
; cos
++)
1835 if (bp
->dcbx_port_params
.ets
.cos_params
[cos
].
1836 pri_bitmask
& pri_bit
)
1837 tt2cos
[pri
].cos
= cos
;
1840 /* we never want the FW to add a 0 vlan tag */
1841 pfc_fw_cfg
->dont_add_pri_0_en
= 1;
1843 bnx2x_dcbx_print_cos_params(bp
, pfc_fw_cfg
);
1846 void bnx2x_dcbx_pmf_update(struct bnx2x
*bp
)
1848 /* if we need to synchronize DCBX result from prev PMF
1849 * read it from shmem and update bp and netdev accordingly
1851 if (SHMEM2_HAS(bp
, drv_flags
) &&
1852 GET_FLAGS(SHMEM2_RD(bp
, drv_flags
), 1 << DRV_FLAGS_DCB_CONFIGURED
)) {
1853 /* Read neg results if dcbx is in the FW */
1854 if (bnx2x_dcbx_read_shmem_neg_results(bp
))
1857 bnx2x_dump_dcbx_drv_param(bp
, &bp
->dcbx_local_feat
,
1859 bnx2x_get_dcbx_drv_param(bp
, &bp
->dcbx_local_feat
,
1863 * Add new app tlvs to dcbnl
1865 bnx2x_dcbnl_update_applist(bp
, false);
1867 * Send a notification for the new negotiated parameters
1869 dcbnl_cee_notify(bp
->dev
, RTM_GETDCB
, DCB_CMD_CEE_GET
, 0, 0);
1872 * reconfigure the netdevice with the results of the new
1875 bnx2x_dcbx_update_tc_mapping(bp
);
1882 #define BNX2X_DCBX_CAPS (DCB_CAP_DCBX_LLD_MANAGED | \
1883 DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
1885 static inline bool bnx2x_dcbnl_set_valid(struct bnx2x
*bp
)
1887 /* validate dcbnl call that may change HW state:
1888 * DCB is on and DCBX mode was SUCCESSFULLY set by the user.
1890 return bp
->dcb_state
&& bp
->dcbx_mode_uset
;
1893 static u8
bnx2x_dcbnl_get_state(struct net_device
*netdev
)
1895 struct bnx2x
*bp
= netdev_priv(netdev
);
1896 DP(BNX2X_MSG_DCB
, "state = %d\n", bp
->dcb_state
);
1897 return bp
->dcb_state
;
1900 static u8
bnx2x_dcbnl_set_state(struct net_device
*netdev
, u8 state
)
1902 struct bnx2x
*bp
= netdev_priv(netdev
);
1903 DP(BNX2X_MSG_DCB
, "state = %s\n", state
? "on" : "off");
1905 /* Fail to set state to "enabled" if dcbx is disabled in nvram */
1906 if (state
&& ((bp
->dcbx_enabled
== BNX2X_DCBX_ENABLED_OFF
) ||
1907 (bp
->dcbx_enabled
== BNX2X_DCBX_ENABLED_INVALID
))) {
1908 DP(BNX2X_MSG_DCB
, "Can not set dcbx to enabled while it is disabled in nvm\n");
1912 bnx2x_dcbx_set_state(bp
, (state
? true : false), bp
->dcbx_enabled
);
1916 static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device
*netdev
,
1919 struct bnx2x
*bp
= netdev_priv(netdev
);
1920 DP(BNX2X_MSG_DCB
, "GET-PERM-ADDR\n");
1922 /* first the HW mac address */
1923 memcpy(perm_addr
, netdev
->dev_addr
, netdev
->addr_len
);
1925 if (CNIC_LOADED(bp
))
1926 /* second SAN address */
1927 memcpy(perm_addr
+netdev
->addr_len
, bp
->fip_mac
,
1931 static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device
*netdev
, int prio
,
1932 u8 prio_type
, u8 pgid
, u8 bw_pct
,
1935 struct bnx2x
*bp
= netdev_priv(netdev
);
1937 DP(BNX2X_MSG_DCB
, "prio[%d] = %d\n", prio
, pgid
);
1938 if (!bnx2x_dcbnl_set_valid(bp
) || prio
>= DCBX_MAX_NUM_PRI_PG_ENTRIES
)
1942 * bw_pct ignored - band-width percentage devision between user
1943 * priorities within the same group is not
1944 * standard and hence not supported
1946 * prio_type ignored - priority levels within the same group are not
1947 * standard and hence are not supported. According
1948 * to the standard pgid 15 is dedicated to strict
1949 * priority traffic (on the port level).
1954 bp
->dcbx_config_params
.admin_configuration_ets_pg
[prio
] = pgid
;
1955 bp
->dcbx_config_params
.admin_ets_configuration_tx_enable
= 1;
1958 static void bnx2x_dcbnl_set_pg_bwgcfg_tx(struct net_device
*netdev
,
1959 int pgid
, u8 bw_pct
)
1961 struct bnx2x
*bp
= netdev_priv(netdev
);
1962 DP(BNX2X_MSG_DCB
, "pgid[%d] = %d\n", pgid
, bw_pct
);
1964 if (!bnx2x_dcbnl_set_valid(bp
) || pgid
>= DCBX_MAX_NUM_PG_BW_ENTRIES
)
1967 bp
->dcbx_config_params
.admin_configuration_bw_precentage
[pgid
] = bw_pct
;
1968 bp
->dcbx_config_params
.admin_ets_configuration_tx_enable
= 1;
1971 static void bnx2x_dcbnl_set_pg_tccfg_rx(struct net_device
*netdev
, int prio
,
1972 u8 prio_type
, u8 pgid
, u8 bw_pct
,
1975 struct bnx2x
*bp
= netdev_priv(netdev
);
1976 DP(BNX2X_MSG_DCB
, "Nothing to set; No RX support\n");
1979 static void bnx2x_dcbnl_set_pg_bwgcfg_rx(struct net_device
*netdev
,
1980 int pgid
, u8 bw_pct
)
1982 struct bnx2x
*bp
= netdev_priv(netdev
);
1983 DP(BNX2X_MSG_DCB
, "Nothing to set; No RX support\n");
1986 static void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device
*netdev
, int prio
,
1987 u8
*prio_type
, u8
*pgid
, u8
*bw_pct
,
1990 struct bnx2x
*bp
= netdev_priv(netdev
);
1991 DP(BNX2X_MSG_DCB
, "prio = %d\n", prio
);
1994 * bw_pct ignored - band-width percentage devision between user
1995 * priorities within the same group is not
1996 * standard and hence not supported
1998 * prio_type ignored - priority levels within the same group are not
1999 * standard and hence are not supported. According
2000 * to the standard pgid 15 is dedicated to strict
2001 * priority traffic (on the port level).
2005 *up_map
= *bw_pct
= *prio_type
= *pgid
= 0;
2007 if (!bp
->dcb_state
|| prio
>= DCBX_MAX_NUM_PRI_PG_ENTRIES
)
2010 *pgid
= DCBX_PRI_PG_GET(bp
->dcbx_local_feat
.ets
.pri_pg_tbl
, prio
);
2013 static void bnx2x_dcbnl_get_pg_bwgcfg_tx(struct net_device
*netdev
,
2014 int pgid
, u8
*bw_pct
)
2016 struct bnx2x
*bp
= netdev_priv(netdev
);
2017 DP(BNX2X_MSG_DCB
, "pgid = %d\n", pgid
);
2021 if (!bp
->dcb_state
|| pgid
>= DCBX_MAX_NUM_PG_BW_ENTRIES
)
2024 *bw_pct
= DCBX_PG_BW_GET(bp
->dcbx_local_feat
.ets
.pg_bw_tbl
, pgid
);
2027 static void bnx2x_dcbnl_get_pg_tccfg_rx(struct net_device
*netdev
, int prio
,
2028 u8
*prio_type
, u8
*pgid
, u8
*bw_pct
,
2031 struct bnx2x
*bp
= netdev_priv(netdev
);
2032 DP(BNX2X_MSG_DCB
, "Nothing to get; No RX support\n");
2034 *prio_type
= *pgid
= *bw_pct
= *up_map
= 0;
2037 static void bnx2x_dcbnl_get_pg_bwgcfg_rx(struct net_device
*netdev
,
2038 int pgid
, u8
*bw_pct
)
2040 struct bnx2x
*bp
= netdev_priv(netdev
);
2041 DP(BNX2X_MSG_DCB
, "Nothing to get; No RX support\n");
2046 static void bnx2x_dcbnl_set_pfc_cfg(struct net_device
*netdev
, int prio
,
2049 struct bnx2x
*bp
= netdev_priv(netdev
);
2050 DP(BNX2X_MSG_DCB
, "prio[%d] = %d\n", prio
, setting
);
2052 if (!bnx2x_dcbnl_set_valid(bp
) || prio
>= MAX_PFC_PRIORITIES
)
2056 bp
->dcbx_config_params
.admin_pfc_bitmap
|= (1 << prio
);
2057 bp
->dcbx_config_params
.admin_pfc_tx_enable
= 1;
2059 bp
->dcbx_config_params
.admin_pfc_bitmap
&= ~(1 << prio
);
2063 static void bnx2x_dcbnl_get_pfc_cfg(struct net_device
*netdev
, int prio
,
2066 struct bnx2x
*bp
= netdev_priv(netdev
);
2067 DP(BNX2X_MSG_DCB
, "prio = %d\n", prio
);
2071 if (!bp
->dcb_state
|| prio
>= MAX_PFC_PRIORITIES
)
2074 *setting
= (bp
->dcbx_local_feat
.pfc
.pri_en_bitmap
>> prio
) & 0x1;
2077 static u8
bnx2x_dcbnl_set_all(struct net_device
*netdev
)
2079 struct bnx2x
*bp
= netdev_priv(netdev
);
2082 DP(BNX2X_MSG_DCB
, "SET-ALL\n");
2084 if (!bnx2x_dcbnl_set_valid(bp
))
2087 if (bp
->recovery_state
!= BNX2X_RECOVERY_DONE
) {
2089 "Handling parity error recovery. Try again later\n");
2092 if (netif_running(bp
->dev
)) {
2093 bnx2x_update_drv_flags(bp
,
2094 1 << DRV_FLAGS_DCB_MFW_CONFIGURED
,
2096 bnx2x_dcbx_init(bp
, true);
2098 DP(BNX2X_MSG_DCB
, "set_dcbx_params done (%d)\n", rc
);
2105 static u8
bnx2x_dcbnl_get_cap(struct net_device
*netdev
, int capid
, u8
*cap
)
2107 struct bnx2x
*bp
= netdev_priv(netdev
);
2110 if (bp
->dcb_state
) {
2112 case DCB_CAP_ATTR_PG
:
2115 case DCB_CAP_ATTR_PFC
:
2118 case DCB_CAP_ATTR_UP2TC
:
2121 case DCB_CAP_ATTR_PG_TCS
:
2122 *cap
= 0x80; /* 8 priorities for PGs */
2124 case DCB_CAP_ATTR_PFC_TCS
:
2125 *cap
= 0x80; /* 8 priorities for PFC */
2127 case DCB_CAP_ATTR_GSP
:
2130 case DCB_CAP_ATTR_BCN
:
2133 case DCB_CAP_ATTR_DCBX
:
2134 *cap
= BNX2X_DCBX_CAPS
;
2137 BNX2X_ERR("Non valid capability ID\n");
2142 DP(BNX2X_MSG_DCB
, "DCB disabled\n");
2146 DP(BNX2X_MSG_DCB
, "capid %d:%x\n", capid
, *cap
);
2150 static int bnx2x_dcbnl_get_numtcs(struct net_device
*netdev
, int tcid
, u8
*num
)
2152 struct bnx2x
*bp
= netdev_priv(netdev
);
2155 DP(BNX2X_MSG_DCB
, "tcid %d\n", tcid
);
2157 if (bp
->dcb_state
) {
2159 case DCB_NUMTCS_ATTR_PG
:
2160 *num
= CHIP_IS_E3B0(bp
) ? DCBX_COS_MAX_NUM_E3B0
:
2161 DCBX_COS_MAX_NUM_E2
;
2163 case DCB_NUMTCS_ATTR_PFC
:
2164 *num
= CHIP_IS_E3B0(bp
) ? DCBX_COS_MAX_NUM_E3B0
:
2165 DCBX_COS_MAX_NUM_E2
;
2168 BNX2X_ERR("Non valid TC-ID\n");
2173 DP(BNX2X_MSG_DCB
, "DCB disabled\n");
2180 static int bnx2x_dcbnl_set_numtcs(struct net_device
*netdev
, int tcid
, u8 num
)
2182 struct bnx2x
*bp
= netdev_priv(netdev
);
2183 DP(BNX2X_MSG_DCB
, "num tcs = %d; Not supported\n", num
);
2187 static u8
bnx2x_dcbnl_get_pfc_state(struct net_device
*netdev
)
2189 struct bnx2x
*bp
= netdev_priv(netdev
);
2190 DP(BNX2X_MSG_DCB
, "state = %d\n", bp
->dcbx_local_feat
.pfc
.enabled
);
2195 return bp
->dcbx_local_feat
.pfc
.enabled
;
2198 static void bnx2x_dcbnl_set_pfc_state(struct net_device
*netdev
, u8 state
)
2200 struct bnx2x
*bp
= netdev_priv(netdev
);
2201 DP(BNX2X_MSG_DCB
, "state = %s\n", state
? "on" : "off");
2203 if (!bnx2x_dcbnl_set_valid(bp
))
2206 bp
->dcbx_config_params
.admin_pfc_tx_enable
=
2207 bp
->dcbx_config_params
.admin_pfc_enable
= (state
? 1 : 0);
2210 static void bnx2x_admin_app_set_ent(
2211 struct bnx2x_admin_priority_app_table
*app_ent
,
2212 u8 idtype
, u16 idval
, u8 up
)
2217 case DCB_APP_IDTYPE_ETHTYPE
:
2218 app_ent
->traffic_type
= TRAFFIC_TYPE_ETH
;
2220 case DCB_APP_IDTYPE_PORTNUM
:
2221 app_ent
->traffic_type
= TRAFFIC_TYPE_PORT
;
2224 break; /* never gets here */
2226 app_ent
->app_id
= idval
;
2227 app_ent
->priority
= up
;
2230 static bool bnx2x_admin_app_is_equal(
2231 struct bnx2x_admin_priority_app_table
*app_ent
,
2232 u8 idtype
, u16 idval
)
2234 if (!app_ent
->valid
)
2238 case DCB_APP_IDTYPE_ETHTYPE
:
2239 if (app_ent
->traffic_type
!= TRAFFIC_TYPE_ETH
)
2242 case DCB_APP_IDTYPE_PORTNUM
:
2243 if (app_ent
->traffic_type
!= TRAFFIC_TYPE_PORT
)
2249 if (app_ent
->app_id
!= idval
)
2255 static int bnx2x_set_admin_app_up(struct bnx2x
*bp
, u8 idtype
, u16 idval
, u8 up
)
2259 /* iterate over the app entries looking for idtype and idval */
2260 for (i
= 0, ff
= -1; i
< DCBX_CONFIG_MAX_APP_PROTOCOL
; i
++) {
2261 struct bnx2x_admin_priority_app_table
*app_ent
=
2262 &bp
->dcbx_config_params
.admin_priority_app_table
[i
];
2263 if (bnx2x_admin_app_is_equal(app_ent
, idtype
, idval
))
2266 if (ff
< 0 && !app_ent
->valid
)
2269 if (i
< DCBX_CONFIG_MAX_APP_PROTOCOL
)
2270 /* if found overwrite up */
2271 bp
->dcbx_config_params
.
2272 admin_priority_app_table
[i
].priority
= up
;
2274 /* not found use first-free */
2275 bnx2x_admin_app_set_ent(
2276 &bp
->dcbx_config_params
.admin_priority_app_table
[ff
],
2279 /* app table is full */
2280 BNX2X_ERR("Application table is too large\n");
2284 /* up configured, if not 0 make sure feature is enabled */
2286 bp
->dcbx_config_params
.admin_application_priority_tx_enable
= 1;
2291 static u8
bnx2x_dcbnl_set_app_up(struct net_device
*netdev
, u8 idtype
,
2294 struct bnx2x
*bp
= netdev_priv(netdev
);
2296 DP(BNX2X_MSG_DCB
, "app_type %d, app_id %x, prio bitmap %d\n",
2299 if (!bnx2x_dcbnl_set_valid(bp
)) {
2300 DP(BNX2X_MSG_DCB
, "dcbnl call not valid\n");
2306 case DCB_APP_IDTYPE_ETHTYPE
:
2307 case DCB_APP_IDTYPE_PORTNUM
:
2310 DP(BNX2X_MSG_DCB
, "Wrong ID type\n");
2313 return bnx2x_set_admin_app_up(bp
, idtype
, idval
, up
);
2316 static u8
bnx2x_dcbnl_get_dcbx(struct net_device
*netdev
)
2318 struct bnx2x
*bp
= netdev_priv(netdev
);
2321 state
= DCB_CAP_DCBX_LLD_MANAGED
| DCB_CAP_DCBX_VER_CEE
;
2323 if (bp
->dcbx_enabled
== BNX2X_DCBX_ENABLED_ON_NEG_OFF
)
2324 state
|= DCB_CAP_DCBX_STATIC
;
2329 static u8
bnx2x_dcbnl_set_dcbx(struct net_device
*netdev
, u8 state
)
2331 struct bnx2x
*bp
= netdev_priv(netdev
);
2332 DP(BNX2X_MSG_DCB
, "state = %02x\n", state
);
2336 if ((state
& BNX2X_DCBX_CAPS
) != state
) {
2337 BNX2X_ERR("Requested DCBX mode %x is beyond advertised capabilities\n",
2342 if (bp
->dcb_state
!= BNX2X_DCB_STATE_ON
) {
2343 BNX2X_ERR("DCB turned off, DCBX configuration is invalid\n");
2347 if (state
& DCB_CAP_DCBX_STATIC
)
2348 bp
->dcbx_enabled
= BNX2X_DCBX_ENABLED_ON_NEG_OFF
;
2350 bp
->dcbx_enabled
= BNX2X_DCBX_ENABLED_ON_NEG_ON
;
2352 bp
->dcbx_mode_uset
= true;
2356 static u8
bnx2x_dcbnl_get_featcfg(struct net_device
*netdev
, int featid
,
2359 struct bnx2x
*bp
= netdev_priv(netdev
);
2362 DP(BNX2X_MSG_DCB
, "featid %d\n", featid
);
2364 if (bp
->dcb_state
) {
2367 case DCB_FEATCFG_ATTR_PG
:
2368 if (bp
->dcbx_local_feat
.ets
.enabled
)
2369 *flags
|= DCB_FEATCFG_ENABLE
;
2370 if (bp
->dcbx_error
& DCBX_LOCAL_ETS_ERROR
)
2371 *flags
|= DCB_FEATCFG_ERROR
;
2373 case DCB_FEATCFG_ATTR_PFC
:
2374 if (bp
->dcbx_local_feat
.pfc
.enabled
)
2375 *flags
|= DCB_FEATCFG_ENABLE
;
2376 if (bp
->dcbx_error
& (DCBX_LOCAL_PFC_ERROR
|
2377 DCBX_LOCAL_PFC_MISMATCH
))
2378 *flags
|= DCB_FEATCFG_ERROR
;
2380 case DCB_FEATCFG_ATTR_APP
:
2381 if (bp
->dcbx_local_feat
.app
.enabled
)
2382 *flags
|= DCB_FEATCFG_ENABLE
;
2383 if (bp
->dcbx_error
& (DCBX_LOCAL_APP_ERROR
|
2384 DCBX_LOCAL_APP_MISMATCH
))
2385 *flags
|= DCB_FEATCFG_ERROR
;
2388 BNX2X_ERR("Non valid feature-ID\n");
2393 DP(BNX2X_MSG_DCB
, "DCB disabled\n");
2400 static u8
bnx2x_dcbnl_set_featcfg(struct net_device
*netdev
, int featid
,
2403 struct bnx2x
*bp
= netdev_priv(netdev
);
2406 DP(BNX2X_MSG_DCB
, "featid = %d flags = %02x\n", featid
, flags
);
2408 /* ignore the 'advertise' flag */
2409 if (bnx2x_dcbnl_set_valid(bp
)) {
2411 case DCB_FEATCFG_ATTR_PG
:
2412 bp
->dcbx_config_params
.admin_ets_enable
=
2413 flags
& DCB_FEATCFG_ENABLE
? 1 : 0;
2414 bp
->dcbx_config_params
.admin_ets_willing
=
2415 flags
& DCB_FEATCFG_WILLING
? 1 : 0;
2417 case DCB_FEATCFG_ATTR_PFC
:
2418 bp
->dcbx_config_params
.admin_pfc_enable
=
2419 flags
& DCB_FEATCFG_ENABLE
? 1 : 0;
2420 bp
->dcbx_config_params
.admin_pfc_willing
=
2421 flags
& DCB_FEATCFG_WILLING
? 1 : 0;
2423 case DCB_FEATCFG_ATTR_APP
:
2424 /* ignore enable, always enabled */
2425 bp
->dcbx_config_params
.admin_app_priority_willing
=
2426 flags
& DCB_FEATCFG_WILLING
? 1 : 0;
2429 BNX2X_ERR("Non valid feature-ID\n");
2434 DP(BNX2X_MSG_DCB
, "dcbnl call not valid\n");
2441 static int bnx2x_peer_appinfo(struct net_device
*netdev
,
2442 struct dcb_peer_app_info
*info
, u16
* app_count
)
2445 struct bnx2x
*bp
= netdev_priv(netdev
);
2447 DP(BNX2X_MSG_DCB
, "APP-INFO\n");
2449 info
->willing
= (bp
->dcbx_remote_flags
& DCBX_APP_REM_WILLING
) ?: 0;
2450 info
->error
= (bp
->dcbx_remote_flags
& DCBX_APP_RX_ERROR
) ?: 0;
2453 for (i
= 0; i
< DCBX_MAX_APP_PROTOCOL
; i
++)
2454 if (bp
->dcbx_remote_feat
.app
.app_pri_tbl
[i
].appBitfield
&
2455 DCBX_APP_ENTRY_VALID
)
2460 static int bnx2x_peer_apptable(struct net_device
*netdev
,
2461 struct dcb_app
*table
)
2464 struct bnx2x
*bp
= netdev_priv(netdev
);
2466 DP(BNX2X_MSG_DCB
, "APP-TABLE\n");
2468 for (i
= 0, j
= 0; i
< DCBX_MAX_APP_PROTOCOL
; i
++) {
2469 struct dcbx_app_priority_entry
*ent
=
2470 &bp
->dcbx_remote_feat
.app
.app_pri_tbl
[i
];
2472 if (ent
->appBitfield
& DCBX_APP_ENTRY_VALID
) {
2473 table
[j
].selector
= bnx2x_dcbx_dcbnl_app_idtype(ent
);
2474 table
[j
].priority
= bnx2x_dcbx_dcbnl_app_up(ent
);
2475 table
[j
++].protocol
= ent
->app_id
;
2481 static int bnx2x_cee_peer_getpg(struct net_device
*netdev
, struct cee_pg
*pg
)
2484 struct bnx2x
*bp
= netdev_priv(netdev
);
2486 pg
->willing
= (bp
->dcbx_remote_flags
& DCBX_ETS_REM_WILLING
) ?: 0;
2488 for (i
= 0; i
< CEE_DCBX_MAX_PGS
; i
++) {
2490 DCBX_PG_BW_GET(bp
->dcbx_remote_feat
.ets
.pg_bw_tbl
, i
);
2492 DCBX_PRI_PG_GET(bp
->dcbx_remote_feat
.ets
.pri_pg_tbl
, i
);
2497 static int bnx2x_cee_peer_getpfc(struct net_device
*netdev
,
2498 struct cee_pfc
*pfc
)
2500 struct bnx2x
*bp
= netdev_priv(netdev
);
2501 pfc
->tcs_supported
= bp
->dcbx_remote_feat
.pfc
.pfc_caps
;
2502 pfc
->pfc_en
= bp
->dcbx_remote_feat
.pfc
.pri_en_bitmap
;
2506 const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops
= {
2507 .getstate
= bnx2x_dcbnl_get_state
,
2508 .setstate
= bnx2x_dcbnl_set_state
,
2509 .getpermhwaddr
= bnx2x_dcbnl_get_perm_hw_addr
,
2510 .setpgtccfgtx
= bnx2x_dcbnl_set_pg_tccfg_tx
,
2511 .setpgbwgcfgtx
= bnx2x_dcbnl_set_pg_bwgcfg_tx
,
2512 .setpgtccfgrx
= bnx2x_dcbnl_set_pg_tccfg_rx
,
2513 .setpgbwgcfgrx
= bnx2x_dcbnl_set_pg_bwgcfg_rx
,
2514 .getpgtccfgtx
= bnx2x_dcbnl_get_pg_tccfg_tx
,
2515 .getpgbwgcfgtx
= bnx2x_dcbnl_get_pg_bwgcfg_tx
,
2516 .getpgtccfgrx
= bnx2x_dcbnl_get_pg_tccfg_rx
,
2517 .getpgbwgcfgrx
= bnx2x_dcbnl_get_pg_bwgcfg_rx
,
2518 .setpfccfg
= bnx2x_dcbnl_set_pfc_cfg
,
2519 .getpfccfg
= bnx2x_dcbnl_get_pfc_cfg
,
2520 .setall
= bnx2x_dcbnl_set_all
,
2521 .getcap
= bnx2x_dcbnl_get_cap
,
2522 .getnumtcs
= bnx2x_dcbnl_get_numtcs
,
2523 .setnumtcs
= bnx2x_dcbnl_set_numtcs
,
2524 .getpfcstate
= bnx2x_dcbnl_get_pfc_state
,
2525 .setpfcstate
= bnx2x_dcbnl_set_pfc_state
,
2526 .setapp
= bnx2x_dcbnl_set_app_up
,
2527 .getdcbx
= bnx2x_dcbnl_get_dcbx
,
2528 .setdcbx
= bnx2x_dcbnl_set_dcbx
,
2529 .getfeatcfg
= bnx2x_dcbnl_get_featcfg
,
2530 .setfeatcfg
= bnx2x_dcbnl_set_featcfg
,
2531 .peer_getappinfo
= bnx2x_peer_appinfo
,
2532 .peer_getapptable
= bnx2x_peer_apptable
,
2533 .cee_peer_getpg
= bnx2x_cee_peer_getpg
,
2534 .cee_peer_getpfc
= bnx2x_cee_peer_getpfc
,
2537 #endif /* BCM_DCBNL */