port.c (21925B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 */ 8 9 #include <soc/defs.h> 10 11 #include <assert.h> 12 #include <shared/bsl.h> 13 #include <sal/core/libc.h> 14 #if defined(BCM_HURRICANE2_SUPPORT) 15 16 #include <shared/util.h> 17 #include <soc/mem.h> 18 #include <soc/cm.h> 19 #include <soc/drv.h> 20 #include <soc/register.h> 21 #include <soc/memory.h> 22 #include <soc/hurricane2.h> 23 #include <bcm/error.h> 24 #include <bcm_int/esw/port.h> 25 #include <bcm_int/esw/firebolt.h> 26 #include <bcm_int/esw/trx.h> 27 #include <bcm_int/esw/xgs3.h> 28 29 #include <bcm_int/esw_dispatch.h> 30 31 /* 32 * Each TSC can be configured into following 5 mode: 33 * Lane number 0 1 2 3 34 * ------------ --- --- --- --- 35 * single port 40G x x x 36 * dual port 20G x 20G x 37 * tri_023 port 20G x 10G 10G 38 * tri_012 port 10G 10G 20G x 39 * quad port 10G 10G 10G 10G 40 * 41 * lanes mode valid lane index 42 * ------------ ---------------- ---------------- 43 * new current new current 44 * --- ------- ------- ------- 45 * #1 4 1 single quad 0 46 * #2 4 1 single tri_012 0 47 * #3 4 2 single tri_023 0 48 * #4 4 2 single dual 0 49 * #5 2 1 tri_023 quad 0 50 * #6 2 1 tri_012 quad 2 51 * #7 2 1 dual tri_023 2 52 * #8 2 1 dual tri_012 0 53 * #9 2 4 dual single 0 54 * #10 1 2 tri_023 dual 2 55 * #11 1 2 tri_012 dual 0 56 * #12 1 2 quad tri_023 0 57 * #13 1 2 quad tri_012 2 58 * #14 1 4 quad single 0 59 * Following mode change requires 2 transition 60 * - from single to tri_023: #9 + #10 61 * - from single to tri_012: #9 + #11 62 * Following mode change are the result of lane change on multiple ports 63 * - from quad to dual: #12 + #7 or #13 + #8 64 * - from dual to quad: #10 + #12 or #11 + # 13 65 * - from tri_023 to tri_012: #7 + #11 or #12 + #6 66 * - from tri_012 to tri_023: #8 + #10 or #13 + #5 67 * 68 * Logical port number will stay the same after conversion, for example 69 * converting single port to dual port, the logical port number of lane 0 70 * will be changed. 71 */ 72 int 73 soc_hurricane2_port_lanes_set(int unit, soc_port_t port_base, int lanes, 74 int *cur_lanes, int *phy_ports, int *phy_ports_len) 75 { 76 soc_info_t *si = &SOC_INFO(unit); 77 soc_field_t fields[2]; 78 uint32 values[2]; 79 int mode, cur_mode; 80 int phy_port_base, port, i; 81 int blk, bindex; 82 uint32 rval; 83 84 /* Find physical port number and lane index of the specified port */ 85 phy_port_base = si->port_l2p_mapping[port_base]; 86 if (phy_port_base == -1) { 87 return SOC_E_PORT; 88 } 89 90 bindex = -1; 91 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 92 blk = SOC_PORT_IDX_BLOCK(unit, phy_port_base, i); 93 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT) { 94 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port_base, i); 95 break; 96 } 97 } 98 99 /* Get the current mode */ 100 SOC_IF_ERROR_RETURN(READ_XLPORT_MODE_REGr(unit, port_base, &rval)); 101 cur_mode = soc_reg_field_get(unit, XLPORT_MODE_REGr, rval, 102 XPORT0_CORE_PORT_MODEf); 103 104 /* Figure out the current number of lane from current mode */ 105 switch (cur_mode) { 106 case SOC_HU2_PORT_MODE_QUAD: 107 *cur_lanes = 1; 108 break; 109 case SOC_HU2_PORT_MODE_TRI_012: 110 *cur_lanes = bindex == 0 ? 1 : 2; 111 break; 112 case SOC_HU2_PORT_MODE_TRI_023: 113 *cur_lanes = bindex == 0 ? 2 : 1; 114 break; 115 case SOC_HU2_PORT_MODE_DUAL: 116 *cur_lanes = 2; 117 break; 118 case SOC_HU2_PORT_MODE_SINGLE: 119 *cur_lanes = 4; 120 break; 121 default: 122 return SOC_E_FAIL; 123 } 124 125 if (lanes == 4 || *cur_lanes == 4) { 126 if (bindex & 0x3) { 127 return SOC_E_PARAM; 128 } 129 } else if (lanes == 2 || *cur_lanes == 2) { 130 if (bindex & 0x1) { 131 return SOC_E_PARAM; 132 } 133 } 134 135 if (lanes == *cur_lanes) { 136 return SOC_E_NONE; 137 } 138 139 /* Figure out new mode */ 140 if (lanes == 4) { 141 mode = SOC_HU2_PORT_MODE_SINGLE; 142 } else if (lanes == 2) { 143 if (cur_mode == SOC_HU2_PORT_MODE_QUAD) { 144 mode = bindex == 0 ? 145 SOC_HU2_PORT_MODE_TRI_023 : SOC_HU2_PORT_MODE_TRI_012; 146 } else { 147 mode = SOC_HU2_PORT_MODE_DUAL; 148 } 149 } else{ 150 if (cur_mode == SOC_HU2_PORT_MODE_DUAL) { 151 mode = bindex == 0 ? 152 SOC_HU2_PORT_MODE_TRI_012 : SOC_HU2_PORT_MODE_TRI_023; 153 } else { 154 mode = SOC_HU2_PORT_MODE_QUAD; 155 } 156 } 157 158 *phy_ports_len = 0; 159 if (lanes > *cur_lanes) { /* Figure out which port(s) to be removed */ 160 if (lanes == 4) { 161 if (cur_mode == SOC_HU2_PORT_MODE_TRI_012 || 162 cur_mode == SOC_HU2_PORT_MODE_QUAD) { 163 if (si->port_p2l_mapping[phy_port_base + 1] != -1) { 164 phy_ports[(*phy_ports_len)++] = phy_port_base + 1; 165 } 166 } 167 if (si->port_p2l_mapping[phy_port_base + 2] != -1) { 168 phy_ports[(*phy_ports_len)++] = phy_port_base + 2; 169 } 170 if (cur_mode == SOC_HU2_PORT_MODE_TRI_023 || 171 cur_mode == SOC_HU2_PORT_MODE_QUAD) { 172 if (si->port_p2l_mapping[phy_port_base + 3] != -1) { 173 phy_ports[(*phy_ports_len)++] = phy_port_base + 3; 174 } 175 } 176 } else { 177 if (si->port_p2l_mapping[phy_port_base + 1] != -1) { 178 phy_ports[(*phy_ports_len)++] = phy_port_base + 1; 179 } 180 } 181 } else { /* Figure out which port(s) to be added */ 182 if (lanes == 2) { 183 if (si->port_p2l_mapping[phy_port_base + 2] != -1) { 184 phy_ports[(*phy_ports_len)++] = phy_port_base + 2; 185 } 186 } else { 187 if (si->port_p2l_mapping[phy_port_base + 1] != -1) { 188 phy_ports[(*phy_ports_len)++] = phy_port_base + 1; 189 } 190 if (cur_mode == SOC_HU2_PORT_MODE_SINGLE) { 191 if (si->port_p2l_mapping[phy_port_base + 2] != -1) { 192 phy_ports[(*phy_ports_len)++] = phy_port_base + 2; 193 } 194 if (si->port_p2l_mapping[phy_port_base + 3] != -1) { 195 phy_ports[(*phy_ports_len)++] = phy_port_base + 3; 196 } 197 } 198 } 199 } 200 201 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 202 static char *mode_name[] = { 203 "QUAD", "TRI_012", "TRI_023", "DUAL", "SINGLE" 204 }; 205 LOG_CLI((BSL_META_U(unit, 206 "port %d physical port %d bindex %d\n"), 207 port_base, phy_port_base, bindex)); 208 LOG_CLI((BSL_META_U(unit, 209 "mode (new:%s cur:%s) lanes (new:%d cur:%d)\n"), 210 mode_name[mode], mode_name[cur_mode], lanes, *cur_lanes)); 211 for (i = 0; i < *phy_ports_len; i++) { 212 LOG_CLI((BSL_META_U(unit, 213 "%s physical port %d (port %d)\n"), 214 lanes > *cur_lanes ? "del" : "add", 215 phy_ports[i], si->port_p2l_mapping[phy_ports[i]])); 216 } 217 } 218 219 /* Update soc_control information */ 220 SOC_CONTROL_LOCK(unit); 221 if (lanes > *cur_lanes) { /* port(s) to be removed */ 222 for (i = 0; i < *phy_ports_len; i++) { 223 port = si->port_p2l_mapping[phy_ports[i]]; 224 SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port); 225 if (IS_HG_PORT(unit, phy_ports[i])) { 226 SOC_PBMP_PORT_REMOVE(si->st.bitmap, port); 227 SOC_PBMP_PORT_REMOVE(si->hg.bitmap, port); 228 } else { 229 SOC_PBMP_PORT_REMOVE(si->ether.bitmap, port); 230 if (IS_GE_PORT(unit, port)) { 231 SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port); 232 } else { 233 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port); 234 } 235 } 236 } 237 } else { /* port(s) to be added */ 238 for (i = 0; i < *phy_ports_len; i++) { 239 port = si->port_p2l_mapping[phy_ports[i]]; 240 SOC_PBMP_PORT_REMOVE(si->all.disabled_bitmap, port); 241 if (IS_HG_PORT(unit, port)) { 242 SOC_PBMP_PORT_ADD(si->st.bitmap, port); 243 SOC_PBMP_PORT_ADD(si->hg.bitmap, port); 244 } else { 245 SOC_PBMP_PORT_ADD(si->ether.bitmap, port); 246 if (IS_GE_PORT(unit, port)) { 247 SOC_PBMP_PORT_ADD(si->ge.bitmap, port); 248 } else { 249 SOC_PBMP_PORT_ADD(si->xe.bitmap, port); 250 } 251 } 252 } 253 } 254 255 #define RECONFIGURE_PORT_TYPE_INFO(ptype) \ 256 si->ptype.num = 0; \ 257 si->ptype.min = si->ptype.max = -1; \ 258 PBMP_ITER(si->ptype.bitmap, port) { \ 259 si->ptype.port[si->ptype.num++] = port; \ 260 if (si->ptype.min < 0) { \ 261 si->ptype.min = port; \ 262 } \ 263 if (port > si->ptype.max) { \ 264 si->ptype.max = port; \ 265 } \ 266 } 267 268 RECONFIGURE_PORT_TYPE_INFO(ether); 269 RECONFIGURE_PORT_TYPE_INFO(st); 270 RECONFIGURE_PORT_TYPE_INFO(hg); 271 RECONFIGURE_PORT_TYPE_INFO(xe); 272 RECONFIGURE_PORT_TYPE_INFO(ge); 273 274 #undef RECONFIGURE_PORT_TYPE_INFO 275 276 /* Update num of lanes info which is used by SerDes driver */ 277 SOC_PORT_NUM_LANES_SET(unit, port_base, lanes); 278 for (i = 0; i < *phy_ports_len; i++) { 279 port = si->port_p2l_mapping[phy_ports[i]]; 280 SOC_PORT_NUM_LANES_SET(unit, port, lanes > *cur_lanes ? 0 : lanes); 281 } 282 283 soc_dport_map_update(unit); 284 SOC_CONTROL_UNLOCK(unit); 285 286 fields[0] = XPORT0_CORE_PORT_MODEf; 287 values[0] = mode; 288 fields[1] = XPORT0_PHY_PORT_MODEf; 289 values[1] = mode; 290 SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, XLPORT_MODE_REGr, 291 port_base, 2, fields, values)); 292 293 if (*phy_ports_len == 0) { 294 return SOC_E_NONE; 295 } 296 297 /* Update TDM */ 298 #ifdef _HURRICANE2_DEBUG 299 SOC_IF_ERROR_RETURN 300 (_soc_hurricane2_port_lanes_update_tdm(unit, port_base, lanes, 301 *cur_lanes, phy_ports, 302 *phy_ports_len)); 303 #endif 304 return SOC_E_NONE; 305 } 306 307 308 int 309 soc_hurricane2_port_lanes_get(int unit, soc_port_t port_base, int *cur_lanes) 310 { 311 soc_info_t *si = &SOC_INFO(unit); 312 int cur_mode; 313 int phy_port_base, i; 314 int blk, bindex; 315 uint32 rval; 316 317 /* Find physical port number and lane index of the specified port */ 318 phy_port_base = si->port_l2p_mapping[port_base]; 319 if (phy_port_base == -1) { 320 return SOC_E_PORT; 321 } 322 323 bindex = -1; 324 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 325 blk = SOC_PORT_IDX_BLOCK(unit, phy_port_base, i); 326 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT) { 327 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port_base, i); 328 break; 329 } 330 } 331 332 /* Get the current mode */ 333 SOC_IF_ERROR_RETURN(READ_XLPORT_MODE_REGr(unit, port_base, &rval)); 334 cur_mode = soc_reg_field_get(unit, XLPORT_MODE_REGr, rval, 335 XPORT0_CORE_PORT_MODEf); 336 337 /* Figure out the current number of lane from current mode */ 338 switch (cur_mode) { 339 case SOC_HU2_PORT_MODE_QUAD: 340 *cur_lanes = 1; 341 break; 342 case SOC_HU2_PORT_MODE_TRI_012: 343 *cur_lanes = bindex == 0 ? 1 : 2; 344 break; 345 case SOC_HU2_PORT_MODE_TRI_023: 346 *cur_lanes = bindex == 0 ? 2 : 1; 347 break; 348 case SOC_HU2_PORT_MODE_DUAL: 349 *cur_lanes = 2; 350 break; 351 case SOC_HU2_PORT_MODE_SINGLE: 352 *cur_lanes = 4; 353 break; 354 default: 355 return SOC_E_FAIL; 356 } 357 358 return SOC_E_NONE; 359 } 360 361 int 362 _bcm_hr2_dual_port_mode_pilot_tx(int unit, int port, bcm_pkt_t *pkt) { 363 int rv; 364 uint64 old_tpok; 365 uint64 new_tpok; 366 uint64 tx_ctl; 367 368 /* Save original counter */ 369 SOC_IF_ERROR_RETURN(READ_TPOKr(unit, port, &old_tpok)); 370 371 /* Setup */ 372 if (bcm_esw_port_loopback_set(unit, port, BCM_PORT_LOOPBACK_PHY) < 0) { 373 LOG_ERROR(BSL_LS_BCM_PORT, 374 (BSL_META_U(unit, 375 "Port %d LoopBack Set Failed\n"), port)); 376 } 377 /* 378 * stop the packet from actually going out on the wire, 379 * while still incrementing the MAC counters 380 */ 381 SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &tx_ctl)); 382 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &tx_ctl, DISCARDf, 1); 383 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, tx_ctl)); 384 385 /* Send Packets */ 386 BCM_PBMP_CLEAR(pkt->tx_pbmp); 387 BCM_PBMP_PORT_ADD(pkt->tx_pbmp, port); 388 rv = bcm_esw_tx(unit, pkt, NULL); 389 if (rv < 0) { 390 LOG_ERROR(BSL_LS_BCM_PORT, 391 (BSL_META_U(unit, 392 "Tx Error %d\n"), rv)); 393 return BCM_E_INTERNAL; 394 } 395 sal_udelay(10000); 396 397 /* Verify Counters */ 398 SOC_IF_ERROR_RETURN(READ_TPOKr(unit, port, &new_tpok)); 399 LOG_VERBOSE(BSL_LS_BCM_PORT, \ 400 (BSL_META_U(unit, \ 401 "old TPOK(port=%d)=0x%x, 0x%x\n"), \ 402 port, COMPILER_64_HI(old_tpok), COMPILER_64_LO(old_tpok))); 403 LOG_VERBOSE(BSL_LS_BCM_PORT, \ 404 (BSL_META_U(unit, \ 405 "new TPOK(port=%d)=0x%x, 0x%x\n"), \ 406 port, COMPILER_64_HI(new_tpok), COMPILER_64_LO(new_tpok))); 407 if ((COMPILER_64_HI(new_tpok) == COMPILER_64_HI(old_tpok)) && \ 408 (COMPILER_64_LO(new_tpok) == COMPILER_64_LO(old_tpok))) { 409 /* packet not transmit out */ 410 return BCM_E_FAIL; 411 } 412 LOG_VERBOSE(BSL_LS_BCM_PORT, \ 413 (BSL_META_U(unit, \ 414 "Dual port mode check pass on port %d\n"),port)); 415 416 /* Cleanup */ 417 if (bcm_esw_l2_addr_delete_by_port(unit, -1, port, 0) < 0) { 418 LOG_ERROR(BSL_LS_BCM_PORT, 419 (BSL_META_U(unit, 420 "Port %d L2 entry delete Failed\n"), port)); 421 } 422 SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &tx_ctl)); 423 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &tx_ctl, DISCARDf, 0); 424 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, tx_ctl)); 425 if (bcm_esw_port_loopback_set(unit, port, BCM_PORT_LOOPBACK_NONE) < 0) { 426 LOG_ERROR(BSL_LS_BCM_PORT, 427 (BSL_META_U(unit, 428 "Port %d LoopBack Set Failed\n"), port)); 429 } 430 if (bcm_esw_stat_clear(unit, port) < 0) { 431 LOG_ERROR(BSL_LS_BCM_PORT, 432 (BSL_META_U(unit, 433 "Port %d Stat Clear Failed\n"), port)); 434 } 435 return rv; 436 } 437 438 int _bcm_hr2_dual_port_mode_check(int unit, bcm_port_t port, uint32 *tx_pkt) 439 { 440 bcm_pkt_t pkt_info; 441 uint32 rval = 0; 442 int mode = 0; 443 int timeout_cnt = 0; 444 int i; 445 int rv = 0; 446 sal_memset(&pkt_info, 0, sizeof(bcm_pkt_t)); 447 pkt_info.unit = unit; 448 pkt_info._pkt_data.data = (uint8 *) tx_pkt; 449 pkt_info.pkt_data = &pkt_info._pkt_data; 450 pkt_info.blk_count = 1; 451 pkt_info._pkt_data.len = 68; 452 pkt_info.call_back = NULL; 453 pkt_info.flags = 0x20; 454 455 timeout_cnt = 0; 456 for (i = 0; i < 10 ; i++) { 457 /* coverity[overrun-buffer-val] */ 458 rv = _bcm_hr2_dual_port_mode_pilot_tx(unit, port, &pkt_info); 459 if (rv == BCM_E_NONE) { 460 break; 461 } else { 462 /* Re-write the MODEs */ 463 /* program the port to quad port mode */ 464 LOG_VERBOSE(BSL_LS_BCM_PORT, \ 465 (BSL_META_U(unit, \ 466 "WAR step 1: program the port to quad port mode\n"))); 467 mode = 0; /* quad port mode */ 468 SOC_IF_ERROR_RETURN(READ_XLPORT_MODE_REGr(unit, port, &rval)); 469 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, 470 XPORT0_CORE_PORT_MODEf, mode); 471 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, 472 XPORT0_PHY_PORT_MODEf, mode); 473 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, port, rval)); 474 475 /* re-program the port to dual port mode */ 476 LOG_VERBOSE(BSL_LS_BCM_PORT, \ 477 (BSL_META_U(unit, \ 478 "WAR step 2: re-program the port to dual port mode\n"))); 479 mode = 3; /* dual port mode */ 480 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, 481 XPORT0_CORE_PORT_MODEf, mode); 482 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, 483 XPORT0_PHY_PORT_MODEf, mode); 484 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, port, rval)); 485 } 486 timeout_cnt++; 487 } 488 LOG_VERBOSE(BSL_LS_BCM_PORT, \ 489 (BSL_META_U(unit, \ 490 "WAR retried %d times on port %d\n"), timeout_cnt, port)); 491 if (timeout_cnt >= 10) { 492 return BCM_E_TIMEOUT; 493 } 494 return BCM_E_NONE; 495 } 496 497 int 498 bcm_hr2_dual_port_mode_reinit(int unit) { 499 uint32 *tx_pkt; 500 uint32 *buff; 501 int rv,i; 502 sal_usecs_t stime = sal_time_usecs(); 503 bcm_port_t test_ports[2]; 504 uint16 dev_id; 505 uint8 rev_id; 506 int hu2_config_id; 507 int check_required = 0; 508 int enable = 0; 509 uint32 pkt[17] = {0x66778899, 0xaabb0011, 0x22334455, 0x81000001, 510 0x002e0000, 0x56761234, 0x56771234, 0x56781234, 511 0x56791234, 0x567a1234, 0x567b1234, 0x567c1234, 512 0x567d1234, 0x567e1234, 0x567f1234, 0x56801234, 513 0x00000000}; 514 515 /* Qualify situation that should apply the WAR */ 516 /* get the port number for the checking */ 517 soc_cm_get_id(unit, &dev_id, &rev_id); 518 hu2_config_id = soc_property_get(unit, spn_BCM5615X_CONFIG, 0); 519 520 /* Test both the dual mode port */ 521 check_required = 0; 522 switch (dev_id) { 523 case BCM56150_DEVICE_ID: 524 case BCM56151_DEVICE_ID: 525 case BCM53346_DEVICE_ID: 526 case BCM53347_DEVICE_ID: 527 case BCM56152_DEVICE_ID: 528 case BCM53344_DEVICE_ID: 529 if ((hu2_config_id == 1) || (hu2_config_id == 10)) { 530 check_required = 1; 531 test_ports[0] = 28; 532 test_ports[1] = 29; 533 } else if (hu2_config_id == 11) { 534 check_required = 1; 535 test_ports[0] = 26; 536 test_ports[1] = 27; 537 538 } 539 break; 540 default : 541 break; 542 } 543 544 if (check_required) { 545 tx_pkt = soc_cm_salloc(unit, 256, "tx_pilot_pkt"); 546 if (tx_pkt == NULL) { 547 return BCM_E_MEMORY; 548 } 549 buff = tx_pkt; 550 for(i = 0; i < 17; i++) { 551 *buff = pkt[i]; 552 buff++; 553 } 554 soc_cm_sflush(unit, tx_pkt, 256); 555 for (i = 0; i < 2; i++) { 556 /* Apply to valid ports */ 557 if (BCM_PBMP_MEMBER(PBMP_PORT_ALL(unit), test_ports[i])) { 558 /* 559 * Check if port is enabled already 560 * Ports could be disabled in this state because of 561 * 'CFLAGS += -DBCM_PORT_DEFAULT_DISABLE' 562 * Check the state and enable port if necessary. 563 */ 564 rv = bcm_esw_port_enable_get(unit, \ 565 test_ports[i], &enable); 566 if (rv < 0) { 567 LOG_ERROR(BSL_LS_BCM_PORT, \ 568 (BSL_META_U(unit, \ 569 "Failed to get Port %d enable status\n"), test_ports[i])); 570 } 571 if (!enable) { 572 rv = bcm_esw_port_enable_set(unit, \ 573 test_ports[i], 1); 574 if (rv < 0) { 575 LOG_ERROR(BSL_LS_BCM_PORT, \ 576 (BSL_META_U(unit, \ 577 "Failed to set Port %d enable status\n"), test_ports[i])); 578 } 579 } 580 LOG_VERBOSE(BSL_LS_BCM_PORT, \ 581 (BSL_META_U(unit, \ 582 "Apply Dual Port Mode WAR to port(%d)\n"), test_ports[i])); 583 rv = _bcm_hr2_dual_port_mode_check(unit, test_ports[i], tx_pkt); 584 if (rv < 0) { 585 LOG_ERROR(BSL_LS_BCM_PORT, 586 (BSL_META_U(unit, 587 "Dual port mode WAR Failed on port %d\n"), test_ports[i])); 588 } 589 590 /* recover the port enable state */ 591 if (!enable) { 592 rv = bcm_esw_port_enable_set(unit, \ 593 test_ports[i], enable); 594 if (rv < 0) { 595 LOG_ERROR(BSL_LS_BCM_PORT, \ 596 (BSL_META_U(unit, \ 597 "Failed to recover Port %d enable status\n"), test_ports[i])); 598 } 599 } 600 } 601 } 602 soc_cm_sfree(unit, tx_pkt); 603 } 604 605 LOG_VERBOSE(BSL_LS_SOC_COMMON, 606 (BSL_META_U(unit, 607 "Dual port mode WAR: took %d usec\n"), 608 SAL_USECS_SUB(sal_time_usecs(), stime))); 609 610 /* Always return OK so that further init can go on */ 611 return BCM_E_NONE; 612 } 613 614 #endif