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