/drivers/net/bnx2x/bnx2x_dcb.c
C | 2244 lines | 1715 code | 314 blank | 215 comment | 285 complexity | bc38dcdc789678075fe6476f3b8bde4a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
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_vali…
Large files files are truncated, but you can click here to view the full file