portctrl.c (354784B)
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 * File: portctrl.c 9 * Purpose: SDK Port Control Layer 10 * 11 * The purpose is to encapsulate port functionality 12 * related to the xxPORT block (i.e. XLPORT, CPORT) 13 * MAC and PHY. 14 * 15 * Currently, only the PortMod library is being supported. 16 * The PortMod library provides support for the MAC, PHY, 17 * and xxPORT registers. 18 * 19 * Callers of the Port Control routines should check 20 * before calling into them with the macro: 21 * SOC_USE_PORTCTRL() 22 */ 23 24 #include <shared/error.h> 25 #include <shared/bsl.h> 26 #include <sal/core/dpc.h> 27 #include <soc/types.h> 28 #include <soc/error.h> 29 #include <soc/macutil.h> 30 #include <soc/drv.h> 31 32 #include <bcm_int/esw_dispatch.h> 33 #include <bcm_int/esw/portctrl.h> 34 #include <bcm_int/esw/port.h> 35 #include <bcm_int/esw/link.h> 36 #include <bcm_int/esw/xgs5.h> 37 38 #ifdef BCM_XGS3_SWITCH_SUPPORT 39 #include <bcm_int/esw/mirror.h> 40 #endif 41 42 #include <bcm/error.h> 43 #include <soc/firebolt.h> 44 #include <bcm_int/esw/triumph.h> 45 #include <bcm_int/esw/mbcm.h> 46 47 #if defined(BCM_TRIDENT2_SUPPORT) 48 #include <bcm_int/esw/trident2.h> 49 #include <soc/trident2.h> 50 #include <bcm_int/esw/trunk.h> 51 #endif /* BCM_TRIDENT2_SUPPORT */ 52 53 #if defined(BCM_TOMAHAWK3_SUPPORT) 54 #include <bcm_int/esw/pfc.h> 55 #include <bcm_int/esw/tomahawk3.h> 56 #endif /* BCM_TOMAHAWK3_SUPPOT */ 57 58 #if defined(BCM_MONTEREY_SUPPORT) 59 #include <soc/monterey.h> 60 #include <bcm_int/esw/monterey.h> 61 #endif 62 #ifdef SW_AUTONEG_SUPPORT 63 #include <bcm_int/common/sw_an.h> 64 #endif 65 66 #ifdef BCM_HELIX5_SUPPORT 67 #include <soc/helix5.h> 68 #endif 69 70 #ifdef PORTMOD_SUPPORT 71 #include <soc/portmod/portmod.h> 72 #include <soc/portmod/portmod_common.h> 73 #include <soc/portmod/portmod_legacy_phy.h> 74 #include <soc/esw/portctrl_internal.h> 75 76 extern uint32_t phymod_dbg_mask; 77 extern uint32_t phymod_dbg_addr; 78 extern uint32_t phymod_dbg_lane; 79 80 /* 81 * Define: 82 * PORTCTRL_PORT_RESOLVE 83 * Purpose: 84 * Converts a GPORT or non-GPORT format port into: 85 * - BCM local port '_lport' 86 * - Port type used in PortMod functions '_pport' 87 */ 88 #define PORTCTRL_PORT_RESOLVE(_unit, _port, _lport, _pport) \ 89 _bcm_esw_portctrl_port_resolve((_unit), (_port), (_lport), (_pport)) 90 91 /* 92 * Define: 93 * PORTCTRL_INIT_CHECK 94 * Purpose: 95 * Checks that Port Control module has been initialized for given 96 * unit. If failure, it causes routine to return with BCM_E_INIT. 97 */ 98 #define PORTCTRL_INIT_CHECK(_unit) \ 99 SOC_IF_ERROR_RETURN(soc_esw_portctrl_init_check(_unit)) 100 101 102 #define _ERR_MSG_MODULE_NAME BSL_BCM_OTHER 103 104 105 #define BCM_ESW_PORTCTRL_PHY_REG_INDIRECT _SHR_PORT_PHY_REG_INDIRECT 106 #define BCM_ESW_PORTCTRL_PHYCTRL_PRBS_RX_ENABLE _SHR_PORT_PHY_CONTROL_PRBS_RX_ENABLE 107 108 STATIC int 109 _bcm_esw_portctrl_speed_chip_reconfigure(int unit, bcm_port_t port, int speed); 110 extern int bcmi_esw_port_eee_cfg_set(int unit, bcm_port_t port, int value); 111 112 /* 113 * 8 Priority Groups supported. 114 */ 115 #define PORTCTRL_PRIOROTY_GROUP_ID_MIN 0 116 #define PORTCTRL_PRIOROTY_GROUP_ID_MAX 7 117 118 #define PORTCTRL_AUTONEG_ABILITY_MAX_COUNT 20 119 #define PORTCTRL_SPEED_ABILITY_MAX_COUNT 50 120 #endif /* PORTMOD_SUPPORT */ 121 122 /* 123 * Macros for use with encapsulation set related functions 124 */ 125 #define BCM_ESW_PORTCTRL_CFG_ENCAP_MODE 1 126 #define BCM_ESW_PORTCTRL_CFG_INTERFACE 2 127 #define BCM_ESW_PORTCTRL_CFG_SPEED 3 128 129 #define BCM_PA_ENCAP(e) \ 130 ((e == BCM_PORT_ENCAP_IEEE) ? BCM_PA_ENCAP_IEEE : \ 131 (e == BCM_PORT_ENCAP_HIGIG) ? BCM_PA_ENCAP_HIGIG : \ 132 (e == BCM_PORT_ENCAP_B5632) ? BCM_PA_ENCAP_B5632 : \ 133 (e == BCM_PORT_ENCAP_HIGIG2) ? BCM_PA_ENCAP_HIGIG2 : \ 134 (e == BCM_PORT_ENCAP_HIGIG2_LITE) ? BCM_PA_ENCAP_HIGIG2_LITE : \ 135 (e == BCM_PORT_ENCAP_HIGIG2_L2) ? BCM_PA_ENCAP_HIGIG2_L2 : \ 136 (e == BCM_PORT_ENCAP_HIGIG2_IP_GRE) ? BCM_PA_ENCAP_HIGIG2_IP_GRE : \ 137 (e == BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET) ? BCM_PA_ENCAP_HIGIG_OVER_ETHERNET : \ 138 (e == BCM_PORT_ENCAP_CPRI) ? BCM_PA_ENCAP_CPRI : \ 139 (e == BCM_PORT_ENCAP_RSVD4) ? BCM_PA_ENCAP_RSVD4 : 0) 140 141 #ifdef PORTMOD_SUPPORT 142 143 /* 144 * Function: 145 * _bcm_esw_portctrl_port_resolve 146 * Purpose: 147 * Converts the given BCM port type, bcm_gport_t, to 148 * the BCM local port type and the port type expected by 149 * the PortMod functions. 150 * Parameters: 151 * unit - (IN) Unit number. 152 * port - (IN) BCM Port number, this can be in GPORT format. 153 * lport - (OUT) Returns BCM logical local port number. 154 * pport - (OUT) Returns port in expected PortMod port type. 155 * Returns: 156 * BCM_E_xxx 157 */ 158 STATIC int 159 _bcm_esw_portctrl_port_resolve(int unit, bcm_gport_t port, 160 bcm_port_t *lport, portctrl_pport_t *pport) 161 { 162 /* 163 * Currently, the PortMod library expects a logical local 164 * port number, which is equivalent to the BCM port local port. 165 */ 166 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, lport)); 167 168 *pport = *lport; 169 return BCM_E_NONE; 170 } 171 172 173 /* 174 * Function: 175 * _bcm_esw_portctrl_from_portmod_ability 176 * Purpose: 177 * Converts the _port_ability_t structure from PortMod to 178 * BCM _port_ability_t 179 * Parameters: 180 * portmod_ability - (IN) PortMod _ability_ structure to convert. 181 * port_ability - (OUT) Returns information in BCM bcm_port_ability_t. 182 * Returns: 183 * None 184 */ 185 STATIC void 186 _bcm_esw_portctrl_from_portmod_ability(portmod_port_ability_t *portmod_ability, 187 bcm_port_ability_t *port_ability) 188 { 189 /* 190 * Currently, the portmod_port_ability_t definition uses 191 * _shr_port_ability_t, which is used by the 192 * SOC soc_port_ability_t and BCM bcm_port_ability_t. 193 */ 194 *port_ability = *portmod_ability; 195 196 return; 197 } 198 199 /* 200 * Function: 201 * _bcm_esw_portctrl_from_portmod_autoneg_ability 202 * Purpose: 203 * Converts the portmod_port_speed_ability_t structure array 204 * to bcm_port_speed_ability_t structure array. 205 * Parameters: 206 * unit - (IN) device unit number 207 * num_ability - (IN) Number of abilities in the array. 208 * portmod_abilities - (IN) portmod_port_speed_ability_t array. 209 * max_num_abilities - (IN) maximum abilities the user array can take 210 * port_abilities - (OUT) bcm_port_speed_ability_t array. 211 * valid_abilities - (OUT) abilities supported by the device 212 * 213 * Returns: 214 * None. 215 */ 216 STATIC int 217 _bcm_esw_portctrl_from_portmod_autoneg_ability(int unit, 218 int num_ability, 219 portmod_port_speed_ability_t *portmod_abilities, 220 int max_num_abilities, 221 bcm_port_speed_ability_t *port_abilities, 222 int *valid_abilities) 223 { 224 int i, rv = BCM_E_NONE; 225 int valid = 0; 226 227 for (i = 0; i < num_ability; i++) { 228 if (BCM_ESW_PORT_DRV(unit)!= NULL) { 229 if (BCM_ESW_PORT_DRV(unit)->device_speed_check != NULL) { 230 231 /* We don't want to add speeds that may be supported by the 232 * port macro, but not the device */ 233 rv = (BCM_ESW_PORT_DRV(unit)->device_speed_check(unit, 234 portmod_abilities[i].speed, 235 portmod_abilities[i].num_lanes)); 236 if (BCM_FAILURE(rv)) { 237 continue; 238 } 239 } 240 } 241 242 /* Do not write beyond the max size of the buffer */ 243 if (valid >= max_num_abilities) { 244 rv = BCM_E_PARAM; 245 } else { 246 port_abilities[valid].speed = portmod_abilities[i].speed; 247 port_abilities[valid].resolved_num_lanes = portmod_abilities[i].num_lanes; 248 port_abilities[valid].fec_type = portmod_abilities[i].fec_type; 249 port_abilities[valid].medium = portmod_abilities[i].medium; 250 port_abilities[valid].pause = portmod_abilities[i].pause; 251 port_abilities[valid].channel = portmod_abilities[i].channel; 252 /* coverity[mixed_enums:FALSE] */ 253 port_abilities[valid].an_mode = portmod_abilities[i].an_mode; 254 } 255 256 /* Increase valid just so we know how many the device can support, 257 * not just how many the PM supports */ 258 valid++; 259 } 260 261 if (BCM_FAILURE(rv)) { 262 LOG_ERROR(BSL_LS_BCM_PORT, 263 (BSL_META_U(unit, 264 "ERROR: Buffer for abilities (%d) not " 265 "large enough for size (%d). )\n"), 266 max_num_abilities, valid)); 267 *valid_abilities = -1; 268 } else { 269 /* Set the number of valid abilities for the device */ 270 *valid_abilities = valid; 271 } 272 273 return rv; 274 } 275 276 /* 277 * Function: 278 * _bcm_esw_portmod_from_portctrl_autoneg_ability 279 * Purpose: 280 * Converts the bcm_port_speed_ability_t structure array 281 * to portmod_port_speed_ability_t sturcture array 282 * Parameters: 283 * num_ability - (IN) Number of abilities in the array. 284 * port_abilities - (IN) bcm_port_speed_ability_t array. 285 * portmod_abilities - (OUT) portmod_port_speed_ability_t array. 286 * Returns: 287 * None. 288 */ 289 STATIC void 290 _bcm_esw_portmod_from_portctrl_autoneg_ability(int num_ability, 291 bcm_port_speed_ability_t *port_abilities, 292 portmod_port_speed_ability_t *portmod_abilities) 293 { 294 int i; 295 296 for (i = 0; i < num_ability; i++) { 297 portmod_abilities[i].speed = port_abilities[i].speed; 298 portmod_abilities[i].num_lanes = port_abilities[i].resolved_num_lanes; 299 portmod_abilities[i].fec_type = port_abilities[i].fec_type; 300 portmod_abilities[i].medium = port_abilities[i].medium; 301 portmod_abilities[i].pause = port_abilities[i].pause; 302 portmod_abilities[i].channel = port_abilities[i].channel; 303 /* coverity[mixed_enums:FALSE] */ 304 portmod_abilities[i].an_mode = port_abilities[i].an_mode; 305 } 306 } 307 308 /* 309 * Function: 310 * _bcm_esw_portctrl_port_fifo_reset 311 * Purpose: 312 * Toggle the port soft reset. 313 * Parameters: 314 * unit - (IN) Unit number. 315 * port - (IN) Logical BCM Port number (non-GPORT). 316 * pport - (IN) Port type expected by PortMod. 317 * Returns: 318 * BCM_E_XXX 319 * Notes: 320 * Must be called with PORT_LOCK held. 321 */ 322 STATIC int 323 _bcm_esw_portctrl_port_fifo_reset(int unit, bcm_port_t port, 324 portctrl_pport_t pport) 325 { 326 int phy_port, block, bindex, i; 327 328 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 329 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 330 block = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 331 if ((SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORT) || 332 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORTB0) || 333 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLG2PORT) || 334 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_GXPORT) || 335 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLPORT)) { 336 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 337 PORTMOD_IF_ERROR_RETURN 338 (portmod_port_soft_reset_toggle(unit, pport, bindex)); 339 break; 340 } 341 } 342 343 return BCM_E_NONE; 344 } 345 346 347 /* 348 * Function: 349 * _bcm_esw_portctrl_port_soft_reset 350 * Purpose: 351 * Release or hold OBM, cell assembly and port logic from/in reset. 352 * Parameters: 353 * unit - (IN) Unit number. 354 * port - (IN) Logical BCM Port number (non-GPORT). 355 * pport - (IN) Port type expected by PortMod. 356 * reset - (IN) O: Release from reset. 357 * 1: Hold port in reset. 358 * Returns: 359 * BCM_E_XXX 360 * Notes: 361 * Must be called with PORT_LOCK held. 362 */ 363 STATIC int 364 _bcm_esw_portctrl_port_soft_reset(int unit, bcm_port_t port, 365 portctrl_pport_t pport, 366 int reset) 367 { 368 int phy_port; 369 int block; 370 int bindex; 371 int i; 372 int flags = PORTMOD_PORT_REG_ACCESS_DEFAULT; 373 374 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 375 376 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 377 block = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 378 379 if ((SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORT) || 380 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_XLPORTB0) || 381 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLG2PORT) || 382 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_GXPORT) || 383 (SOC_BLOCK_INFO(unit, block).type == SOC_BLK_CLPORT)) { 384 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 385 PORTMOD_IF_ERROR_RETURN 386 (portmod_port_soft_reset_set(unit, pport, bindex, reset, flags)); 387 break; 388 } 389 } 390 391 return BCM_E_NONE; 392 } 393 394 395 /* 396 * Function: 397 * _bcm_esw_portctrl_tx_fifo_empty 398 * Purpose: 399 * Poll until the MAC TX FIFO is empty, or until 400 * it times out. 401 * Parameters: 402 * unit - (IN) Unit number. 403 * port - (IN) Logical BCM Port number (non-GPORT). 404 * pport - (IN) Port type expected by PortMod. 405 * Returns: 406 * BCM_E_XXX 407 * Notes: 408 * Must be called with PORT_LOCK held. 409 */ 410 411 STATIC int 412 _bcm_esw_portctrl_tx_fifo_empty(int unit, bcm_port_t port, 413 portctrl_pport_t pport) 414 { 415 uint32 cell_count; 416 soc_timeout_t to; 417 int wait_time = 250000; 418 419 if (SAL_BOOT_QUICKTURN) { 420 wait_time *= 20; 421 } 422 423 /* Wait until MAC TX fifo cell count is 0 */ 424 soc_timeout_init(&to, wait_time, 0); 425 for (;;) { 426 PORTMOD_IF_ERROR_RETURN 427 (portmod_port_txfifo_cell_cnt_get(unit, pport, &cell_count)); 428 429 if (cell_count == 0) { 430 break; 431 } 432 if (soc_timeout_check(&to)) { 433 LOG_ERROR(BSL_LS_BCM_PORT, 434 (BSL_META_UP(unit, port, 435 "ERROR: u=%d p=%d timeout draining " 436 "MAC TX FIFO (%d cells remain)\n"), 437 unit, port, cell_count)); 438 return BCM_E_INTERNAL; 439 } 440 } 441 442 return BCM_E_NONE; 443 } 444 445 446 /* 447 * Function: 448 * _bcm_esw_portctrl_drain_cells 449 * Purpose: 450 * Drain cells for given port. 451 * Parameters: 452 * unit - (IN) Unit number. 453 * port - (IN) Logical BCM Port number (non-GPORT). 454 * pport - (IN) Port type expected by PortMod. 455 * Returns: 456 * BCM_E_XXX 457 * Notes: 458 * Must be called with PORT_LOCK held. 459 */ 460 STATIC int 461 _bcm_esw_portctrl_drain_cells(int unit, bcm_port_t port, 462 portctrl_pport_t pport) 463 { 464 portmod_drain_cells_t drain_cells; 465 uint32 cell_count; 466 soc_timeout_t to; 467 int rv = BCM_E_NONE; 468 int wait_time = 250000; 469 int qmode = 0; 470 471 if (SAL_BOOT_QUICKTURN) { 472 wait_time *= 20; 473 } 474 475 PORTMOD_IF_ERROR_RETURN 476 (portmod_port_drain_cell_get(unit, pport, &drain_cells)); 477 478 /* Start TX FIFO draining */ 479 PORTMOD_IF_ERROR_RETURN 480 (portmod_port_drain_cell_start(unit, pport)); 481 482 #ifdef BCM_HELIX5_SUPPORT 483 if (SOC_IS_HELIX5(unit)) { 484 soc_helix5_port_qsgmii_mode_get(unit, pport, &qmode); 485 } 486 #endif 487 /* Can't reset EP credit if mac is unimac, or else credit would be mismatched */ 488 if (!qmode) { 489 /* Reset EP credit before de-assert SOFT_RESET */ 490 SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port)); 491 } 492 493 /* De-assert SOFT_RESET to let the drain start */ 494 PORTMOD_IF_ERROR_RETURN 495 (portmod_port_mac_reset_set(unit, pport, 0)); 496 497 /* Wait until mmu cell count is 0 */ 498 rv = soc_egress_drain_cells(unit, port, wait_time); 499 if (BCM_E_NONE == rv) { 500 /* Wait until TX fifo cell count is 0 */ 501 soc_timeout_init(&to, wait_time, 0); 502 for (;;) { 503 rv = portmod_port_txfifo_cell_cnt_get(unit, pport, &cell_count); 504 if (BCM_E_NONE != rv) { 505 break; 506 } 507 if (cell_count == 0) { 508 break; 509 } 510 if (soc_timeout_check(&to)) { 511 LOG_ERROR(BSL_LS_BCM_PORT, 512 (BSL_META_UP(unit, port, 513 "ERROR: u=%d p=%d timeout draining " 514 "TX FIFO (%d cells remain)\n"), 515 unit, port, cell_count)); 516 rv = BCM_E_INTERNAL; 517 break; 518 } 519 } 520 } 521 522 /* Stop TX FIFO draining */ 523 PORTMOD_IF_ERROR_RETURN 524 (portmod_port_drain_cell_stop(unit, pport, &drain_cells)); 525 526 return rv; 527 } 528 529 530 /* 531 * Function: 532 * _bcm_esw_portctrl_mmu_flush 533 * Purpose: 534 * Flush port in MMU. 535 * Parameters: 536 * unit - (IN) Unit number. 537 * port - (IN) Logical BCM Port number (non-GPORT). 538 * pport - (IN) Port type expected by PortMod. 539 * Returns: 540 * BCM_E_XXX 541 * Notes: 542 * Must be called with PORT_LOCK hed. 543 */ 544 545 STATIC int 546 _bcm_esw_portctrl_mmu_flush(int unit, bcm_port_t port, 547 portctrl_pport_t pport) 548 { 549 portmod_pfc_control_t pfc, prev_pfc; 550 portmod_llfc_control_t llfc, prev_llfc; 551 portmod_pause_control_t pause, prev_pause; 552 int rv = BCM_E_NONE; 553 int wait_time = 250000; 554 555 if (SAL_BOOT_QUICKTURN) { 556 wait_time *= 20; 557 } 558 559 560 /* Disable flow control (store current settings) */ 561 PORTMOD_IF_ERROR_RETURN 562 (portmod_port_pause_control_get(unit, pport, &pause)); 563 prev_pause = pause; 564 pause.rx_enable = 0; 565 PORTMOD_IF_ERROR_RETURN 566 (portmod_port_pause_control_set(unit, pport, &pause)); 567 568 PORTMOD_IF_ERROR_RETURN 569 (portmod_port_pfc_control_get(unit, pport, &pfc)); 570 prev_pfc = pfc; 571 pfc.rx_enable = 0; 572 PORTMOD_IF_ERROR_RETURN 573 (portmod_port_pfc_control_set(unit, pport, &pfc)); 574 575 PORTMOD_IF_ERROR_RETURN 576 (portmod_port_llfc_control_get(unit, pport, &llfc)); 577 prev_llfc = llfc; 578 llfc.rx_enable = 0; 579 PORTMOD_IF_ERROR_RETURN 580 (portmod_port_llfc_control_set(unit, pport, &llfc)); 581 582 /* Wait until mmu cell count is 0 */ 583 rv = soc_egress_drain_cells(unit, port, 250000); 584 585 /* Restore flow control settings */ 586 PORTMOD_IF_ERROR_RETURN 587 (portmod_port_pause_control_set(unit, pport, &prev_pause)); 588 PORTMOD_IF_ERROR_RETURN 589 (portmod_port_pfc_control_set(unit, pport, &prev_pfc)); 590 PORTMOD_IF_ERROR_RETURN 591 (portmod_port_llfc_control_set(unit, pport, &prev_llfc)); 592 593 /* 594 * Delay 1 usec to ensure all cells drained from MMU 595 * during the flush have left EP. 596 */ 597 sal_udelay(1); 598 599 return rv; 600 } 601 602 603 /* 604 * Function: 605 * _bcm_esw_portctrl_enable_set 606 * Purpose: 607 * Core function to enable or disable a port. 608 * This includes all the necessary steps to correctly bring 609 * up or down a port. 610 * 611 * The sequence to bring a port UP or DOWN requires a series of 612 * interleaved steps that falls inside and outside the PortMod library. 613 * Some operations need to occur in the xxPORT, or MAC, or PHY blocks, 614 * whereas others need to occur at the EP, or MMU blocks. 615 * 616 * There are two approaches: 617 * 1) SDK drives the logic calling the corresponding PortMod and 618 * non-PortMod routines. 619 * 2) PortMod drive the logic calling callback routines provided 620 * by SDK to perform operations outside the PortMod. 621 * 622 * At the moment (1) is implemented. 623 * Parameters: 624 * unit - (IN) Unit number. 625 * port - (IN) Logical BCM Port number (non-GPORT). 626 * pport - (IN) Port type expected by PortMod. 627 * flags - (IN) Indicates whether to enable PHY, MAC, or both. 628 * enable - (IN) Indicates whether to enable or disable port. 629 * Returns: 630 * BCM_E_XXX 631 * Notes: 632 * Must be called with PORT_LOCK held. 633 * This follows the new sequence provided by the design team. 634 * 635 * Currently, the PortMod API portmod_port_enable_set() do enable/disable 636 * the MAC does not have the complete bringup sequence. Callers 637 * should be calling this routine instead to bring the port up or down 638 * properly. 639 */ 640 STATIC int 641 _bcm_esw_portctrl_enable_set(int unit, bcm_port_t port, 642 portctrl_pport_t pport, 643 int flags, int enable) 644 { 645 pbmp_t mask; 646 int flags_temp; 647 int mac_reset; 648 int wait_us, mngport; 649 #if defined(BCM_MONTEREY_SUPPORT) 650 uint32 preemption_enable = 0 ; 651 #endif 652 if (enable) { 653 /* 654 * PORT UP 655 */ 656 657 /* Enable PHY if PHY flag is set */ 658 if (PORTMOD_PORT_ENABLE_PHY_GET(flags)) { 659 flags_temp = flags; 660 PORTMOD_PORT_ENABLE_MAC_CLR(flags_temp); 661 PORTMOD_IF_ERROR_RETURN 662 (portmod_port_enable_set(unit, pport, flags_temp, 1)); 663 } 664 665 /* 666 * Check if MAC needs to be modified based on whether 667 * we want to enable or disable the MAC. 668 * If not changes are needed, assume port is 669 * already UP and just skip enabling MAC. 670 */ 671 PORTMOD_IF_ERROR_RETURN 672 (portmod_port_mac_reset_check(unit, pport, 673 enable, &mac_reset)); 674 /* 675 * If MAC flag is set and MAC is not UP yet, continue with rest of 676 * sequence to bring the port UP, including resetting credits, 677 * cells draining, etc. 678 */ 679 if (mac_reset && PORTMOD_PORT_ENABLE_MAC_GET(flags)) { 680 681 if (soc_feature(unit, soc_feature_port_leverage)) { 682 if (BCM_ESW_PORT_DRV(unit)!= NULL) { 683 if (BCM_ESW_PORT_DRV(unit)->port_enable_set != NULL) { 684 BCM_IF_ERROR_RETURN 685 (BCM_ESW_PORT_DRV(unit)->port_enable_set(unit, 686 port, 687 1)); 688 } 689 } 690 } else { 691 /* 692 * Initialize EP credits, 693 * release EDB port buffer reset and enable cell request 694 * generation in EP. 695 */ 696 SOC_IF_ERROR_RETURN 697 (soc_port_egress_buffer_sft_reset(unit, port, 0)); 698 699 /* Release OBM, cell assembly and port logic from reset */ 700 BCM_IF_ERROR_RETURN 701 (_bcm_esw_portctrl_port_soft_reset(unit, port, pport, 0)); 702 703 /* Release Ingress buffers from reset */ 704 SOC_IF_ERROR_RETURN 705 (soc_port_ingress_buffer_reset(unit, port, 0)); 706 707 /* Enable MAC TX and RX and take MAC out of reset */ 708 PORTMOD_IF_ERROR_RETURN 709 (portmod_port_drain_cells_rx_enable(unit, pport, 1)); 710 711 } 712 } 713 /* Add port to EPC_LINK and ING_DEST_PORT_ENABLE */ 714 soc_link_mask2_get(unit, &mask); 715 SOC_PBMP_PORT_ADD(mask, port); 716 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 717 718 #if defined(BCM_MONTEREY_SUPPORT) 719 if (SOC_IS_MONTEREY(unit) && PORTMOD_PORT_ENABLE_MAC_GET(flags)) { 720 SOC_IF_ERROR_RETURN( 721 bcmi_mn_preemption_capability_get(unit , port , &preemption_enable)); 722 if (preemption_enable) { 723 portmod_port_discard_set( unit, port, 1); 724 bcm_monterey_send_packetport(unit , port , 0 , 250); 725 portmod_port_discard_set( unit, port, 0); 726 } 727 } 728 #endif 729 } else { 730 /* 731 * PORT DOWN 732 */ 733 734 /* 735 * Remove from EPC_LINK and ING_DEST_PORT_ENABLE to prevent packets 736 * queued to this port from TX 737 */ 738 soc_link_mask2_get(unit, &mask); 739 SOC_PBMP_PORT_REMOVE(mask, port); 740 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 741 742 /* Wait 8ms if management port configured to 10/100, else 80 us. 743 * please refer TH2/TD2p_uA_flexport.pdf, Section 6.6.1 */ 744 wait_us = 80; 745 SOC_PBMP_ITER(PBMP_MANAGEMENT(unit), mngport) { 746 if (SOC_INFO(unit).port_init_speed[mngport] <= 100) { 747 wait_us = 8000; 748 break; 749 } 750 } 751 if (SAL_BOOT_QUICKTURN) { 752 wait_us *= 10000; 753 } 754 sal_usleep(wait_us); 755 756 /* 757 * Due to a HW issue, the MAC RX needs to be disabled 758 * before disabling PHY (SW workaround) 759 */ 760 761 /* 762 * If only PHY flag is set, just disable PHY. 763 * Otherwise, PHY is disabled later along with the MAC 764 * following the right order. 765 */ 766 if (PORTMOD_PORT_ENABLE_PHY_GET(flags) && 767 !PORTMOD_PORT_ENABLE_MAC_GET(flags)) { 768 PORTMOD_IF_ERROR_RETURN 769 (portmod_port_enable_set(unit, pport, flags, 0)); 770 } 771 772 /* 773 * If MAC flag is set, continue with rest of sequence 774 * to bring the port DOWN. 775 */ 776 if (PORTMOD_PORT_ENABLE_MAC_GET(flags)) { 777 778 /* 779 * Disable MAC RX and PHY (if flag is supplied). 780 * 781 * NOTE: MAC RX needs to be disabled before the TSC. 782 */ 783 PORTMOD_IF_ERROR_RETURN 784 (portmod_port_rx_mac_enable_set(unit, pport, 0)); 785 if (PORTMOD_PORT_ENABLE_PHY_GET(flags)) { 786 PORTMOD_IF_ERROR_RETURN 787 (portmod_port_enable_set(unit, pport, 788 PORTMOD_PORT_ENABLE_PHY, 0)); 789 } 790 791 /* 792 * Check if MAC needs to be modified based on whether 793 * we want to enable or disable the MAC. 794 * If not changes are needed, assume port is 795 * already DOWN and just return. 796 */ 797 PORTMOD_IF_ERROR_RETURN 798 (portmod_port_mac_reset_check(unit, pport, 799 enable, &mac_reset)); 800 if (!mac_reset) { 801 return BCM_E_NONE; 802 } 803 804 if (soc_feature(unit, soc_feature_port_leverage)) { 805 if (BCM_ESW_PORT_DRV(unit)!= NULL) { 806 if (BCM_ESW_PORT_DRV(unit)->port_enable_set != NULL) { 807 BCM_IF_ERROR_RETURN 808 (BCM_ESW_PORT_DRV(unit)->port_enable_set(unit, 809 port, 810 0)); 811 } 812 } 813 } else { 814 /* Hold MAC in reset state */ 815 BCM_IF_ERROR_RETURN 816 (portmod_port_mac_reset_set(unit, pport, 1)); 817 818 819 /* Put port in flush state using MAC discard */ 820 PORTMOD_IF_ERROR_RETURN 821 (portmod_port_discard_set(unit, pport, 1)); 822 823 /* Remove MAC reset */ 824 BCM_IF_ERROR_RETURN 825 (portmod_port_mac_reset_set(unit, pport, 0)); 826 827 /* Reset Ingress buffers */ 828 SOC_IF_ERROR_RETURN 829 (soc_port_ingress_buffer_reset(unit, port, 1)); 830 831 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 832 if (SOC_IS_TRIDENT2PLUS(unit)) { 833 /* Hold OBM in reset will clear OBM counters. 834 * Clear in counter thread accordingly. 835 */ 836 SOC_IF_ERROR_RETURN 837 (soc_td2_obm_counters_reset(unit, port)); 838 } 839 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 840 /* Hold OBM, cell assembly and port logic in reset */ 841 BCM_IF_ERROR_RETURN 842 (_bcm_esw_portctrl_port_soft_reset(unit, port, pport, 1)); 843 844 /* MMU flush */ 845 BCM_IF_ERROR_RETURN 846 (_bcm_esw_portctrl_mmu_flush(unit, port, pport)); 847 848 /* Reset Egress buffers */ 849 SOC_IF_ERROR_RETURN 850 (soc_port_egress_buffer_sft_reset(unit, port, 1)); 851 852 /* Poll until MAC TX FIFO is empty */ 853 BCM_IF_ERROR_RETURN 854 (_bcm_esw_portctrl_tx_fifo_empty(unit, port, pport)); 855 856 /* Disable MAC TX and power down TSC */ 857 PORTMOD_IF_ERROR_RETURN 858 (portmod_port_tx_down(unit, pport)); 859 } 860 } /* MAC flag is set */ 861 862 } /* PORT DOWN */ 863 864 return BCM_E_NONE; 865 } 866 867 868 /* 869 * Function: 870 * _bcm_esw_portctrl_egress_queue_drain 871 * Purpose: 872 * Drain the egress queues without bringing down the port. 873 * Parameters: 874 * unit - (IN) Unit number. 875 * port - (IN) Logical BCM Port number (non-GPORT). 876 * pport - (IN) Port type expected by PortMod. 877 * Returns: 878 * BCM_E_XXX 879 * Notes: 880 * Must be called with PORT_LOCK held. 881 * Helper to bcm_esw_portctrl_egress_queue_drain. 882 */ 883 STATIC int 884 _bcm_esw_portctrl_egress_queue_drain(int unit, bcm_port_t port, 885 portctrl_pport_t pport) 886 { 887 uint64 mac_ctrl; 888 int rx_enable = 0; 889 pbmp_t mask; 890 int is_active = 0; 891 int qmode = 0; 892 893 PORTMOD_IF_ERROR_RETURN 894 (portmod_port_egress_queue_drain_get(unit, pport, 895 &mac_ctrl, &rx_enable)); 896 897 /* Remove port from EPC_LINK */ 898 soc_link_mask2_get(unit, &mask); 899 if (SOC_PBMP_MEMBER(mask, port)) { 900 is_active = 1; 901 SOC_PBMP_PORT_REMOVE(mask, port); 902 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 903 } 904 905 /* Drain cells */ 906 BCM_IF_ERROR_RETURN 907 (_bcm_esw_portctrl_drain_cells(unit, port, pport)); 908 909 /* Reset port FIFO */ 910 BCM_IF_ERROR_RETURN 911 (_bcm_esw_portctrl_port_fifo_reset(unit, port, pport)); 912 913 /* Put port into SOFT_RESET */ 914 PORTMOD_IF_ERROR_RETURN 915 (portmod_port_mac_reset_set(unit, pport, 1)); 916 917 #ifdef BCM_HELIX5_SUPPORT 918 if (SOC_IS_HELIX5(unit)) { 919 soc_helix5_port_qsgmii_mode_get(unit, pport, &qmode); 920 } 921 #endif 922 /* Can't reset EP credit if mac is unimac, or else credit would be mismatched */ 923 if (!qmode) { 924 /* Reset EP credit before de-assert SOFT_RESET */ 925 SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port)); 926 } 927 928 /* Enable TX, set RX, de-assert SOFT_RESET */ 929 PORTMOD_IF_ERROR_RETURN 930 (portmod_port_egress_queue_drain_rx_en(unit, pport, rx_enable)); 931 932 /* Restore XLMAC_CTRL to original value */ 933 PORTMOD_IF_ERROR_RETURN 934 (portmod_port_mac_ctrl_set(unit, pport, mac_ctrl)); 935 936 /* Add port to EPC_LINK */ 937 if(is_active) { 938 soc_link_mask2_get(unit, &mask); 939 SOC_PBMP_PORT_ADD(mask, port); 940 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 941 } 942 943 return BCM_E_NONE; 944 } 945 946 /* 947 * Function: 948 * _bcm_esw_portctrl_interface_config_set 949 * Purpose: 950 * Core function to set the port interface configuration. 951 * Parameters: 952 * unit - (IN) Unit number. 953 * port - (IN) Logical BCM Port number (non-GPORT). 954 * pport - (IN) Port type expected by PortMod. 955 * if_cfg - (IN) Port Configuration to set. 956 * Returns: 957 * BCM_E_XXX 958 * Notes: 959 * Must be called with PORT_LOCK held. 960 * 961 * SDK drivers should NOT call portmod_port_interface_config_set() 962 * directly, expect for this routine. Drivers should call 963 * this routine instead to set the port interface configuration. 964 * 965 * In order to change a port inteface configuration, the port must 966 * be properly be disabled and then re-enabled back. Since the 967 * port bringup sequence is currenlty in the SDK and not in the PortMod 968 * library, the complete function to modify the port configuration will 969 * resides in the SDK driver. 970 */ 971 STATIC int 972 _bcm_esw_portctrl_interface_config_set(int unit, bcm_port_t port, 973 portctrl_pport_t pport, 974 portmod_port_interface_config_t *if_cfg, 975 uint32 all_phy) 976 { 977 int enable, phy_init_flag = PORTMOD_INIT_F_EXTERNAL_MOST_ONLY; 978 979 PORTCTRL_INIT_CHECK(unit); 980 981 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 982 983 PORTMOD_IF_ERROR_RETURN 984 (portmod_port_enable_get(unit, port, PORTMOD_PORT_ENABLE_MAC, &enable)); 985 986 if (enable) { 987 /* Disable port */ 988 BCM_IF_ERROR_RETURN 989 (_bcm_esw_portctrl_enable_set(unit, port, pport, 990 PORTMOD_PORT_ENABLE_MAC, 0)); 991 } 992 993 if (if_cfg->encap_mode & BCM_PORT_ENCAP_CPRI) { 994 if_cfg->interface_modes |= PHYMOD_INTF_MODES_HIGIG; 995 } else if (if_cfg->encap_mode & BCM_PORT_ENCAP_HIGIG2) { 996 if_cfg->interface_modes |= PHYMOD_INTF_MODES_HIGIG; 997 } else { 998 if_cfg->interface_modes &= ~PHYMOD_INTF_MODES_HIGIG; 999 } 1000 1001 if (all_phy){ 1002 phy_init_flag = PORTMOD_INIT_F_ALL_PHYS; 1003 } 1004 1005 PORTMOD_IF_ERROR_RETURN 1006 (portmod_port_interface_config_set(unit, pport, if_cfg, phy_init_flag)); 1007 1008 if (enable) { 1009 /* Re-enable port */ 1010 BCM_IF_ERROR_RETURN 1011 (_bcm_esw_portctrl_enable_set(unit, port, pport, 1012 PORTMOD_PORT_ENABLE_MAC, 1)); 1013 } 1014 1015 return BCM_E_NONE; 1016 } 1017 1018 /* 1019 * Function: 1020 * _bcm_esw_portctrl_speed_config_set 1021 * Purpose: 1022 * Core function to set the port speed configuration. 1023 * Parameters: 1024 * unit - (IN) Unit number. 1025 * port - (IN) Logical BCM Port number (non-GPORT). 1026 * pport - (IN) Port type expected by PortMod. 1027 * sp_cfg - (IN) Port Configuration to set. 1028 * Returns: 1029 * BCM_E_XXX 1030 * Notes: 1031 * Must be called with PORT_LOCK held. 1032 * 1033 * SDK drivers should NOT call portmod_port_speed_config_set() 1034 * directly, expect for this routine. Drivers should call 1035 * this routine instead to set the port interface configuration. 1036 * 1037 * In order to change a port inteface configuration, the port must 1038 * be properly be disabled and then re-enabled back. Since the 1039 * port bringup sequence is currenlty in the SDK and not in the PortMod 1040 * library, the complete function to modify the port configuration will 1041 * resides in the SDK driver. 1042 */ 1043 STATIC int 1044 _bcm_esw_portctrl_speed_config_set(int unit, bcm_port_t port, 1045 portctrl_pport_t pport, 1046 portmod_speed_config_t *sp_cfg) 1047 { 1048 int enable; 1049 1050 PORTCTRL_INIT_CHECK(unit); 1051 1052 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 1053 1054 PORTMOD_IF_ERROR_RETURN 1055 (portmod_port_enable_get(unit, port, PORTMOD_PORT_ENABLE_MAC, &enable)); 1056 1057 if (enable) { 1058 /* Disable port */ 1059 BCM_IF_ERROR_RETURN 1060 (_bcm_esw_portctrl_enable_set(unit, port, pport, 1061 PORTMOD_PORT_ENABLE_MAC, 0)); 1062 } 1063 1064 PORTMOD_IF_ERROR_RETURN 1065 (portmod_port_speed_config_set(unit, pport, sp_cfg)); 1066 1067 if (enable) { 1068 /* Re-enable port */ 1069 BCM_IF_ERROR_RETURN 1070 (_bcm_esw_portctrl_enable_set(unit, port, pport, 1071 PORTMOD_PORT_ENABLE_MAC, 1)); 1072 } 1073 1074 return BCM_E_NONE; 1075 } 1076 #endif /* PORTMOD_SUPPORT */ 1077 1078 /* 1079 * Function: 1080 * bcmi_esw_portctrl_probe 1081 * Purpose: 1082 * Probe given port and add to Portmod. 1083 * Parameters: 1084 * unit - (IN) Unit number. 1085 * port - (IN) Port number. 1086 * okay - (OUT) Returns true is port was successfully added. 1087 * Returns: 1088 * BCM_E_NONE 1089 * BCM_E_XXX 1090 * Notes: 1091 * If port is already attached/added in the PortMod, port 1092 * is first removed(detached) and then added again. 1093 */ 1094 int 1095 bcmi_esw_portctrl_probe(int unit, bcm_gport_t port, int init_flag, void *add_info, 1096 int *okay) 1097 { 1098 #ifdef PORTMOD_SUPPORT 1099 portmod_pbmp_t p_pbmp; 1100 int rv = BCM_E_NONE, valid, flags=0, lane=0, num_lanes, speed, physical_port; 1101 portctrl_pport_t pport; 1102 bcm_port_if_t intf; 1103 portmod_dispatch_type_t pm_type; 1104 #ifdef PORTMOD_PM8X50_SUPPORT 1105 portmod_pm_capability_t pm_cap; 1106 int phy_port, pm, lanes_per_pm; 1107 #endif 1108 1109 PORTCTRL_INIT_CHECK(unit); 1110 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 1111 1112 *okay = FALSE; 1113 1114 /* Check if port is already in PM */ 1115 rv = portmod_port_is_valid(unit, pport, &valid); 1116 if (PORTMOD_FAILURE(rv)) { 1117 return rv; 1118 } 1119 1120 1121 /* Remove port from PM if this has been already added */ 1122 if (valid) { 1123 if ((!init_flag) || (init_flag == PORTMOD_PORT_ADD_F_INIT_CORE_PROBE)) { 1124 rv = portmod_port_pm_type_get(unit, port, &port, &pm_type); 1125 if (rv != BCM_E_NONE) { 1126 return rv; 1127 } 1128 #ifdef PORTMOD_PM8X50_SUPPORT 1129 if (pm_type == portmodDispatchTypePm8x50) { 1130 rv = BCM_E_NONE; 1131 } else 1132 #endif 1133 { 1134 rv = bcm_esw_port_interface_get(unit, port, &intf); 1135 /* Don't update speed if the port is attached to PHY_NULL */ 1136 if (BCM_SUCCESS(rv) && (intf != SOC_PORT_IF_NULL)) { 1137 speed = SOC_INFO(unit).port_init_speed[port] > 0 ? 1138 SOC_INFO(unit).port_init_speed[port] : 1139 SOC_INFO(unit).port_speed_max[port]; 1140 rv = _bcm_esw_portctrl_speed_chip_reconfigure(unit, port, speed); 1141 } 1142 } 1143 if (BCM_SUCCESS(rv)) { 1144 PORT_LOCK(unit); 1145 /* PortMod requires port to be disabled before removing it */ 1146 PORTMOD_PORT_ENABLE_PHY_SET(flags); 1147 PORTMOD_PORT_ENABLE_MAC_SET(flags); 1148 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, flags, 0); 1149 if (BCM_SUCCESS(rv)) { 1150 rv = soc_esw_portctrl_delete(unit, pport); 1151 #ifdef PORTMOD_PM8X50_SUPPORT 1152 /* for PM8x50 need to set vco to reconfigure because since 1153 * the port got deleted, the VCOs have been reset in the 1154 * portmod driver */ 1155 if (pm_type == portmodDispatchTypePm8x50) { 1156 phy_port = SOC_INFO(unit).port_l2p_mapping[pport]; 1157 PORTMOD_IF_ERROR_RETURN( 1158 portmod_pm_capability_get(unit, pm_type, &pm_cap)); 1159 lanes_per_pm = pm_cap.pm_capability.pm8x50_cap.num_lanes; 1160 pm = (phy_port - 1) / lanes_per_pm; 1161 SOC_INFO(unit).pm_vco_info[pm].is_tvco_new = 1; 1162 SOC_INFO(unit).pm_vco_info[pm].is_ovco_new = 1; 1163 SOC_IF_ERROR_RETURN( 1164 soc_esw_portctrl_pm_vco_reconfigure(unit)); 1165 } 1166 #endif 1167 } 1168 PORT_UNLOCK(unit); 1169 } 1170 } 1171 } 1172 1173 /* Add port to PM */ 1174 if (SOC_SUCCESS(rv)) { 1175 /* Attach external PHY to Portmod 1176 * Don't attach external PHY to Portmod if port is inactive, like "portmap_2=2:10:i" for flexport 1177 */ 1178 if (((!init_flag) || (init_flag == PORTMOD_PORT_ADD_F_INIT_CORE_PROBE)) && 1179 !SOC_PBMP_MEMBER(SOC_INFO(unit).all.disabled_bitmap, port)) { 1180 PORTMOD_PBMP_CLEAR(p_pbmp); 1181 num_lanes = SOC_INFO(unit).port_num_lanes[port]; 1182 if(num_lanes == 10) { 1183 num_lanes=12; 1184 } 1185 for (lane = 0; lane < num_lanes; lane++) { 1186 PORT_LOCK(unit); 1187 physical_port = SOC_INFO(unit).port_l2p_mapping[port]; 1188 #ifdef BCM_TRIDENT3_SUPPORT 1189 /*To support the 2nd MGMT port, convert its physical port to the dummy port number 131 on TD3.*/ 1190 if((SOC_IS_TRIDENT3(unit)) && (physical_port == 128) && (SOC_PBMP_MEMBER(SOC_INFO(unit).management_pbm, port))){ 1191 physical_port = 131; 1192 } 1193 #endif /* BCM_TRIDENT3_SUPPORT */ 1194 #ifdef BCM_TOMAHAWK3_SUPPORT 1195 /* Tomahawk 3's Management Port Macro requires a spacing between 1196 * the lanes, so even though the two management ports' physical 1197 * ports are 257 and 258, the lane needs to be the next one, 1198 * so logical port 118 being mapped to physical port 258 needs 1199 * to pass 259 to portmod because portmod only recognizes lane 1200 * 0 (physical port 257) and lane 2 (physial port 259). 1201 */ 1202 if (SOC_IS_TOMAHAWK3(unit) && port == 118) { 1203 physical_port = 259; 1204 } 1205 #endif 1206 portmod_xphy_lane_detach(unit, physical_port+lane, 1); 1207 PORT_UNLOCK(unit); 1208 PORTMOD_PBMP_PORT_ADD(p_pbmp, physical_port+lane); 1209 } 1210 PORT_LOCK(unit); 1211 rv = soc_esw_portctrl_setup_ext_phy_add(unit, port, &p_pbmp); 1212 PORT_UNLOCK(unit); 1213 if (SOC_FAILURE(rv)) { 1214 return rv; 1215 } 1216 } 1217 PORT_LOCK(unit); 1218 rv = soc_esw_portctrl_add(unit, port, init_flag, add_info); 1219 PORT_UNLOCK(unit); 1220 } 1221 1222 if (SOC_SUCCESS(rv)) { 1223 if ((init_flag == PORTMOD_PORT_ADD_F_INIT_PASS2) || !init_flag) { 1224 /* Probe function should leave port disabled */ 1225 PORT_LOCK(unit); 1226 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, 1227 PORTMOD_PORT_ENABLE_PHY, 0); 1228 PORT_UNLOCK(unit); 1229 if (SOC_FAILURE(rv)) { 1230 return rv; 1231 } 1232 } 1233 } 1234 1235 *okay = TRUE; 1236 1237 return rv; 1238 1239 #else /* PORTMOD_SUPPORT */ 1240 return BCM_E_UNAVAIL; 1241 #endif /* PORTMOD_SUPPORT */ 1242 } 1243 1244 1245 /* 1246 * Function: 1247 * bcmi_esw_portctrl_probe_pbmp 1248 * Purpose: 1249 * Probe give port bitmap to identify which ports to add to Portmod. 1250 * Parameters: 1251 * unit - (IN) Unit number. 1252 * pbmp - (IN) Port bitmap. 1253 * okay_pbmp - (OUT) Port bitmap okay. 1254 * Returns: 1255 * BCM_E_NONE 1256 * BCM_E_XXX 1257 */ 1258 int 1259 bcmi_esw_portctrl_probe_pbmp(int unit, pbmp_t pbmp, pbmp_t *okay_pbmp) 1260 { 1261 #ifdef PORTMOD_SUPPORT 1262 pbmp_t lcl_pbmp; 1263 soc_port_t port; 1264 int okay = 0; 1265 int rv = BCM_E_NONE; 1266 portctrl_pport_t pport; 1267 phymod_operation_mode_t phy_op_mode; 1268 _bcm_port_info_t *port_info = NULL; 1269 portmod_port_add_info_t *add_info = NULL; 1270 portmod_port_add_info_t *port_add_info = NULL; 1271 int count = 0; 1272 int physical_port; 1273 #ifdef FW_BCAST_DOWNLOAD 1274 int bcast_flag, crc_en; 1275 #endif 1276 1277 PORTCTRL_INIT_CHECK(unit); 1278 1279 SOC_PBMP_CLEAR(lcl_pbmp); 1280 SOC_PBMP_CLEAR(*okay_pbmp); 1281 1282 PBMP_ITER(pbmp, port) { 1283 /* Skip RCPU ports */ 1284 #ifdef BCM_RCPU_SUPPORT 1285 if (SOC_IS_RCPU_ONLY(unit) && 1286 SOC_PORT_VALID(unit, RCPU_PORT(unit)) && 1287 BCM_PBMP_MEMBER(pbmp, RCPU_PORT(unit))) { 1288 continue; 1289 } 1290 #endif /* BCM_RCPU_SUPPORT */ 1291 if (IS_TDM_PORT(unit, port)) { 1292 continue; 1293 } 1294 SOC_PBMP_PORT_ADD(lcl_pbmp, port); 1295 } 1296 1297 if (!SOC_WARM_BOOT(unit)) { 1298 SOC_PBMP_COUNT(pbmp, count); 1299 1300 add_info = sal_alloc(sizeof(portmod_port_add_info_t)*count, 1301 "portmod_port_add_info_t"); 1302 if (add_info == NULL) { 1303 rv = SOC_E_MEMORY; 1304 return rv; 1305 } 1306 1307 /*step1: probe Serdes and external PHY core*/ 1308 count = 0; 1309 PBMP_ITER(lcl_pbmp, port) { 1310 port_add_info = add_info + count; 1311 rv = bcmi_esw_portctrl_probe(unit, port, 1312 PORTMOD_PORT_ADD_F_INIT_CORE_PROBE, 1313 port_add_info, &okay); 1314 if (BCM_FAILURE(rv)) { 1315 goto cleanup; 1316 } 1317 1318 count++; 1319 } 1320 1321 /*step2 : initialize PASS1 for SerDes and external PHY*/ 1322 count = 0; 1323 PBMP_ITER(lcl_pbmp, port) { 1324 port_add_info = add_info + count; 1325 rv = bcmi_esw_portctrl_probe(unit, port, 1326 PORTMOD_PORT_ADD_F_INIT_PASS1, port_add_info, &okay); 1327 if (BCM_FAILURE(rv)) { 1328 goto cleanup; 1329 } 1330 1331 count++; 1332 } 1333 1334 #ifdef FW_BCAST_DOWNLOAD 1335 bcast_flag = soc_property_get(unit, spn_LOAD_FIRMWARE, 0); 1336 if (bcast_flag & 0xff0000) { 1337 crc_en = (bcast_flag >> 8) & 0xFF; 1338 rv = portmod_common_serdes_fw_bcst(unit, lcl_pbmp, crc_en); 1339 if (BCM_FAILURE(rv)) { 1340 goto cleanup; 1341 } 1342 } 1343 #endif 1344 1345 /* step3:broadcast firmware download for all external phys inculde legacy and Phymod PHYs*/ 1346 if (!(SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit))) { 1347 rv = portmod_legacy_ext_phy_init(unit, pbmp); 1348 if (BCM_FAILURE(rv)) { 1349 goto cleanup; 1350 } 1351 1352 rv = portmod_common_ext_phy_fw_bcst(unit, &lcl_pbmp); 1353 if (BCM_FAILURE(rv)) { 1354 goto cleanup; 1355 } 1356 } 1357 1358 /*step4:initialize PASS2 for Serdes and external PHY*/ 1359 count = 0; 1360 PBMP_ITER(lcl_pbmp, port) { 1361 port_add_info = add_info + count; 1362 rv = bcmi_esw_portctrl_probe(unit, port, 1363 PORTMOD_PORT_ADD_F_INIT_PASS2, port_add_info, &okay); 1364 if (BCM_FAILURE(rv)) { 1365 goto cleanup; 1366 } 1367 1368 if (okay) { 1369 SOC_PBMP_PORT_ADD(*okay_pbmp, port); 1370 soc_counter_port_pbmp_add(unit, port); 1371 } 1372 count++; 1373 } 1374 cleanup: 1375 if (add_info != NULL) { 1376 sal_free(add_info); 1377 } 1378 if (BCM_FAILURE(rv)) { 1379 return rv; 1380 } 1381 } 1382 1383 /* warmboot boot, restore external phys data base. */ 1384 if (SOC_WARM_BOOT(unit)) { 1385 BCM_IF_ERROR_RETURN(soc_esw_portctrl_xphy_wb_db_restore(unit)); 1386 } 1387 1388 PBMP_ITER(pbmp, port) { 1389 BCM_IF_ERROR_RETURN 1390 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 1391 if (!SOC_WARM_BOOT(unit)) { 1392 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, 1393 PORTMOD_PORT_ENABLE_MAC, FALSE); 1394 if (BCM_FAILURE(rv)) { 1395 SOC_PBMP_PORT_REMOVE(*okay_pbmp, port); 1396 soc_counter_port_pbmp_remove(unit, port); 1397 LOG_WARN(BSL_LS_BCM_PORT, 1398 (BSL_META_U(unit, 1399 "MAC init failed on port %s\n"), 1400 SOC_PORT_NAME(unit, port))); 1401 break; 1402 } 1403 } else { 1404 portmod_port_interface_config_t interface_config; 1405 portmod_port_init_config_t init_config; 1406 portmod_pbmp_t p_pbmp; 1407 int lane=0, num_lanes=0; 1408 int legacy_phy = 0; 1409 1410 rv = soc_esw_portctrl_config_get(unit, port, 1411 &interface_config, 1412 &init_config, 1413 &phy_op_mode); 1414 if (BCM_FAILURE(rv)) { 1415 break; 1416 } 1417 1418 /* restore external phy attach */ 1419 PORTMOD_PBMP_CLEAR(p_pbmp); 1420 num_lanes = SOC_INFO(unit).port_num_lanes[port]; 1421 if(num_lanes == 10) num_lanes=12; 1422 for (lane = 0; lane < num_lanes; lane++) { 1423 physical_port = SOC_INFO(unit).port_l2p_mapping[port]; 1424 #ifdef BCM_TRIDENT3_SUPPORT 1425 /*To support the 2nd MGMT port, convert its physical port to the dummy port number 131 on TD3.*/ 1426 if((SOC_IS_TRIDENT3X(unit)) && (physical_port == 128) && (SOC_PBMP_MEMBER(SOC_INFO(unit).management_pbm, port))){ 1427 physical_port = 131; 1428 } 1429 #endif /* BCM_TRIDENT3_SUPPORT */ 1430 #ifdef BCM_TOMAHAWK3_SUPPORT 1431 if (SOC_IS_TOMAHAWK3(unit) && (physical_port == 258)) { 1432 physical_port = 259; 1433 } 1434 #endif 1435 PORTMOD_PBMP_PORT_ADD(p_pbmp, physical_port + lane); 1436 } 1437 SOC_IF_ERROR_RETURN(soc_esw_portctrl_setup_ext_phy_add(unit, port, &p_pbmp)); 1438 1439 /* Restore ports with legacy external phys */ 1440 rv = portmod_port_check_legacy_phy(unit, port, &legacy_phy); 1441 if (BCM_FAILURE(rv)) { 1442 break; 1443 } 1444 1445 if (legacy_phy) { 1446 BCM_IF_ERROR_RETURN(portmod_port_legacy_phy_init(unit, port)); 1447 } 1448 1449 rv = portmod_port_warmboot_db_restore(unit, pport, &interface_config, &init_config, phy_op_mode); 1450 if (BCM_FAILURE(rv)) { 1451 break; 1452 } 1453 } 1454 1455 if (soc_property_get(unit, spn_SAME_SPEED_INTF_DO_NOT_OVERWRITE, 1456 (SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM))) { 1457 _bcm_port_info_access(unit, port, &port_info); 1458 1459 /* PM8x50 ports do not support port_interface_get */ 1460 if (IS_CD_PORT(unit, port)) { 1461 port_info->intf = BCM_PORT_IF_NOCXN; 1462 } else { 1463 if ((rv = bcm_esw_port_interface_get(unit, port, 1464 &port_info->intf)) < 0) { 1465 port_info->intf = BCM_PORT_IF_NOCXN; 1466 } 1467 } 1468 } 1469 1470 if (soc_property_port_get(unit, port, spn_FCMAP_ENABLE, 0)) { 1471 soc_persist_t *sop = SOC_PERSIST(unit); 1472 SOC_PBMP_PORT_ADD(sop->lc_pbm_fc, port); 1473 } 1474 1475 /* Check if the port is set in EtherRAM buffer mode */ 1476 if (soc_property_port_get(unit, port, spn_PHY_OPERATIONAL_MODE, 0) == 3) { 1477 soc_persist_t *sop = SOC_PERSIST(unit); 1478 SOC_PBMP_PORT_ADD(sop->lc_pbm_eth_buffer_mode, port); 1479 } 1480 } 1481 1482 return BCM_E_NONE; 1483 1484 #else /* PORTMOD_SUPPORT */ 1485 return BCM_E_UNAVAIL; 1486 #endif /* PORTMOD_SUPPORT */ 1487 } 1488 1489 1490 /* 1491 * Function: 1492 * bcmi_esw_portctrl_ability_get 1493 * Purpose: 1494 * Retrieve the local port abilities. 1495 * Parameters: 1496 * unit - (IN) Unit number. 1497 * port - (IN) Port number. 1498 * port_ability - (OUT) Returns bcm_port_ability_t structure information. 1499 * ability_mask - (OUT) If !NULL, returns mask of BCM_PORT_ABIL_ 1500 * values indicating the ability of the MAC/PHY. 1501 * Returns: 1502 * BCM_E_NONE 1503 * BCM_E_XXX 1504 */ 1505 int 1506 bcmi_esw_portctrl_ability_get(int unit, bcm_gport_t port, 1507 bcm_port_ability_t *port_ability, 1508 bcm_port_abil_t *ability_mask) 1509 { 1510 #ifdef PORTMOD_SUPPORT 1511 int rv = BCM_E_NONE; 1512 portctrl_pport_t pport; 1513 portmod_port_ability_t portmod_ability; 1514 1515 PORTCTRL_INIT_CHECK(unit); 1516 1517 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 1518 1519 if(!(SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port))) { 1520 return BCM_E_PORT; 1521 } 1522 1523 if (IS_CD_PORT(unit, port)) { 1524 return BCM_E_UNAVAIL; 1525 } 1526 1527 sal_memset(port_ability, 0, sizeof(*port_ability)); 1528 sal_memset(&portmod_ability, 0, sizeof(portmod_ability)); 1529 if (ability_mask != NULL) { 1530 *ability_mask = 0; 1531 } 1532 1533 PORT_LOCK(unit); 1534 rv = portmod_port_ability_local_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &portmod_ability); 1535 PORT_UNLOCK(unit); 1536 1537 if (PORTMOD_SUCCESS(rv)) { 1538 _bcm_esw_portctrl_from_portmod_ability(&portmod_ability, 1539 port_ability); 1540 1541 #if defined (BCM_TOMAHAWK2_SUPPORT) || defined (BCM_TRIDENT3_SUPPORT) || defined (BCM_TOMAHAWK3_SUPPORT) 1542 if ((SOC_IS_TOMAHAWK2(unit) || SOC_IS_TRIDENT3X(unit) || 1543 SOC_IS_TOMAHAWK3(unit)) && 1544 soc_feature(unit, soc_feature_flexport_based_speed_set)) { 1545 bcm_port_abil_t mask; 1546 1547 BCM_IF_ERROR_RETURN 1548 (bcmi_xgs5_flexport_based_speed_ability_get(unit, port, &mask)); 1549 port_ability->speed_full_duplex &= mask; 1550 port_ability->speed_half_duplex &= mask; 1551 } 1552 #endif 1553 port_ability->loopback |= BCM_PORT_ABILITY_LB_NONE; 1554 if(SAL_BOOT_SIMULATION) { 1555 port_ability->loopback |= BCM_PORT_ABILITY_LB_MAC; 1556 port_ability->loopback &= ~BCM_PORT_ABILITY_LB_PHY; 1557 } 1558 1559 if ((soc_feature(unit, soc_feature_embedded_higig)) && 1560 IS_E_PORT(unit, port)) { 1561 port_ability->encap |= BCM_PA_ENCAP_HIGIG2_L2; 1562 port_ability->encap |= BCM_PA_ENCAP_HIGIG2_IP_GRE; 1563 } 1564 1565 if ((soc_feature(unit, soc_feature_higig_over_ethernet))) { 1566 port_ability->encap |= BCM_PA_ENCAP_HIGIG_OVER_ETHERNET; 1567 } 1568 1569 if (soc_feature(unit, soc_feature_no_higig_plus)) { 1570 port_ability->encap &= ~BCM_PA_ENCAP_HIGIG; 1571 } 1572 1573 if (soc_feature(unit, soc_feature_roe)) { 1574 port_ability->encap |= BCM_PA_ENCAP_CPRI; 1575 port_ability->encap |= BCM_PA_ENCAP_RSVD4; 1576 } 1577 1578 SOC_IF_ERROR_RETURN( 1579 soc_esw_portctrl_port_ability_update(unit, port, port_ability)); 1580 1581 /* Convert to BCM_PORT_ABIL_ mask if needed */ 1582 if (ability_mask != NULL) { 1583 rv = soc_port_ability_to_mode(port_ability, ability_mask); 1584 } 1585 } 1586 1587 if (ability_mask != NULL) { 1588 LOG_INFO(BSL_LS_BCM_PORT, 1589 (BSL_META_UP(unit, port, 1590 "Port ability get: u=%d p=%d abil=0x%x " 1591 "rv=%d\n"), 1592 unit, port, *ability_mask, rv)); 1593 } else { 1594 LOG_INFO(BSL_LS_BCM_PORT, 1595 (BSL_META_UP(unit, port, 1596 "Port ability get: u=%d p=%d rv=%d\n"), 1597 unit, port, rv)); 1598 } 1599 1600 LOG_VERBOSE(BSL_LS_BCM_PORT, 1601 (BSL_META_UP(unit, port, 1602 "Speed(HD=0x%08x, FD=0x%08x) Pause=0x%08x abl_get\n" 1603 "Interface=0x%08x Medium=0x%08x EEE=0x%08x " 1604 "Loopback=0x%08x Flags=0x%08x\n"), 1605 port_ability->speed_half_duplex, 1606 port_ability->speed_full_duplex, 1607 port_ability->pause, port_ability->interface, 1608 port_ability->medium, port_ability->eee, 1609 port_ability->loopback, port_ability->flags)); 1610 1611 return rv; 1612 #else /* PORTMOD_SUPPORT */ 1613 return BCM_E_UNAVAIL; 1614 #endif /* PORTMOD_SUPPORT */ 1615 } 1616 1617 /* Function: 1618 * bcmi_esw_portctrl_speed_ability_local_get 1619 * Purpose: 1620 * Retrieve the local speed abilities 1621 * Parameters: 1622 * unit - (IN) Unit number. 1623 * port - (IN) Port number. 1624 * max_num_ability - (IN) Maximum number of abilities that can be returned. 1625 * abilities - (OUT) Abilities array. 1626 * actual_num_ability - (OUT) Actual number of abilities in abilities array. 1627 * Returns: 1628 * BCM_E_NONE 1629 * BCM_E_XXX 1630 */ 1631 int 1632 bcmi_esw_portctrl_speed_ability_local_get(int unit, 1633 bcm_gport_t port, 1634 int max_num_ability, 1635 bcm_port_speed_ability_t *abilities, 1636 int *actual_num_ability) 1637 { 1638 #ifdef PORTMOD_SUPPORT 1639 int rv = BCM_E_NONE, sp_abilities_size = 0; 1640 portctrl_pport_t pport; 1641 portmod_port_speed_ability_t *sp_abilities = NULL; 1642 int valid_abilities; 1643 1644 PORTCTRL_INIT_CHECK(unit); 1645 1646 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 1647 1648 sp_abilities_size = PORTCTRL_SPEED_ABILITY_MAX_COUNT; 1649 1650 sp_abilities = sal_alloc(sp_abilities_size * sizeof(portmod_port_speed_ability_t), "abilities array"); 1651 if (sp_abilities == NULL) { 1652 rv = SOC_E_MEMORY; 1653 return rv; 1654 } 1655 1656 sal_memset(sp_abilities, 0, sp_abilities_size * sizeof(portmod_port_speed_ability_t)); 1657 *actual_num_ability = 0; 1658 1659 PORT_LOCK(unit); 1660 rv = portmod_port_speed_ability_local_get(unit, pport, sp_abilities_size, 1661 sp_abilities, actual_num_ability); 1662 PORT_UNLOCK(unit); 1663 1664 if (PORTMOD_SUCCESS(rv)) { 1665 BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_from_portmod_autoneg_ability(unit, 1666 *actual_num_ability, sp_abilities, max_num_ability, 1667 abilities, &valid_abilities)); 1668 *actual_num_ability = valid_abilities; 1669 } 1670 1671 LOG_INFO(BSL_LS_BCM_PORT, (BSL_META_UP(unit, port, 1672 "Port speed ability local get: u=%d p=%d rv=%d\n"), unit, port, rv)); 1673 1674 if (NULL != sp_abilities) { 1675 sal_free(sp_abilities); 1676 } 1677 return rv; 1678 #else /* PORTMOD_SUPPORT */ 1679 return BCM_E_UNAVAIL; 1680 #endif /* PORTMOD_SUPPORT */ 1681 } 1682 /* 1683 * Function: 1684 * bcmi_esw_portctrl_ability_remote_get 1685 * Purpose: 1686 * Retrieve the remote advertised port abilities. 1687 * Parameters: 1688 * unit - (IN) Unit number. 1689 * port - (IN) Port number. 1690 * port_ability - (OUT) Returns bcm_port_ability_t structure information. 1691 * ability_mask - (OUT) If !NULL, returns mask of BCM_PORT_ABIL_ 1692 * values indicating the ability of the MAC/PHY. 1693 * Returns: 1694 * BCM_E_NONE 1695 * BCM_E_XXX 1696 */ 1697 int 1698 bcmi_esw_portctrl_ability_remote_get(int unit, bcm_gport_t port, 1699 bcm_port_ability_t *port_ability, 1700 bcm_port_abil_t *ability_mask) 1701 { 1702 #ifdef PORTMOD_SUPPORT 1703 int rv = BCM_E_NONE; 1704 portctrl_pport_t pport; 1705 portmod_port_ability_t portmod_ability; 1706 phymod_autoneg_status_t an_status; 1707 1708 PORTCTRL_INIT_CHECK(unit); 1709 1710 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 1711 1712 sal_memset(port_ability, 0, sizeof(*port_ability)); 1713 sal_memset(&portmod_ability, 0, sizeof(portmod_ability)); 1714 if (ability_mask != NULL) { 1715 *ability_mask = 0; 1716 } 1717 1718 PORT_LOCK(unit); 1719 1720 rv = portmod_port_autoneg_status_get(unit, pport, &an_status); 1721 1722 if (PORTMOD_SUCCESS(rv)) { 1723 if (an_status.enabled && an_status.locked) { 1724 #ifdef SW_AUTONEG_SUPPORT 1725 { 1726 int an_mode = 0; 1727 1728 an_mode = soc_property_port_get(unit, port, 1729 spn_PHY_AN_C73, an_mode); 1730 if (soc_feature(unit, soc_feature_sw_autoneg)) { 1731 /* phy_an_c73 value of 3 indicated MSA AN mode */ 1732 if ((an_mode == SW_AN_MODE_CL73_MSA) || 1733 (an_mode == SW_AN_MODE_MSA_ONLY)) { 1734 rv = bcm_sw_an_ability_remote_get(unit, port, port_ability); 1735 if (PORTMOD_SUCCESS(rv)) { 1736 /* Convert to BCM_PORT_ABIL_ mask if needed */ 1737 if (ability_mask != NULL) { 1738 rv = soc_port_ability_to_mode(port_ability, ability_mask); 1739 } 1740 PORT_UNLOCK(unit); 1741 return rv; 1742 } 1743 } 1744 } 1745 } 1746 #endif 1747 rv = portmod_port_ability_remote_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, 1748 &portmod_ability); 1749 } 1750 } 1751 1752 PORT_UNLOCK(unit); 1753 1754 if (PORTMOD_SUCCESS(rv)) { 1755 _bcm_esw_portctrl_from_portmod_ability(&portmod_ability, 1756 port_ability); 1757 1758 /* Convert to BCM_PORT_ABIL_ mask if needed */ 1759 if (ability_mask != NULL) { 1760 rv = soc_port_ability_to_mode(port_ability, ability_mask); 1761 } 1762 } 1763 1764 if (ability_mask != NULL) { 1765 LOG_INFO(BSL_LS_BCM_PORT, 1766 (BSL_META_UP(unit, port, 1767 "Port ability remote get: u=%d p=%d abil=0x%x " 1768 "rv=%d\n"), 1769 unit, port, *ability_mask, rv)); 1770 } else { 1771 LOG_INFO(BSL_LS_BCM_PORT, 1772 (BSL_META_UP(unit, port, 1773 "Port ability remote get: u=%d p=%d rv=%d\n"), 1774 unit, port, rv)); 1775 } 1776 1777 LOG_VERBOSE(BSL_LS_BCM_PORT, 1778 (BSL_META_UP(unit, port, 1779 "Speed(HD=0x%08x, FD=0x%08x) Pause=0x%08x abl_remote_get\n" 1780 "Interface=0x%08x Medium=0x%08x " 1781 "Loopback=0x%08x Flags=0x%08x\n"), 1782 port_ability->speed_half_duplex, 1783 port_ability->speed_full_duplex, 1784 port_ability->pause, port_ability->interface, 1785 port_ability->medium, 1786 port_ability->loopback, port_ability->flags)); 1787 1788 return rv; 1789 #else /* PORTMOD_SUPPORT */ 1790 return BCM_E_UNAVAIL; 1791 #endif /* PORTMOD_SUPPORT */ 1792 } 1793 1794 /* Function: 1795 * bcmi_esw_portctrl_autoneg_ability_remote_get 1796 * Purpose: 1797 * Retrieve the remote advertised autoneg abilities 1798 * Parameters: 1799 * unit - (IN) Unit number. 1800 * port - (IN) Port number. 1801 * max_num_ability - (IN) Maximum number of abilities that can be returned. 1802 * abilities - (OUT) Abilities array. 1803 * actual_num_ability - (OUT) Actual number of abilities in abilities array. 1804 * Returns: 1805 * BCM_E_NONE 1806 * BCM_E_XXX 1807 */ 1808 int 1809 bcmi_esw_portctrl_autoneg_ability_remote_get(int unit, 1810 bcm_gport_t port, 1811 int max_num_ability, 1812 bcm_port_speed_ability_t *abilities, 1813 int *actual_num_ability) 1814 { 1815 #ifdef PORTMOD_SUPPORT 1816 int rv = BCM_E_NONE, an_abilities_size = 0; 1817 portctrl_pport_t pport; 1818 portmod_port_speed_ability_t *an_abilities = NULL; 1819 phymod_autoneg_status_t an_status; 1820 int valid_abilities; 1821 1822 PORTCTRL_INIT_CHECK(unit); 1823 1824 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 1825 1826 an_abilities_size = PORTCTRL_AUTONEG_ABILITY_MAX_COUNT; 1827 1828 an_abilities = sal_alloc(an_abilities_size * sizeof(portmod_port_speed_ability_t), "abilities array"); 1829 if (an_abilities == NULL) { 1830 rv = SOC_E_MEMORY; 1831 return rv; 1832 } 1833 1834 sal_memset(an_abilities, 0, an_abilities_size * sizeof(portmod_port_speed_ability_t)); 1835 *actual_num_ability = 0; 1836 1837 PORT_LOCK(unit); 1838 rv = portmod_port_autoneg_status_get(unit, pport, &an_status); 1839 if (PORTMOD_SUCCESS(rv)) { 1840 if (an_status.enabled && an_status.locked) { 1841 rv = portmod_port_autoneg_ability_remote_get(unit, pport, 1842 an_abilities_size, an_abilities, actual_num_ability); 1843 } 1844 } 1845 PORT_UNLOCK(unit); 1846 1847 if (PORTMOD_SUCCESS(rv)) { 1848 _bcm_esw_portctrl_from_portmod_autoneg_ability(unit, 1849 *actual_num_ability, an_abilities, 1850 max_num_ability, abilities, &valid_abilities); 1851 *actual_num_ability = valid_abilities; 1852 } 1853 1854 LOG_INFO(BSL_LS_BCM_PORT, (BSL_META_UP(unit, port, 1855 "Port autoneg ability remote get: u=%d p=%d rv=%d\n"), unit, port, rv)); 1856 1857 if (NULL != an_abilities) { 1858 sal_free(an_abilities); 1859 } 1860 return rv; 1861 #else /* PORTMOD_SUPPORT */ 1862 return BCM_E_UNAVAIL; 1863 #endif /* PORTMOD_SUPPORT */ 1864 } 1865 1866 /* 1867 * Function: 1868 * bcmi_esw_portctrl_enable_get 1869 * Purpose: 1870 * Gets the enable state as defined by bcm_port_enable_set() 1871 * Parameters: 1872 * unit - (IN) Unit number. 1873 * port - (IN) Port number. 1874 * enable - (OUT) TRUE, port is enabled, FALSE port is disabled. 1875 * Returns: 1876 * BCM_E_XXX 1877 * Notes: 1878 * The PHY enable holds the port enable state set by the user. 1879 * The MAC enable transitions up and down automatically via linkscan 1880 * even if user port enable is always up. 1881 */ 1882 int 1883 bcmi_esw_portctrl_enable_get(int unit, bcm_gport_t port, int *enable) 1884 { 1885 #ifdef PORTMOD_SUPPORT 1886 int rv = BCM_E_NONE; 1887 portctrl_pport_t pport; 1888 _bcm_port_info_t *port_info = NULL; 1889 1890 PORTCTRL_INIT_CHECK(unit); 1891 1892 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 1893 1894 if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), port)) { 1895 *enable = 0; 1896 return BCM_E_NONE; 1897 } 1898 1899 PORT_LOCK(unit); 1900 1901 rv = portmod_port_enable_get(unit, pport, PORTMOD_PORT_ENABLE_PHY, enable); 1902 1903 _bcm_port_info_access(unit, port, &port_info); 1904 1905 if (port_info == NULL) { 1906 PORT_UNLOCK(unit); 1907 return BCM_E_INIT; 1908 } 1909 *enable = port_info->enable & (*enable); 1910 1911 PORT_UNLOCK(unit); 1912 1913 LOG_INFO(BSL_LS_BCM_PORT, 1914 (BSL_META_UP(unit, port, 1915 "Port enable get: u=%d p=%d rv=%d enable=%d\n"), 1916 unit, port, rv, *enable)); 1917 1918 return rv; 1919 1920 #else /* PORTMOD_SUPPORT */ 1921 return BCM_E_UNAVAIL; 1922 #endif /* PORTMOD_SUPPORT */ 1923 } 1924 1925 1926 /* 1927 * Function: 1928 * bcmi_esw_portctrl_enable_set 1929 * Purpose: 1930 * Physically enable/disable the MAC/PHY on this port. 1931 * Parameters: 1932 * unit - (IN) Unit number. 1933 * port - (IN) Port number. 1934 * enable - (IN) TRUE, port is enabled, FALSE port is disabled. 1935 * Returns: 1936 * BCM_E_XXX 1937 * Notes: 1938 * If linkscan is running, it also controls the MAC enable state. 1939 */ 1940 int 1941 bcmi_esw_portctrl_enable_set(int unit, bcm_gport_t port, int enable) 1942 { 1943 #ifdef PORTMOD_SUPPORT 1944 int rv = BCM_E_NONE; 1945 portctrl_pport_t pport; 1946 int link, loopback = BCM_PORT_LOOPBACK_NONE; 1947 soc_persist_t *sop = SOC_PERSIST(unit); 1948 _bcm_port_info_t *port_info; 1949 int flags = 0; 1950 pbmp_t pbm; 1951 1952 #if defined(INCLUDE_L3) 1953 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 1954 int ecmp_dlb_restore = 0; 1955 int dlb_link_status; 1956 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 1957 #endif /* INCLUDE_L3 */ 1958 1959 PORTCTRL_INIT_CHECK(unit); 1960 1961 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 1962 1963 #ifdef BCM_RCPU_SUPPORT 1964 if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) { 1965 return BCM_E_PORT; 1966 } 1967 #endif /* BCM_RCPU_SUPPORT */ 1968 1969 BCM_IF_ERROR_RETURN 1970 (bcmi_esw_portctrl_loopback_get(unit, port, &loopback)); 1971 1972 PORT_LOCK(unit); 1973 1974 if (enable) { 1975 if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit, all), port)) { 1976 PORT_UNLOCK(unit); 1977 return BCM_E_NONE; 1978 } 1979 1980 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, 1981 PORTMOD_PORT_ENABLE_PHY, 1); 1982 if (BCM_FAILURE(rv)) { 1983 PORT_UNLOCK(unit); 1984 return rv; 1985 } 1986 1987 /* Get link status after PHY state has been set */ 1988 rv = bcm_esw_port_link_status_get(unit, port, &link); 1989 if (BCM_FAILURE(rv)) { 1990 if (rv == BCM_E_INIT) { 1991 link = FALSE; 1992 rv = BCM_E_NONE; 1993 } else { 1994 PORT_UNLOCK(unit); 1995 return rv; 1996 } 1997 } 1998 if (link || (loopback != BCM_PORT_LOOPBACK_NONE) 1999 || SOC_PBMP_MEMBER(sop->lc_pbm_fc, port) 2000 || SOC_PBMP_MEMBER(sop->lc_pbm_linkdown_tx, port)) { 2001 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, 2002 PORTMOD_PORT_ENABLE_MAC, 1); 2003 if (BCM_FAILURE(rv)) { 2004 PORT_UNLOCK(unit); 2005 return rv; 2006 } 2007 } 2008 2009 } else { 2010 2011 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2012 (BSL_META_UP(unit, port, 2013 "Disable and isolate u=%d p=%d\n"), 2014 unit, port)); 2015 2016 /* 2017 * When the port is configured to MAC loopback, 2018 * cannot disable MAC. 2019 */ 2020 PORTMOD_PORT_ENABLE_PHY_SET(flags); 2021 if (loopback != BCM_PORT_LOOPBACK_MAC) { 2022 PORTMOD_PORT_ENABLE_MAC_SET(flags); 2023 } 2024 #if defined(INCLUDE_L3) 2025 #if defined (BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 2026 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 2027 soc_mem_lock(unit, DLB_ECMP_LINK_CONTROLm); 2028 rv = _bcm_esw_port_ecmp_dlb_link_status_get(unit, port, &dlb_link_status); 2029 if (rv != BCM_E_NONE) { 2030 if (rv != BCM_E_UNAVAIL) { 2031 soc_mem_unlock(unit, DLB_ECMP_LINK_CONTROLm); 2032 PORT_UNLOCK(unit); 2033 return rv; 2034 } 2035 } else { 2036 if (dlb_link_status == BCM_L3_ECMP_DYNAMIC_MEMBER_HW_DOWN || 2037 dlb_link_status == BCM_L3_ECMP_DYNAMIC_MEMBER_HW_UP) { 2038 dlb_link_status = BCM_L3_ECMP_DYNAMIC_MEMBER_HW; 2039 } 2040 if (dlb_link_status != BCM_L3_ECMP_DYNAMIC_MEMBER_FORCE_DOWN) { 2041 rv = _bcm_esw_port_ecmp_dlb_link_status_set(unit, port, 2042 BCM_L3_ECMP_DYNAMIC_MEMBER_FORCE_DOWN); 2043 if (rv != BCM_E_NONE) { 2044 if (rv != BCM_E_UNAVAIL) { 2045 soc_mem_unlock(unit, DLB_ECMP_LINK_CONTROLm); 2046 PORT_UNLOCK(unit); 2047 return rv; 2048 } 2049 } else { 2050 ecmp_dlb_restore = 1; 2051 } 2052 } 2053 } 2054 } 2055 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 2056 #endif /* INCLUDE_L3 */ 2057 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, flags, 0); 2058 if (BCM_FAILURE(rv)) { 2059 #if defined(INCLUDE_L3) 2060 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 2061 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 2062 soc_mem_unlock(unit, DLB_ECMP_LINK_CONTROLm); 2063 } 2064 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 2065 #endif /* INCLUDE_L3 */ 2066 PORT_UNLOCK(unit); 2067 return rv; 2068 } 2069 2070 #if defined(INCLUDE_L3) 2071 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 2072 if (soc_feature(unit, soc_feature_ecmp_dlb_optimized)) { 2073 if (ecmp_dlb_restore) { 2074 rv = _bcm_esw_port_ecmp_dlb_link_status_set(unit, port, 2075 dlb_link_status); 2076 if (rv != BCM_E_NONE && rv != BCM_E_UNAVAIL) { 2077 soc_mem_unlock(unit, DLB_ECMP_LINK_CONTROLm); 2078 PORT_UNLOCK(unit); 2079 return rv; 2080 } 2081 } 2082 soc_mem_unlock(unit, DLB_ECMP_LINK_CONTROLm); 2083 } 2084 #endif /* BCM_TOMAHAWK2_SUPPORT || BCM_TRIDENT3_SUPPORT */ 2085 #endif /* INCLUDE_L3 */ 2086 } 2087 2088 _bcm_port_info_access(unit, port, &port_info); 2089 port_info->enable = enable; 2090 2091 #ifdef SW_AUTONEG_SUPPORT 2092 rv = _bcm_esw_port_notify_link_down_evt(unit, port); 2093 if (BCM_FAILURE(rv)) { 2094 LOG_WARN(BSL_LS_BCM_PORT, 2095 (BSL_META_U(unit, 2096 "u=%d p=%d NOTIFY LINK DOWN EVT rv=%d\n"),unit, port, rv)); 2097 PORT_UNLOCK(unit); 2098 return rv; 2099 } 2100 #endif 2101 PORT_UNLOCK(unit); 2102 2103 /* Unlock before link call */ 2104 if (loopback != BCM_PORT_LOOPBACK_NONE) { 2105 if (loopback == BCM_PORT_LOOPBACK_MAC) { 2106 rv = _bcm_esw_link_force(unit, 0, port, TRUE, TRUE); 2107 } else { 2108 rv = _bcm_esw_link_force(unit, 0, port, TRUE, enable); 2109 } 2110 } else { 2111 /* Check for change in link status to avoid race with linkscan thread 2112 */ 2113 SOC_PBMP_CLEAR(pbm); 2114 SOC_PBMP_PORT_ADD(pbm, port); 2115 (void)bcm_esw_linkscan_update(unit, pbm); 2116 } 2117 2118 LOG_INFO(BSL_LS_BCM_PORT, 2119 (BSL_META_UP(unit, port, 2120 "Port enable set: u=%d p=%d enable=%d rv=%d\n"), 2121 unit, port, enable, rv)); 2122 2123 #ifdef BCM_WARM_BOOT_SUPPORT 2124 SOC_CONTROL_LOCK(unit); 2125 SOC_CONTROL(unit)->scache_dirty = 1; 2126 SOC_CONTROL_UNLOCK(unit); 2127 #endif 2128 2129 return rv; 2130 2131 #else /* PORTMOD_SUPPORT */ 2132 return BCM_E_UNAVAIL; 2133 #endif /* PORTMOD_SUPPORT */ 2134 } 2135 2136 2137 /* 2138 * Function: 2139 * bcmi_esw_portctrl_mac_enable_set 2140 * Purpose: 2141 * Physically enable/disable the MAC on this port. 2142 * Parameters: 2143 * unit - (IN) Unit number. 2144 * port - (IN) Port number. 2145 * enable - (IN) TRUE, port is enabled, FALSE port is disabled. 2146 * Returns: 2147 * BCM_E_XXX 2148 * Notes: 2149 * Unlike bcmi_esw_portctl_enable_set(), this routine 2150 * only enables the MAC. It does not contain any logic 2151 * to handle loopback cases, PHY, or current port state. 2152 */ 2153 int 2154 bcmi_esw_portctrl_mac_enable_set(int unit, bcm_gport_t port, int enable) 2155 { 2156 #ifdef PORTMOD_SUPPORT 2157 int rv = BCM_E_NONE; 2158 portctrl_pport_t pport; 2159 2160 PORTCTRL_INIT_CHECK(unit); 2161 2162 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 2163 2164 PORT_LOCK(unit); 2165 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, 2166 PORTMOD_PORT_ENABLE_MAC, enable); 2167 PORT_UNLOCK(unit); 2168 2169 return rv; 2170 2171 #else /* PORTMOD_SUPPORT */ 2172 return BCM_E_UNAVAIL; 2173 #endif /* PORTMOD_SUPPORT */ 2174 } 2175 2176 2177 /* 2178 * Function: 2179 * bcmi_esw_portctrl_phy_enable_set 2180 * Purpose: 2181 * Physically enable/disable the PHY on this port. 2182 * Parameters: 2183 * unit - (IN) Unit number. 2184 * port - (IN) Port number. 2185 * enable - (IN) TRUE, PHY port is enabled, FALSE PHY port is disabled. 2186 * Returns: 2187 * BCM_E_XXX 2188 * Notes: 2189 * Unlike bcmi_esw_portctl_enable_set(), this routine 2190 * only enables the PHY. It does not contain any logic 2191 * to handle loopback cases, MAC, or current port state. 2192 */ 2193 int 2194 bcmi_esw_portctrl_phy_enable_set(int unit, bcm_gport_t port, int enable) 2195 { 2196 #ifdef PORTMOD_SUPPORT 2197 int rv = BCM_E_NONE; 2198 portctrl_pport_t pport; 2199 2200 PORTCTRL_INIT_CHECK(unit); 2201 2202 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 2203 2204 PORT_LOCK(unit); 2205 rv = portmod_port_enable_set(unit, pport, 2206 PORTMOD_PORT_ENABLE_PHY, enable); 2207 PORT_UNLOCK(unit); 2208 2209 return rv; 2210 2211 #else /* PORTMOD_SUPPORT */ 2212 return BCM_E_UNAVAIL; 2213 #endif /* PORTMOD_SUPPORT */ 2214 } 2215 2216 2217 /* 2218 * Function: 2219 * bcmi_esw_portctrl_egress_queue_drain 2220 * Purpose: 2221 * Drain the egress queues without bringing down the port. 2222 * Parameters: 2223 * unit - (IN) Unit number. 2224 * port - (IN) Port number. 2225 * Returns: 2226 * BCM_E_XXX 2227 * Notes: 2228 */ 2229 int 2230 bcmi_esw_portctrl_egress_queue_drain(int unit, bcm_gport_t port) 2231 { 2232 #ifdef PORTMOD_SUPPORT 2233 int rv = BCM_E_NONE; 2234 portctrl_pport_t pport; 2235 2236 PORTCTRL_INIT_CHECK(unit); 2237 2238 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 2239 2240 PORT_LOCK(unit); 2241 rv = _bcm_esw_portctrl_egress_queue_drain(unit, port, pport); 2242 PORT_UNLOCK(unit); 2243 2244 return rv; 2245 2246 #else /* PORTMOD_SUPPORT */ 2247 return BCM_E_UNAVAIL; 2248 #endif /* PORTMOD_SUPPORT */ 2249 } 2250 2251 /* 2252 * Function: 2253 * bcmi_esw_portctrl_notify 2254 * Description: 2255 * Notify application the chip reconfigure failure from a auto-neg speed. 2256 * Parameters: 2257 * unit_vp - (IN) Device number. 2258 * event_vp - (IN) Port number. 2259 * port_vp - (IN) Port number. 2260 * arg1 - (IN) arg1 2261 * arg2 - (IN) arg2 2262 * Returns: 2263 * No 2264 * Notes: 2265 */ 2266 #ifdef PORTMOD_SUPPORT 2267 STATIC void 2268 bcmi_esw_portctrl_notify(void *unit_vp, void *event_vp, 2269 void *port_vp, void *arg1_vp, void *arg2_vp) 2270 { 2271 int unit, event, port, arg1, arg2; 2272 2273 unit = PTR_TO_INT(unit_vp); 2274 event = PTR_TO_INT(event_vp); 2275 port = PTR_TO_INT(port_vp); 2276 arg1 = PTR_TO_INT(arg1_vp); 2277 arg2 = PTR_TO_INT(arg2_vp); 2278 2279 (void)soc_event_generate(unit, event, port, arg1, arg2); 2280 } 2281 #endif /* PORTMOD_SUPPORT */ 2282 2283 /* 2284 * Function: 2285 * bcmi_esw_portctrl_update 2286 * Description: 2287 * Get port characteristics from PHY and program MAC to match. 2288 * Parameters: 2289 * unit - (IN) Device number. 2290 * port - (IN) Port number. 2291 * link - (IN) TRUE - process as link up. 2292 * FALSE - process as link down. 2293 * Returns: 2294 * BCM_E_XXX 2295 * Notes: 2296 * This function cannot hold the PORT_LOCK because it is called 2297 * by the linkscan thread. 2298 */ 2299 int 2300 bcmi_esw_portctrl_update(int unit, bcm_gport_t port, int link) 2301 { 2302 #ifdef PORTMOD_SUPPORT 2303 portctrl_pport_t pport; 2304 portmod_port_interface_config_t if_config; 2305 #ifdef PORTMOD_PM8X50_SUPPORT 2306 portmod_speed_config_t speed_config; 2307 portmod_dispatch_type_t pm_type = portmodDispatchTypeCount; 2308 int phy_port; 2309 #endif 2310 int config_speed; 2311 int speed, enable; 2312 int duplex; 2313 phymod_autoneg_status_t an_status; 2314 int is_legacy_phy, skip_spd_sync; 2315 int rv = BCM_E_NONE; 2316 2317 is_legacy_phy = 0; 2318 skip_spd_sync = 0; 2319 2320 PORTCTRL_INIT_CHECK(unit); 2321 2322 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 2323 2324 if (!link) { 2325 #ifdef SW_AUTONEG_SUPPORT 2326 rv = _bcm_esw_port_notify_link_down_evt(unit, port); 2327 if (BCM_FAILURE(rv)) { 2328 LOG_WARN(BSL_LS_BCM_PORT, 2329 (BSL_META_U(unit, 2330 "u=%d p=%d NOTIFY LINK DOWN EVT rv=%d\n"),unit, port, rv)); 2331 return rv; 2332 } 2333 #endif 2334 /*need to check if Pm8x50 Gen1/Gen2 400G AN workaround*/ 2335 /* if 400G AN enabled, bypass the port update */ 2336 #ifdef PORTMOD_PM8X50_SUPPORT 2337 /* first get physical port */ 2338 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 2339 /* get the PM type */ 2340 PORTMOD_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type)); 2341 if (pm_type == portmodDispatchTypePm8x50) { 2342 sal_memset(&an_status, 0, sizeof(an_status)); 2343 PORTMOD_IF_ERROR_RETURN 2344 (portmod_port_autoneg_status_get(unit, pport, &an_status)); 2345 if ((an_status.enabled) && (an_status.data_rate == 400000)) { 2346 return rv; 2347 } 2348 } 2349 #endif 2350 /* PHY is down. Disable the MAC. */ 2351 PORTMOD_IF_ERROR_RETURN 2352 ( _bcm_esw_portctrl_enable_set(unit, port, pport, 2353 PORTMOD_PORT_ENABLE_MAC, 0)); 2354 /* PHY link down event */ 2355 rv = (portmod_port_phy_link_down_event(unit, port)); 2356 if (BCM_FAILURE(rv) && (BCM_E_UNAVAIL != rv)) { 2357 LOG_WARN(BSL_LS_BCM_PORT, 2358 (BSL_META_U(unit, 2359 "u=%d p=%d portmod_port_phy_link_down_event rv=%d\n"),unit, port, rv)); 2360 return rv; 2361 } 2362 return BCM_E_NONE; 2363 } 2364 2365 /* PHY link up event */ 2366 rv = (portmod_port_phy_link_up_event(unit, port)); 2367 if (BCM_FAILURE(rv) && (BCM_E_UNAVAIL != rv)) { 2368 LOG_WARN(BSL_LS_BCM_PORT, 2369 (BSL_META_U(unit, 2370 "u=%d p=%d portmod_port_phy_link_up_event rv=%d\n"),unit, port, rv)); 2371 return rv; 2372 } 2373 2374 sal_memset(&an_status, 0, sizeof(an_status)); 2375 PORTMOD_IF_ERROR_RETURN 2376 (portmod_port_autoneg_status_get(unit, pport, &an_status)); 2377 2378 /* 2379 * Set MAC speed first, since for GTH ports, this will switch 2380 * between the 1000Mb/s or 10/100Mb/s MACs. 2381 */ 2382 if (!IS_HG_PORT(unit, port) || IS_GX_PORT(unit, port)) { 2383 #ifdef PORTMOD_PM8X50_SUPPORT 2384 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 2385 #ifdef BCM_TOMAHAWK3_SUPPORT 2386 /* Tomahawk 3's Management Port Macro requires a spacing between 2387 * the lanes, so even though the two management ports' physical 2388 * ports are 257 and 258, the lane needs to be the next one, 2389 * so logical port 118 being mapped to physical port 258 needs 2390 * to pass 259 to portmod because portmod only recognizes lane 2391 * 0 (physical port 257) and lane 2 (physial port 259). 2392 */ 2393 if (SOC_IS_TOMAHAWK3(unit) && (phy_port == 258)) { 2394 phy_port = 259; 2395 } 2396 #endif 2397 PORTMOD_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type)); 2398 if (pm_type == portmodDispatchTypePm8x50) { 2399 PORTMOD_IF_ERROR_RETURN 2400 (portmod_port_speed_config_get(unit, pport, &speed_config)); 2401 speed = speed_config.speed; 2402 } else 2403 #endif 2404 { 2405 PORTMOD_IF_ERROR_RETURN 2406 (portmod_port_interface_config_get(unit, pport, &if_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY)); 2407 speed = if_config.speed; 2408 2409 if (IS_HG_PORT(unit, port) && (if_config.speed < 5000)) { 2410 speed = 0; 2411 } 2412 } 2413 2414 PORTMOD_IF_ERROR_RETURN 2415 (portmod_port_duplex_get(unit, pport, &duplex)); 2416 2417 2418 #ifdef INCLUDE_FCMAP 2419 /* 2420 * In the FC-mode the switch and the system side of the PHY operates 2421 * at max_speed of the port in full duplex. 2422 */ 2423 if (soc_property_port_get(unit, port, spn_FCMAP_ENABLE, 0)) { 2424 speed = if_config.max_speed; 2425 duplex = 1; 2426 } 2427 #endif 2428 2429 if (an_status.enabled) { 2430 /* If AN is enabled, get both "line side speed" and 2431 * "SERDES speed(multiply number of lanes", then compare them. 2432 * Otherwise, set LINKUP flag and continue. 2433 */ 2434 int line_speed, serdes_speed; 2435 2436 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_speed_get( 2437 unit, port, &line_speed)); 2438 PORTMOD_IF_ERROR_RETURN(portmod_port_speed_get( 2439 unit, port, &serdes_speed)); 2440 2441 BCM_IF_ERROR_RETURN( 2442 portmod_port_is_legacy_ext_phy_present(unit, port, &is_legacy_phy)); 2443 if (is_legacy_phy) { 2444 skip_spd_sync = portmod_port_legacy_is_skip_spd_sync(unit, port); 2445 } 2446 2447 if ((line_speed != serdes_speed) && (!skip_spd_sync)) { 2448 #ifdef PORTMOD_PM8X50_SUPPORT 2449 if (pm_type == portmodDispatchTypePm8x50) { 2450 2451 speed_config.speed = speed; 2452 /* following is for 400G autoneg only */ 2453 /* if 400G AN< bypass port update */ 2454 if (speed == 400000) { 2455 return BCM_E_NONE; 2456 } 2457 } else 2458 #endif 2459 { 2460 if_config.speed = serdes_speed; 2461 } 2462 } 2463 if_config.flags |= PHYMOD_INTF_F_UPDATE_SPEED_LINKUP; 2464 } 2465 2466 /* 1. Assuming Autoneg process is still running. 2467 * We should not call speed_set function because speed_set involves 2468 * disable AN, and IP/EP/MMU/TDM reconfiguration. 2469 * just call _bcm_esw_portctrl_interface_config_set to update interface 2470 * 2. For PHY devices that has line and system side operate at different speeds 2471 * speed sync between line and system side is not required. 2472 */ 2473 #ifdef PORTMOD_PM8X50_SUPPORT 2474 if (pm_type == portmodDispatchTypePm8x50) { 2475 config_speed = speed_config.speed; 2476 } else 2477 #endif 2478 { 2479 config_speed = if_config.speed; 2480 } 2481 if (((config_speed != speed) || (((an_status.enabled) && (an_status.locked)))) && 2482 (!skip_spd_sync) && link) { 2483 PORTMOD_IF_ERROR_RETURN 2484 (portmod_port_enable_get(unit, port, PORTMOD_PORT_ENABLE_MAC, 2485 &enable)); 2486 if (enable) { 2487 /* Disable MAC */ 2488 BCM_IF_ERROR_RETURN 2489 (_bcm_esw_portctrl_enable_set(unit, port, pport, 2490 PORTMOD_PORT_ENABLE_MAC, 0)); 2491 } 2492 2493 /* reconfigure chip (TDM/IP/EP/MMU) */ 2494 rv = _bcm_esw_portctrl_speed_chip_reconfigure(unit, port, speed); 2495 if (BCM_FAILURE(rv) && (an_status.enabled)) { 2496 sal_dpc(bcmi_esw_portctrl_notify, 2497 INT_TO_PTR(unit), 2498 INT_TO_PTR(SOC_SWITCH_EVENT_AUTONEG_SPEED_ERROR), 2499 INT_TO_PTR(port), 2500 INT_TO_PTR(speed), 2501 INT_TO_PTR(rv)); 2502 return rv; 2503 } 2504 #ifdef PORTMOD_PM8X50_SUPPORT 2505 if (pm_type == portmodDispatchTypePm8x50) { 2506 /* Do nothing for PM8x50. The PM does not support 2507 * interface_config_set 2508 */ 2509 } else 2510 #endif 2511 { 2512 if_config.speed = speed; 2513 PORTMOD_IF_ERROR_RETURN 2514 (_bcm_esw_portctrl_interface_config_set(unit, port, pport, 2515 &if_config, 0)); 2516 } 2517 2518 if (enable) { 2519 /* Re-enable port */ 2520 BCM_IF_ERROR_RETURN 2521 (_bcm_esw_portctrl_enable_set(unit, port, pport, 2522 PORTMOD_PORT_ENABLE_MAC, 2523 1)); 2524 } 2525 } 2526 2527 PORTMOD_IF_ERROR_RETURN 2528 (portmod_port_duplex_set(unit, pport, duplex)); 2529 } else { 2530 duplex = 1; 2531 } 2532 2533 /* 2534 * If autonegotiating, check the negotiated PAUSE values, and program 2535 * MACs accordingly. Link can also be achieved thru parallel detect. 2536 * In this case, it should be treated as in the forced mode. 2537 */ 2538 #ifdef PORTMOD_PM8X50_SUPPORT 2539 if (pm_type == portmodDispatchTypePm8x50) { 2540 /* Do nothing for PM8x50. Pause settings for AN will be taken care 2541 * inside Portmod. 2542 */ 2543 } else 2544 #endif 2545 { 2546 if (an_status.enabled && an_status.locked) { 2547 bcm_port_ability_t local_advert, remote_advert; 2548 int tx_pause, rx_pause; 2549 portmod_pause_control_t pause_control; 2550 2551 BCM_IF_ERROR_RETURN 2552 (bcmi_esw_portctrl_ability_advert_get(unit, port, 2553 &local_advert, NULL)); 2554 BCM_IF_ERROR_RETURN 2555 (bcmi_esw_portctrl_ability_remote_get(unit, port, 2556 &remote_advert, NULL)); 2557 2558 /* 2559 * IEEE 802.3 Flow Control Resolution. 2560 * Please see $SDK/doc/pause-resolution.txt for more information. 2561 */ 2562 if (duplex) { 2563 tx_pause = 2564 ((remote_advert.pause & SOC_PA_PAUSE_RX) && 2565 (local_advert.pause & SOC_PA_PAUSE_RX)) || 2566 ((remote_advert.pause & SOC_PA_PAUSE_RX) && 2567 !(remote_advert.pause & SOC_PA_PAUSE_TX) && 2568 (local_advert.pause & SOC_PA_PAUSE_TX)); 2569 2570 rx_pause = 2571 ((remote_advert.pause & SOC_PA_PAUSE_RX) && 2572 (local_advert.pause & SOC_PA_PAUSE_RX)) || 2573 ((local_advert.pause & SOC_PA_PAUSE_RX) && 2574 (remote_advert.pause & SOC_PA_PAUSE_TX) && 2575 !(local_advert.pause & SOC_PA_PAUSE_TX)); 2576 } else { 2577 rx_pause = tx_pause = 0; 2578 } 2579 2580 PORTMOD_IF_ERROR_RETURN 2581 (portmod_port_pause_control_get(unit, pport, &pause_control)); 2582 pause_control.rx_enable = rx_pause; 2583 pause_control.tx_enable = tx_pause; 2584 PORTMOD_IF_ERROR_RETURN 2585 (portmod_port_pause_control_set(unit, pport, &pause_control)); 2586 } 2587 } 2588 2589 /* Enable the MAC */ 2590 BCM_IF_ERROR_RETURN 2591 (_bcm_esw_portctrl_enable_set(unit, port, pport, 2592 PORTMOD_PORT_ENABLE_MAC, 1)); 2593 2594 2595 /* When a link comes up, hardware will not update the 2596 * LINK_STATUS register until software has toggled the 2597 * the LAG_FAILOVER_CONFIG.LINK_STATUS_UP field. 2598 * When a link goes down, hardware will update the 2599 * LINK_STATUS register without software intervention. 2600 */ 2601 /* Toggle link_status_up bit to notify IPIPE on link up */ 2602 if (!IS_QSGMII_PORT(unit, pport)) { 2603 PORTMOD_IF_ERROR_RETURN 2604 (portmod_port_lag_failover_status_toggle(unit, pport)); 2605 } 2606 2607 return BCM_E_NONE; 2608 2609 #else /* PORTMOD_SUPPORT */ 2610 return BCM_E_UNAVAIL; 2611 #endif /* PORTMOD_SUPPORT */ 2612 } 2613 2614 2615 /* 2616 * Function: 2617 * bcmi_esw_portctrl_fault_get 2618 * Description: 2619 * Get link fault type. 2620 * Parameters: 2621 * unit - (IN) Device number. 2622 * port - (IN) Port number. 2623 * flags - (OUT) flags to indicate fault type. 2624 * Returns: 2625 * BCM_E_XXX 2626 */ 2627 int 2628 bcmi_esw_portctrl_fault_get(int unit, bcm_gport_t port, uint32 *flags) 2629 { 2630 #ifdef PORTMOD_SUPPORT 2631 int rv = BCM_E_NONE; 2632 portctrl_pport_t pport; 2633 int local_fault = 0, remote_fault = 0; 2634 portmod_local_fault_control_t local_control; 2635 portmod_remote_fault_control_t remote_control; 2636 2637 PORTCTRL_INIT_CHECK(unit); 2638 2639 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 2640 2641 PORT_LOCK(unit); 2642 2643 /* 2644 * NOTE: 2645 * The PortMod functions portmod_port_local/remote_fault_status_get() 2646 * only return the fault status field values and do not check 2647 * for the fault disable fields. 2648 * 2649 * In order to maintain the same API behavior, 2650 * we need to call additional PortMod functions to check 2651 * the fault disable fields. 2652 */ 2653 2654 rv = portmod_port_local_fault_control_get(unit, pport, &local_control); 2655 if (PORTMOD_SUCCESS(rv)) { 2656 if (local_control.enable) { 2657 rv = portmod_port_local_fault_status_get(unit, pport, 2658 &local_fault); 2659 } 2660 } 2661 2662 if (PORTMOD_SUCCESS(rv)) { 2663 rv = portmod_port_remote_fault_control_get(unit, pport, 2664 &remote_control); 2665 if (PORTMOD_SUCCESS(rv)) { 2666 if (remote_control.enable) { 2667 rv = portmod_port_remote_fault_status_get(unit, pport, 2668 &remote_fault); 2669 } 2670 } 2671 } 2672 2673 PORT_UNLOCK(unit); 2674 2675 *flags = 0; 2676 if (local_fault) { 2677 *flags |= BCM_PORT_FAULT_LOCAL; 2678 } 2679 if (remote_fault) { 2680 *flags |= BCM_PORT_FAULT_REMOTE; 2681 } 2682 2683 return rv; 2684 2685 #else /* PORTMOD_SUPPORT */ 2686 return BCM_E_UNAVAIL; 2687 #endif /* PORTMOD_SUPPORT */ 2688 } 2689 2690 2691 /* 2692 * Function: 2693 * bcmi_esw_portctrl_link_fault_get 2694 * Description: 2695 * Get the fault and remote fault status. 2696 * Parameters: 2697 * unit - (IN) Device number. 2698 * port - (IN) Port number. 2699 * local_fault - (OUT) Local fault status 2700 * remote_fault - (OUT) Remote fault status 2701 * Returns: 2702 * BCM_E_XXX 2703 */ 2704 int 2705 bcmi_esw_portctrl_link_fault_get(int unit, bcm_gport_t port, 2706 int *local_fault, int *remote_fault) 2707 { 2708 #ifdef PORTMOD_SUPPORT 2709 int rv = BCM_E_NONE; 2710 portctrl_pport_t pport; 2711 2712 PORTCTRL_INIT_CHECK(unit); 2713 2714 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 2715 2716 PORT_LOCK(unit); 2717 rv = portmod_port_local_fault_status_get(unit, pport, local_fault); 2718 if (PORTMOD_SUCCESS(rv)) { 2719 rv = portmod_port_remote_fault_status_get(unit, pport, remote_fault); 2720 } 2721 PORT_UNLOCK(unit); 2722 2723 return rv; 2724 2725 #else /* PORTMOD_SUPPORT */ 2726 return BCM_E_UNAVAIL; 2727 #endif /* PORTMOD_SUPPORT */ 2728 } 2729 2730 2731 /* 2732 * Function: 2733 * bcmi_esw_portctrl_loopback_get 2734 * Purpose: 2735 * Recover the current loopback operation for the specified port. 2736 * Parameters: 2737 * unit - (IN) Unit number. 2738 * port - (IN) Port number. 2739 * loopback - (OUT) One of: 2740 * BCM_PORT_LOOPBACK_NONE 2741 * BCM_PORT_LOOPBACK_MAC 2742 * BCM_PORT_LOOPBACK_PHY 2743 * Returns: 2744 * BCM_E_NONE 2745 * BCM_E_XXX 2746 */ 2747 int 2748 bcmi_esw_portctrl_loopback_get(int unit, bcm_gport_t port, int *loopback) 2749 { 2750 #ifdef PORTMOD_SUPPORT 2751 int rv = BCM_E_NONE; 2752 portctrl_pport_t pport; 2753 int i = 0, enable = 0; 2754 int phy_lane = -1; 2755 int phyn = 0, sys_side = 0; 2756 bcm_port_t local_port = -1; 2757 uint32 phy_lb = 0; 2758 2759 portmod_loopback_mode_t portmod_lb_modes[] = { 2760 portmodLoopbackMacOuter, 2761 portmodLoopbackPhyGloopPMD, 2762 portmodLoopbackPhyGloopPCS, 2763 portmodLoopbackPhyRloopPMD 2764 /* portmodLoopbackPhyRloopPCS - no support */ 2765 }; 2766 int bcm_lb_modes[] = { 2767 BCM_PORT_LOOPBACK_MAC, 2768 BCM_PORT_LOOPBACK_PHY, 2769 BCM_PORT_LOOPBACK_PHY, 2770 BCM_PORT_LOOPBACK_PHY_REMOTE, 2771 BCM_PORT_LOOPBACK_PHY_REMOTE 2772 }; 2773 2774 PORTCTRL_INIT_CHECK(unit); 2775 2776 BCM_IF_ERROR_RETURN( 2777 _bcm_esw_port_gport_phyn_validate(unit, port, 2778 &local_port, &phyn, 2779 &phy_lane, &sys_side)); 2780 2781 if (local_port != -1) { 2782 port = local_port; 2783 } 2784 2785 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 2786 2787 if (local_port != -1) { 2788 PORT_LOCK(unit); 2789 rv = portmod_port_redirect_loopback_get(unit, pport, phyn, 2790 phy_lane, sys_side, 2791 &phy_lb); 2792 PORT_UNLOCK(unit); 2793 if (PORTMOD_FAILURE(rv)) { 2794 LOG_VERBOSE(BSL_LS_BCM_PORT, 2795 (BSL_META_UP(unit, port, 2796 "Redirect loopback get failed: p=%d, rv=%d"), 2797 port, rv)); 2798 return rv; 2799 } 2800 } 2801 2802 *loopback = BCM_PORT_LOOPBACK_NONE; 2803 2804 for (i = 0; i < COUNTOF(portmod_lb_modes); i++) { 2805 PORT_LOCK(unit); 2806 rv = portmod_port_loopback_get(unit, pport, 2807 portmod_lb_modes[i], &enable); 2808 PORT_UNLOCK(unit); 2809 2810 if (PORTMOD_FAILURE(rv)) { 2811 LOG_VERBOSE(BSL_LS_BCM_PORT, 2812 (BSL_META_UP(unit, port, 2813 "Loopback get failed: p=%d, rv=%d"), 2814 port, rv)); 2815 return rv; 2816 } 2817 2818 if (enable) { 2819 *loopback = bcm_lb_modes[i]; 2820 break; 2821 } 2822 } 2823 2824 if (*loopback != BCM_PORT_LOOPBACK_MAC && phy_lb) { 2825 *loopback = BCM_PORT_LOOPBACK_PHY; 2826 } 2827 2828 return BCM_E_NONE; 2829 2830 #else /* PORTMOD_SUPPORT */ 2831 return BCM_E_UNAVAIL; 2832 #endif /* PORTMOD_SUPPORT */ 2833 } 2834 2835 2836 /* 2837 * Function: 2838 * bcmi_esw_portctrl_loopback_set 2839 * Purpose: 2840 * Set loopback mode for the specified port. 2841 * Parameters: 2842 * unit - StrataSwitch Unit #. 2843 * port - StrataSwitch port #. 2844 * loopback - one of: 2845 * BCM_PORT_LOOPBACK_NONE 2846 * BCM_PORT_LOOPBACK_MAC 2847 * BCM_PORT_LOOPBACK_PHY 2848 * Returns: 2849 * BCM_E_NONE 2850 * BCM_E_XXX 2851 */ 2852 int 2853 bcmi_esw_portctrl_loopback_set(int unit, bcm_gport_t port, int loopback) 2854 { 2855 #ifdef PORTMOD_SUPPORT 2856 int rv = BCM_E_NONE, link = TRUE; 2857 portctrl_pport_t pport; 2858 int lpbk_type; 2859 int phy_lane = -1; 2860 int phyn = 0, sys_side = 0; 2861 int flags = 0, is_loopback_set = 0; 2862 int mac_lpbk = 0, phy_lpbk = 0, rmt_lpbk = 0; 2863 bcm_port_t local_port = -1; 2864 int tmp_flags=0, soc_flag = 0; 2865 soc_persist_t *sop = SOC_PERSIST(unit); 2866 portmod_dispatch_type_t pm_type = portmodDispatchTypeCount; 2867 2868 PORTCTRL_INIT_CHECK(unit); 2869 2870 BCM_IF_ERROR_RETURN( 2871 _bcm_esw_port_gport_phyn_validate(unit, port, 2872 &local_port, &phyn, 2873 &phy_lane, &sys_side)); 2874 2875 if (local_port != -1) { 2876 port = local_port; 2877 } 2878 2879 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 2880 2881 #ifdef BCM_RCPU_SUPPORT 2882 if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) { 2883 return BCM_E_PORT; 2884 } 2885 #endif /* BCM_RCPU_SUPPORT */ 2886 2887 /* get current loopback state. Do nothing if the current state matches requested state */ 2888 if (local_port == -1) { 2889 rv = portmod_port_loopback_get(unit, pport, portmodLoopbackMacOuter, &mac_lpbk); 2890 if (PORTMOD_FAILURE(rv)) return(rv); 2891 2892 rv = portmod_port_loopback_get(unit, pport, portmodLoopbackPhyGloopPCS, &phy_lpbk); 2893 if (PORTMOD_FAILURE(rv)) return(rv); 2894 2895 rv = portmod_port_loopback_get(unit, pport, portmodLoopbackPhyRloopPMD, &rmt_lpbk); 2896 if (PORTMOD_FAILURE(rv)) return(rv); 2897 2898 if (((loopback == BCM_PORT_LOOPBACK_MAC) && mac_lpbk) || 2899 ((loopback == BCM_PORT_LOOPBACK_PHY) && phy_lpbk) || 2900 ((loopback == BCM_PORT_LOOPBACK_PHY_REMOTE) && rmt_lpbk) || 2901 ((loopback == BCM_PORT_LOOPBACK_NONE) && !mac_lpbk && !phy_lpbk && !rmt_lpbk)) { 2902 2903 /* current state matches with requested state - dont need to do anything */ 2904 LOG_VERBOSE(BSL_LS_BCM_PORT, (BSL_META_UP(unit, port, "Port%d : Loopback Command Skip (State Match)\n"), port)); 2905 is_loopback_set = 1; 2906 } 2907 } 2908 2909 PORTMOD_PORT_ENABLE_PHY_SET(flags); 2910 PORT_LOCK(unit); 2911 rv = portmod_port_enable_get(unit, pport, flags, &link); 2912 PORT_UNLOCK(unit); 2913 2914 if (PORTMOD_FAILURE(rv)) { 2915 LOG_VERBOSE(BSL_LS_BCM_PORT, 2916 (BSL_META_UP(unit, port, 2917 "Get port enable failed: p=%d, rv=%d"), 2918 port, rv)); 2919 } 2920 2921 if (TRUE == link) { 2922 PORT_LOCK(unit); 2923 2924 if (SOC_PBMP_MEMBER(sop->lc_pbm_override_ports, port)) { 2925 if(!SOC_PBMP_MEMBER(sop->lc_pbm_override_link, port)) { 2926 link = FALSE; 2927 } 2928 } 2929 2930 PORT_UNLOCK(unit); 2931 } 2932 2933 /* 2934 * Always force link before changing hardware to avoid 2935 * race with the linkscan thread. 2936 */ 2937 if (!(loopback == BCM_PORT_LOOPBACK_NONE)) { 2938 rv = _bcm_esw_link_force(unit, 0 /*flags*/, port, TRUE, FALSE); 2939 2940 if(rv == BCM_E_NONE) { 2941 /* Force the update function to be called so the state is 2942 updated */ 2943 if (_soc_linkscan_phy_flags_test(unit, port, PHY_FLAGS_EXTERNAL_PHY)) { 2944 rv = bcm_esw_port_update(unit, port, TRUE); 2945 } 2946 } 2947 } 2948 2949 if (BCM_FAILURE(rv)) { 2950 return (rv); 2951 } 2952 2953 rv = portmod_port_pm_type_get(unit, port, &port, &pm_type); 2954 if (rv != BCM_E_NONE) { 2955 return rv; 2956 } 2957 2958 if (!is_loopback_set) { 2959 PORT_LOCK(unit); 2960 2961 if (local_port == -1) { 2962 lpbk_type = portmodLoopbackCount; 2963 #ifdef PORTMOD_PM12X10_SUPPORT 2964 if (pm_type == portmodDispatchTypePm12x10){ 2965 soc_flag = 1; 2966 } 2967 #endif 2968 /* MAC loopback needs to clear the credits of 2969 * EDB at the stage of soft_reset of clmac in 2970 * portmod_port_loopback_set (PM4x25) 2971 */ 2972 if (soc_flag) { 2973 if ((loopback == BCM_PORT_LOOPBACK_MAC) || 2974 ((loopback != BCM_PORT_LOOPBACK_MAC) && (mac_lpbk == BCM_PORT_LOOPBACK_MAC))) { 2975 rv = soc_egress_enable(unit, pport, 0); 2976 if (BCM_FAILURE(rv)) { 2977 PORT_UNLOCK(unit); 2978 return rv; 2979 } 2980 rv = soc_port_credit_reset(unit, pport); 2981 if (BCM_FAILURE(rv)) { 2982 PORT_UNLOCK(unit); 2983 return rv; 2984 } 2985 rv = soc_egress_enable(unit, pport, 1); 2986 if (BCM_FAILURE(rv)) { 2987 PORT_UNLOCK(unit); 2988 return rv; 2989 } 2990 } 2991 } 2992 2993 /* clear if any loopback was set prior */ 2994 if (BCM_SUCCESS(rv) && mac_lpbk) { 2995 rv = portmod_port_loopback_set(unit, pport, 2996 portmodLoopbackMacOuter, 0); 2997 } 2998 if (BCM_SUCCESS(rv) && phy_lpbk) { 2999 rv = portmod_port_loopback_set(unit, pport, 3000 portmodLoopbackPhyGloopPCS, 0); 3001 } 3002 if (BCM_SUCCESS(rv) && rmt_lpbk) { 3003 rv = portmod_port_loopback_set(unit, pport, 3004 portmodLoopbackPhyRloopPMD, 0); 3005 } 3006 3007 if (BCM_FAILURE(rv)) { 3008 PORT_UNLOCK(unit); 3009 return (rv); 3010 } 3011 3012 if (loopback == BCM_PORT_LOOPBACK_MAC) { 3013 lpbk_type = portmodLoopbackMacOuter; 3014 } else if (loopback == BCM_PORT_LOOPBACK_PHY){ 3015 lpbk_type = portmodLoopbackPhyGloopPCS; 3016 } else if (loopback == BCM_PORT_LOOPBACK_PHY_REMOTE) { 3017 lpbk_type = portmodLoopbackPhyRloopPMD; 3018 } 3019 3020 if (lpbk_type != portmodLoopbackCount) { 3021 rv = portmod_port_loopback_set(unit, pport, lpbk_type, 1); 3022 } 3023 } else { 3024 rv = portmod_port_redirect_loopback_set(unit, pport, 3025 phyn, phy_lane, sys_side, 3026 (loopback == BCM_PORT_LOOPBACK_PHY)? 1 : 0); 3027 } 3028 PORT_UNLOCK(unit); /* unlock before link call */ 3029 } 3030 3031 flags = 0; 3032 PORTMOD_PORT_ENABLE_PHY_SET(flags); 3033 PORTMOD_PORT_ENABLE_MAC_SET(flags); 3034 3035 if ((loopback == BCM_PORT_LOOPBACK_NONE) || PORTMOD_FAILURE(rv)) { 3036 _bcm_esw_link_force(unit, 0 /*flags*/, port, FALSE, DONT_CARE); 3037 3038 if ((FALSE == link) && (loopback == BCM_PORT_LOOPBACK_NONE)) { 3039 PORT_LOCK(unit); 3040 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, flags, 0); 3041 PORT_UNLOCK(unit); 3042 } else { 3043 /* Phy need to be re-enable when the port is enabled and 3044 clearing the loopback. */ 3045 tmp_flags = 0; 3046 PORTMOD_PORT_ENABLE_PHY_SET(tmp_flags); 3047 PORTMOD_IF_ERROR_RETURN 3048 (portmod_port_enable_set(unit, port, tmp_flags, 1)); 3049 } 3050 } else { 3051 #ifdef PORTMOD_PM8X50_SUPPORT 3052 if (pm_type == portmodDispatchTypePm8x50){ 3053 PORTMOD_PORT_ENABLE_PHY_CLR(flags); 3054 } 3055 #endif 3056 PORT_LOCK(unit); 3057 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, flags, 1); 3058 3059 /* If the port is disabled and apply loopback, phy need to 3060 be disabled. */ 3061 if(FALSE == link){ 3062 tmp_flags = 0; 3063 PORTMOD_PORT_ENABLE_PHY_SET(tmp_flags); 3064 rv = portmod_port_enable_set(unit, port, tmp_flags, 0); 3065 if (PORTMOD_FAILURE(rv)) { 3066 PORT_UNLOCK(unit); 3067 return rv; 3068 } 3069 } 3070 3071 PORT_UNLOCK(unit); 3072 3073 if (PORTMOD_SUCCESS(rv)) { 3074 /* Make sure that the link status is updated only after the 3075 * MAC is enabled so that link_mask2 is set before the 3076 * calling thread synchronizes with linkscan thread in 3077 * _bcm_link_force call. 3078 * If the link is forced before MAC is enabled, there could 3079 * be a race condition in _soc_link_update where linkscan 3080 * may use an old view of link_mask2 and override the 3081 * EPC_LINK_BMAP after the mac_enable_set updates 3082 * link_mask2 and EPC_LINK_BMAP. 3083 */ 3084 if (loopback == BCM_PORT_LOOPBACK_MAC) { 3085 rv = _bcm_esw_link_force(unit, 0 /*flags*/, port, TRUE, TRUE); 3086 } else { 3087 rv = _bcm_esw_link_force(unit, 0 /*flags*/, port, TRUE, link); 3088 } 3089 } 3090 } 3091 3092 LOG_INFO(BSL_LS_BCM_PORT, 3093 (BSL_META_UP(unit, port, 3094 "bcm_port_loopback_set: p=%d lb=%d rv=%d\n"), 3095 port, loopback, rv)); 3096 3097 return rv; 3098 3099 #else /* PORTMOD_SUPPORT */ 3100 return BCM_E_UNAVAIL; 3101 #endif /* PORTMOD_SUPPORT */ 3102 } 3103 3104 /* 3105 * Function: 3106 * bcmi_esw_portctrl_speed_get 3107 * Purpose: 3108 * Getting the speed of the port 3109 * Parameters: 3110 * unit - StrataSwitch Unit #. 3111 * port - StrataSwitch port #. 3112 * speed - (OUT) Value in megabits/sec (10, 100, etc) 3113 * Returns: 3114 * BCM_E_NONE 3115 * BCM_E_XXX 3116 * Notes: 3117 * If port is in MAC loopback, the speed of the loopback is returned. 3118 */ 3119 int 3120 bcmi_esw_portctrl_speed_get(int unit, bcm_gport_t port, int *speed) 3121 { 3122 #ifdef PORTMOD_SUPPORT 3123 int rv = BCM_E_NONE, valid = 0; 3124 portctrl_pport_t pport; 3125 portmod_port_interface_config_t portmod_if_config; 3126 #ifdef PORTMOD_PM8X50_SUPPORT 3127 portmod_speed_config_t portmod_sp_config; 3128 portmod_dispatch_type_t pm_type; 3129 int phy_port; 3130 #endif 3131 3132 PORTCTRL_INIT_CHECK(unit); 3133 3134 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 3135 3136 BCM_IF_ERROR_RETURN(portmod_port_is_valid(unit, pport, &valid)); 3137 if (!valid) { 3138 return BCM_E_PORT; 3139 } 3140 3141 #ifdef PORTMOD_PM8X50_SUPPORT 3142 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 3143 #ifdef BCM_TOMAHAWK3_SUPPORT 3144 /* Tomahawk 3's Management Port Macro requires a spacing between 3145 * the lanes, so even though the two management ports' physical 3146 * ports are 257 and 258, the lane needs to be the next one, 3147 * so logical port 118 being mapped to physical port 258 needs 3148 * to pass 259 to portmod because portmod only recognizes lane 3149 * 0 (physical port 257) and lane 2 (physial port 259). 3150 */ 3151 if (SOC_IS_TOMAHAWK3(unit) && (phy_port == 258)) { 3152 phy_port = 259; 3153 } 3154 #endif 3155 3156 BCM_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type)); 3157 if (pm_type == portmodDispatchTypePm8x50) { 3158 PORT_LOCK(unit); 3159 rv = portmod_port_speed_config_get(unit, pport, &portmod_sp_config); 3160 PORT_UNLOCK(unit); 3161 3162 if (PORTMOD_SUCCESS(rv)) { 3163 *speed = portmod_sp_config.speed; 3164 } 3165 LOG_INFO(BSL_LS_BCM_PORT, 3166 (BSL_META_UP(unit, port, 3167 "Get port speed: p=%d speed=%d rv=%d\n"), 3168 port, BCM_SUCCESS(rv) ? *speed : 0, rv)); 3169 3170 return rv; 3171 } 3172 #endif 3173 3174 3175 PORT_LOCK(unit); 3176 rv = portmod_port_interface_config_get(unit, pport, &portmod_if_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY); 3177 PORT_UNLOCK(unit); 3178 3179 if (PORTMOD_SUCCESS(rv)) { 3180 *speed = portmod_if_config.speed; 3181 3182 if (IS_HG_PORT(unit, port) && *speed < 5000) { 3183 *speed = 0; 3184 } 3185 } 3186 3187 LOG_INFO(BSL_LS_BCM_PORT, 3188 (BSL_META_UP(unit, port, 3189 "Get port speed: p=%d speed=%d rv=%d\n"), 3190 port, BCM_SUCCESS(rv) ? *speed : 0, rv)); 3191 3192 return rv; 3193 3194 #else /* PORTMOD_SUPPORT */ 3195 return BCM_E_UNAVAIL; 3196 #endif /* PORTMOD_SUPPORT */ 3197 } 3198 3199 STATIC int 3200 bcmi_esw_portctrl_speed_ability_local_max(int unit, bcm_gport_t port, 3201 int *speed_max) 3202 { 3203 #ifdef PORTMOD_SUPPORT 3204 bcm_port_speed_ability_t *abilities; 3205 int actual_num_ability = 0, max = 0; 3206 int i, rv; 3207 3208 abilities = sal_alloc(PORTCTRL_SPEED_ABILITY_MAX_COUNT * 3209 sizeof(bcm_port_speed_ability_t), "speed abilities"); 3210 if (NULL == abilities) { 3211 return BCM_E_MEMORY; 3212 } 3213 3214 rv = bcmi_esw_portctrl_speed_ability_local_get(unit, 3215 port, 3216 PORTCTRL_SPEED_ABILITY_MAX_COUNT, 3217 abilities, 3218 &actual_num_ability); 3219 if (BCM_FAILURE(rv)) { 3220 goto cleanup; 3221 } 3222 3223 for (i = 0; i < actual_num_ability; i++) { 3224 if (abilities[i].speed > max) { 3225 max = abilities[i].speed; 3226 } 3227 } 3228 3229 *speed_max = max; 3230 3231 cleanup: 3232 if (NULL != abilities) { 3233 sal_free(abilities); 3234 } 3235 3236 return BCM_E_NONE; 3237 #else /* Portmod Support */ 3238 return BCM_E_UNAVAIL; 3239 #endif /* Portmod Support */ 3240 } 3241 3242 /* 3243 * Function: 3244 * bcmi_esw_portctrl_speed_max 3245 * Purpose: 3246 * Getting the maximum speed of the port 3247 * Parameters: 3248 * unit - StrataSwitch Unit #. 3249 * port - StrataSwitch port #. 3250 * speed - (OUT) Value in megabits/sec (10, 100, etc) 3251 * Returns: 3252 * BCM_E_NONE 3253 * BCM_E_XXX 3254 */ 3255 int 3256 bcmi_esw_portctrl_speed_max(int unit, bcm_gport_t port, int *speed) 3257 { 3258 #ifdef PORTMOD_SUPPORT 3259 int rv; 3260 bcm_port_ability_t ability; 3261 portctrl_pport_t pport; 3262 #ifdef PORTMOD_PM8X50_SUPPORT 3263 portmod_dispatch_type_t pm_type; 3264 int phy_port; 3265 #endif 3266 3267 PORTCTRL_INIT_CHECK(unit); 3268 3269 sal_memset(&ability, 0, sizeof(bcm_port_ability_t)); 3270 3271 if (speed == NULL) { 3272 return (BCM_E_PARAM); 3273 } 3274 3275 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 3276 3277 #ifdef PORTMOD_PM8X50_SUPPORT 3278 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 3279 #ifdef BCM_TOMAHAWK3_SUPPORT 3280 /* Tomahawk 3's Management Port Macro requires a spacing between 3281 * the lanes, so even though the two management ports' physical 3282 * ports are 257 and 258, the lane needs to be the next one, 3283 * so logical port 118 being mapped to physical port 258 needs 3284 * to pass 259 to portmod because portmod only recognizes lane 3285 * 0 (physical port 257) and lane 2 (physial port 259). 3286 */ 3287 if (SOC_IS_TOMAHAWK3(unit) && (phy_port == 258)) { 3288 phy_port = 259; 3289 } 3290 #endif 3291 BCM_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type)); 3292 3293 if (pm_type == portmodDispatchTypePm8x50) { 3294 rv = bcmi_esw_portctrl_speed_ability_local_max(unit, port, 3295 speed); 3296 } else 3297 #endif 3298 { 3299 3300 rv = bcmi_esw_portctrl_ability_get(unit, port, &ability, NULL); 3301 3302 if (BCM_SUCCESS(rv)) { 3303 { 3304 *speed = BCM_PORT_ABILITY_SPEED_MAX(ability.speed_full_duplex | 3305 ability.speed_half_duplex); 3306 } 3307 3308 if (IS_HG_PORT(unit, port)) { 3309 if (SOC_INFO(unit).port_speed_max[port]) { 3310 switch (*speed) { 3311 case 10000: 3312 case 20000: 3313 case 40000: 3314 case 100000: 3315 case 120000: 3316 *speed = SOC_INFO(unit).port_speed_max[port]; 3317 break; 3318 default: 3319 break; 3320 } 3321 } 3322 } else { 3323 switch (*speed) { 3324 case 11000: 3325 case 21000: 3326 case 42000: 3327 case 106000: 3328 case 127000: 3329 *speed = SOC_INFO(unit).port_speed_max[port]; 3330 break; 3331 case 13000: 3332 case 16000: 3333 if(SOC_IS_TITAN2PLUS(unit)){ 3334 *speed = SOC_INFO(unit).port_speed_max[port]; 3335 } 3336 break; 3337 default: 3338 break; 3339 } 3340 } 3341 3342 } else { 3343 *speed = 0; 3344 } 3345 } 3346 3347 LOG_INFO(BSL_LS_BCM_PORT, 3348 (BSL_META_UP(unit, port, 3349 "Max port speed: p=%d speed=%d rv=%d\n"), 3350 port, *speed, rv)); 3351 3352 return rv; 3353 3354 #else /* PORTMOD_SUPPORT */ 3355 return BCM_E_UNAVAIL; 3356 #endif /* PORTMOD_SUPPORT */ 3357 } 3358 3359 #ifdef PORTMOD_SUPPORT 3360 3361 /* 3362 * Function: 3363 * _bcm_esw_portctrl_speed_validate 3364 * Purpose: 3365 * Validate the speed change can be supported 3366 * Parameters: 3367 * unit - SOC unit number 3368 * port - bcm_gport_t port number 3369 * speed - port speed 3370 * Returns: 3371 * BCM_E_XXX 3372 */ 3373 STATIC int 3374 _bcm_esw_portctrl_speed_validate(int unit, bcm_gport_t port, int speed) 3375 { 3376 bcm_port_ability_t port_ability, requested_ability; 3377 int mode = -1; 3378 int rv; 3379 int max_speed; 3380 3381 /* PM8x50 ports will have their speed config checked in portmod */ 3382 if (IS_CD_PORT(unit, port)) { 3383 if (BCM_ESW_PORT_DRV(unit)!= NULL) { 3384 if (BCM_ESW_PORT_DRV(unit)->device_speed_check != NULL) { 3385 3386 rv = (BCM_ESW_PORT_DRV(unit)->device_speed_check(unit, 3387 speed, -1)); 3388 if (BCM_FAILURE(rv)) { 3389 return rv; 3390 } 3391 } 3392 } 3393 3394 /* On a speed change validate, don't allow higher speed than 3395 * port_speed_max. User needs to flex up */ 3396 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_speed_ability_local_max( 3397 unit, port, &max_speed)); 3398 if (speed > max_speed) { 3399 return BCM_E_CONFIG; 3400 } 3401 return BCM_E_NONE; 3402 } 3403 3404 sal_memset(&port_ability, 0, sizeof(bcm_port_ability_t)); 3405 sal_memset(&requested_ability, 0, sizeof(bcm_port_ability_t)); 3406 3407 BCM_IF_ERROR_RETURN 3408 (bcmi_esw_portctrl_ability_get(unit, port, &port_ability, NULL)); 3409 BCM_IF_ERROR_RETURN 3410 (bcmi_esw_portctrl_encap_get(unit, port, &mode)); 3411 3412 requested_ability.speed_full_duplex = SOC_PA_SPEED(speed); 3413 requested_ability.speed_half_duplex = SOC_PA_SPEED(speed); 3414 3415 if (((port_ability.speed_full_duplex & 3416 requested_ability.speed_full_duplex) == 0) && 3417 ((port_ability.speed_half_duplex & 3418 requested_ability.speed_half_duplex) == 0)) { 3419 LOG_VERBOSE(BSL_LS_BCM_PORT, 3420 (BSL_META_UP(unit, port, 3421 "Port %d doesn't support %d Mbps speed.\n"), 3422 port, speed)); 3423 return BCM_E_CONFIG; 3424 } 3425 3426 /* Higig speed on Ethernet port is not supported */ 3427 if ((mode == BCM_PORT_ENCAP_IEEE) && SOC_PORTCTRL_IS_HG2_SPEED(speed)) { 3428 LOG_VERBOSE(BSL_LS_BCM_PORT, 3429 (BSL_META_UP(unit, port, 3430 "Port %d doesn't support %d Mbps speed.\n"), 3431 port, speed)); 3432 return BCM_E_CONFIG; 3433 } 3434 3435 return BCM_E_NONE; 3436 } 3437 3438 /* 3439 * Function: 3440 * _bcm_esw_portctrl_disable_autoneg 3441 * Purpose: 3442 * Disable Autoneg 3443 * Parameters: 3444 * unit - SOC unit number 3445 * pport - port type for portmod function 3446 * Returns: 3447 * BCM_E_XXX 3448 */ 3449 STATIC int 3450 _bcm_esw_portctrl_disable_autoneg(int unit, portctrl_pport_t pport) 3451 { 3452 int rv; 3453 phymod_autoneg_control_t an; 3454 3455 sal_memset(&an, 0, sizeof(phymod_autoneg_control_t)); 3456 3457 PORT_LOCK(unit); 3458 rv = portmod_port_autoneg_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an); 3459 if (PORTMOD_FAILURE(rv)) { 3460 PORT_UNLOCK(unit); 3461 return rv; 3462 } 3463 3464 an.enable = FALSE; 3465 3466 rv = portmod_port_autoneg_set(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an); 3467 if (PORTMOD_FAILURE(rv)) { 3468 PORT_UNLOCK(unit); 3469 return rv; 3470 } 3471 PORT_UNLOCK(unit); 3472 3473 return BCM_E_NONE; 3474 } 3475 3476 /* 3477 * Function: 3478 * _bcm_esw_portctrl_speed_chip_reconfig 3479 * Purpose: 3480 * Reconfigure chip(PGW/TDM/IP/EP/MMU) for speed set change 3481 * Parameters: 3482 * unit - SOC unit number 3483 * port - bcm_port_t port number 3484 * speed - port speed 3485 * Returns: 3486 * BCM_E_XXX 3487 */ 3488 STATIC int 3489 _bcm_esw_portctrl_speed_chip_reconfigure(int unit, bcm_port_t port, int speed) 3490 { 3491 int rv = BCM_E_NONE; 3492 3493 PORT_LOCK(unit); 3494 if (BCM_ESW_PORT_DRV(unit)!= NULL) { 3495 if (BCM_ESW_PORT_DRV(unit)->resource_speed_set != NULL) { 3496 rv = BCM_ESW_PORT_DRV(unit)->resource_speed_set(unit, port, 3497 speed); 3498 } 3499 } 3500 PORT_UNLOCK(unit); 3501 3502 if (BCM_FAILURE(rv)) { 3503 LOG_VERBOSE(BSL_LS_BCM_PORT, 3504 (BSL_META_UP(unit, port, 3505 "Set speed for chip resource failed\n"))); 3506 } 3507 3508 return rv; 3509 } 3510 3511 /* 3512 * Function: 3513 * _bcm_esw_portctrl_speed_interface_config_set 3514 * Purpose: 3515 * Change interface for speed. 3516 * Parameters: 3517 * unit - SOC unit number 3518 * port - bcm_port_t port number 3519 * pport - port number for portmod function 3520 * speed - port speed 3521 * Returns: 3522 * BCM_E_XXX 3523 */ 3524 STATIC int 3525 _bcm_esw_portctrl_speed_interface_config_set(int unit, bcm_gport_t port, 3526 portctrl_pport_t pport, int speed) 3527 { 3528 int rv; 3529 portmod_port_interface_config_t portmod_if_config; 3530 soc_port_if_t sys_interface; 3531 soc_port_if_t default_interface; 3532 bcm_gport_t gport; 3533 3534 PORT_LOCK(unit); 3535 3536 rv = portmod_port_interface_config_get(unit, pport, &portmod_if_config, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY); 3537 if (PORTMOD_FAILURE(rv)) { 3538 PORT_UNLOCK(unit); 3539 return rv; 3540 } 3541 3542 /* When changing the speed, the existing interface type of the 3543 * port may not be valid anymore. Need to retrieve the default 3544 * interface type based on the new speed and update 3545 * portmod_if_config. 3546 */ 3547 if (portmod_if_config.speed != speed) { 3548 portmod_if_config.speed = speed; 3549 default_interface = SOC_PORT_IF_NULL; 3550 rv = portmod_port_default_interface_get( 3551 unit, port, &portmod_if_config, &default_interface); 3552 if (SOC_FAILURE(rv)) { 3553 PORT_UNLOCK(unit); 3554 return (rv); 3555 } 3556 if (default_interface != SOC_PORT_IF_NULL) { 3557 portmod_if_config.interface = default_interface; 3558 } else { 3559 SOC_IF_ERROR_RETURN( 3560 portmod_common_default_interface_get(&portmod_if_config)); 3561 } 3562 } 3563 3564 3565 if (PORTMOD_SUCCESS(rv)) { 3566 rv = _bcm_esw_portctrl_interface_config_set(unit, port, pport, 3567 &portmod_if_config, 1); 3568 } 3569 3570 sys_interface = soc_property_port_get(unit, port, 3571 spn_PHY_SYS_INTERFACE, SOC_PORT_IF_COUNT); 3572 3573 if (sys_interface != SOC_PORT_IF_COUNT) { 3574 BCM_PHY_GPORT_PHYN_SYS_SIDE_PORT_SET(gport, 0, port); 3575 bcmi_esw_portctrl_phy_control_set(unit, gport, SOC_PHY_CONTROL_INTERFACE, 3576 sys_interface); 3577 } 3578 3579 PORT_UNLOCK(unit); 3580 3581 if (PORTMOD_FAILURE(rv)) { 3582 LOG_VERBOSE(BSL_LS_BCM_PORT, 3583 (BSL_META_UP(unit, port, 3584 "Set port speed failed: p=%d speed=%d rv=%d\n"), 3585 port, speed, rv)); 3586 } 3587 3588 return rv; 3589 } 3590 #endif 3591 3592 /* 3593 * Function: 3594 * bcmi_esw_portctrl_speed_set 3595 * Purpose: 3596 * Setting the speed for a given port 3597 * Parameters: 3598 * unit - StrataSwitch Unit #. 3599 * port - StrataSwitch port #. 3600 * speed - Value in megabits/sec (10, 100, etc) 3601 * Returns: 3602 * BCM_E_NONE 3603 * BCM_E_XXX 3604 */ 3605 int 3606 bcmi_esw_portctrl_speed_set(int unit, bcm_gport_t port, int speed) 3607 { 3608 #ifdef PORTMOD_SUPPORT 3609 portctrl_pport_t pport; 3610 int cur_speed; 3611 int loopback; 3612 int enable; 3613 int rv = SOC_E_NONE; 3614 3615 /* If current speed is different from target speed, 3616 need to call full speed_set sequence which includes IP/EP/MMU/TDM reprogramming 3617 If current speed is same as target speed, just 3618 need to disable Autoneg and call interface_config_set to apply interface change */ 3619 #define IS_FULL_SPEED_SET_REQUIRED(cur_speed, new_speed) \ 3620 ((cur_speed) != (new_speed)) 3621 3622 PORTCTRL_INIT_CHECK(unit); 3623 3624 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 3625 3626 /* check inactive port */ 3627 if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), port)) { 3628 LOG_VERBOSE(BSL_LS_BCM_PORT, 3629 (BSL_META_UP(unit, port, 3630 "Port %d is inactive port\n"), port)); 3631 return BCM_E_NONE; 3632 } 3633 3634 /* if speed is 0, set the port speed to max */ 3635 if (speed == 0) { 3636 BCM_IF_ERROR_RETURN 3637 (bcmi_esw_portctrl_speed_max(unit, port, &speed)); 3638 } 3639 3640 /* get current speed */ 3641 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_speed_get(unit, port, &cur_speed)); 3642 3643 3644 if (IS_FULL_SPEED_SET_REQUIRED(cur_speed, speed)) { 3645 /* validation : speed change is supported */ 3646 BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_speed_validate(unit, port, speed)); 3647 3648 /* clear loopback */ 3649 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_get(unit, 3650 port, &loopback)); 3651 if (loopback != BCM_PORT_LOOPBACK_NONE) { 3652 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_set(unit, 3653 port, 3654 BCM_PORT_LOOPBACK_NONE)); 3655 } 3656 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_enable_get(unit, port, &enable)); 3657 if (enable == TRUE) { 3658 /* disable MAC and PHY */ 3659 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_enable_set(unit, port, FALSE)); 3660 } 3661 3662 /* disable AN */ 3663 BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_disable_autoneg(unit, pport)); 3664 3665 /* reconfigure chip (PGW/TDM/IP/EP/MMU) */ 3666 rv = _bcm_esw_portctrl_speed_chip_reconfigure(unit, port, speed); 3667 if (BCM_SUCCESS(rv)) { 3668 /* reconfigure MAC & PHY */ 3669 BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_speed_interface_config_set( 3670 unit, port, pport, speed)); 3671 } 3672 if (enable == TRUE) { 3673 /* Restore port's enable state based on what was read prior to 3674 setting speed */ 3675 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_enable_set(unit, port, TRUE)); 3676 } 3677 /* restore loopback */ 3678 if (loopback != BCM_PORT_LOOPBACK_NONE) { 3679 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_set(unit, 3680 port, 3681 loopback)); 3682 } 3683 } else { 3684 PORTMOD_IF_ERROR_RETURN 3685 (portmod_port_enable_get(unit, port, PORTMOD_PORT_ENABLE_MAC, &enable)); 3686 3687 /* No full sequence is not required. If speed is same, 3688 just disable autoneg and apply interface_config_set */ 3689 if (enable == TRUE) { 3690 /* Disable port */ 3691 BCM_IF_ERROR_RETURN 3692 (_bcm_esw_portctrl_enable_set(unit, port, pport, 3693 PORTMOD_PORT_ENABLE_MAC, 0)); 3694 } 3695 3696 /* Autoneg should be disabled after disabling the MAC */ 3697 BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_disable_autoneg(unit, pport)); 3698 3699 /* reconfigure MAC & PHY */ 3700 BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_speed_interface_config_set( 3701 unit, port, pport, speed)); 3702 if (enable == TRUE) { 3703 /* Restore port's enable state. */ 3704 BCM_IF_ERROR_RETURN 3705 (_bcm_esw_portctrl_enable_set(unit, port, pport, 3706 PORTMOD_PORT_ENABLE_MAC, 1)); 3707 } 3708 } 3709 return rv; 3710 3711 #else /* PORTMOD_SUPPORT */ 3712 return BCM_E_UNAVAIL; 3713 #endif /* PORTMOD_SUPPORT */ 3714 } 3715 3716 /* Function: 3717 * bcmi_esw_portctrl_resource_speed_config_validate 3718 * Purpose: 3719 * Validate the resource configuration 3720 * Parameters: 3721 * unit - (IN) Unit number. 3722 * resource - (IN) The resource being validated 3723 * pbmp - (OUT) The port bitmap of affected sister ports 3724 * Returns: 3725 * BCM_E_NONE - Config is honored without affecting sister ports 3726 * BCM_E_PARAM - Config will affect sister ports in pbmp 3727 */ 3728 int 3729 bcmi_esw_portctrl_resource_speed_config_validate(int unit, 3730 bcm_port_resource_t *resource, bcm_pbmp_t *pbmp) 3731 { 3732 #ifdef PORTMOD_SUPPORT 3733 int rv = BCM_E_NONE; 3734 int port; 3735 portctrl_pport_t pport; 3736 portmod_speed_config_t sp_config; 3737 portmod_pbmp_t portmod_pbm; 3738 3739 PORTCTRL_INIT_CHECK(unit); 3740 3741 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, resource->port, 3742 &(resource->port), &pport)); 3743 3744 sp_config.speed = resource->speed; 3745 sp_config.num_lane = resource->lanes; 3746 sp_config.fec = resource->fec_type; 3747 sp_config.link_training = resource->link_training; 3748 sp_config.lane_config = resource->phy_lane_config; 3749 3750 PORT_LOCK(unit); 3751 rv = portmod_port_speed_config_validate(unit, pport, &sp_config, &portmod_pbm); 3752 PORT_UNLOCK(unit); 3753 3754 PORTMOD_PBMP_ITER(portmod_pbm, port) { 3755 if (port >= BCM_PBMP_PORT_MAX) { 3756 LOG_ERROR(BSL_LS_BCM_PORT, 3757 (BSL_META_UP(unit, port, 3758 "ERROR: Portmod Port %d greater than BCM " 3759 "Bitmap number of bits %d)\n"), 3760 port, (int)(sizeof(bcm_pbmp_t) * 4))); 3761 return BCM_E_INTERNAL; 3762 } 3763 3764 BCM_PBMP_PORT_ADD(*pbmp, port); 3765 } 3766 3767 return rv; 3768 #else /* PORTMOD_SUPPORT */ 3769 return BCM_E_UNAVAIL; 3770 #endif /* PORTMOD_SUPPORT */ 3771 } 3772 3773 #ifdef PORTMOD_SUPPORT 3774 /* 3775 * Function: 3776 * _bcm_esw_portctrl_speed_multi_set_chip_reconfigure 3777 * Purpose: 3778 * Reconfigure chip(PGW/TDM/IP/EP/MMU) for speed set change 3779 * Parameters: 3780 * unit - SOC unit number 3781 * nport - number of bcm_port_resource_t structs 3782 * resource - structure holding speed information 3783 * Returns: 3784 * BCM_E_XXX 3785 */ 3786 STATIC int 3787 _bcm_esw_portctrl_speed_multi_set_chip_reconfigure(int unit, int nport, 3788 bcm_port_resource_t *resource) 3789 { 3790 int rv = BCM_E_UNAVAIL; 3791 3792 PORT_LOCK(unit); 3793 if (BCM_ESW_PORT_DRV(unit)!= NULL) { 3794 if (BCM_ESW_PORT_DRV(unit)->port_resource_speed_multi_set != NULL) { 3795 rv = BCM_ESW_PORT_DRV(unit)->port_resource_speed_multi_set(unit, 3796 nport, resource); 3797 } 3798 } 3799 PORT_UNLOCK(unit); 3800 3801 if (BCM_FAILURE(rv)) { 3802 LOG_VERBOSE(BSL_LS_BCM_PORT, 3803 (BSL_META_U(unit, 3804 "Speed multi set for chip resource failed\n"))); 3805 } 3806 3807 return rv; 3808 } 3809 #endif /* PORTMOD_SUPPORT */ 3810 3811 /* 3812 * Function: 3813 * bcmi_esw_portctrl_speed_multi_set 3814 * Purpose: 3815 * Setting the speed given ports 3816 * Parameters: 3817 * unit - StrataSwitch Unit #. 3818 * nport - number of resource structures 3819 * resource - structures holding speed information 3820 * Returns: 3821 * BCM_E_NONE 3822 * BCM_E_XXX 3823 */ 3824 int 3825 bcmi_esw_portctrl_speed_multi_set(int unit, int nport, 3826 bcm_port_resource_t *resource) 3827 { 3828 #ifdef PORTMOD_SUPPORT 3829 int i; 3830 int *cur_speed = NULL; 3831 int *loopback = NULL; 3832 int *enable = NULL; 3833 portctrl_pport_t *pport = NULL; 3834 int rv = BCM_E_NONE; 3835 #ifdef PORTMOD_PM8X50_SUPPORT 3836 int phy_port = 0; 3837 portmod_speed_config_t sp_cfg; 3838 portmod_dispatch_type_t pm_type = portmodDispatchTypeCount; 3839 #endif 3840 PORTCTRL_INIT_CHECK(unit); 3841 3842 cur_speed = sal_alloc(nport * sizeof(int), "cur_speed array"); 3843 loopback = sal_alloc(nport * sizeof(int), "loopback array"); 3844 enable = sal_alloc(nport * sizeof(int), "enable array"); 3845 pport = sal_alloc(nport * sizeof(portctrl_pport_t), "pport array"); 3846 if (NULL == cur_speed || NULL == loopback || NULL == enable || 3847 NULL == pport) { 3848 goto multi_set_cleanup; 3849 } 3850 3851 /* Perform everything BEFORE the speed multi set call for each of the 3852 * ports first. 3853 * EVERYTHING is considered a full sequence change! */ 3854 for (i = 0; i < nport; i++) { 3855 3856 rv = PORTCTRL_PORT_RESOLVE(unit, resource[i].port, 3857 &(resource[i].port), &pport[i]); 3858 if (!BCM_SUCCESS(rv)) { 3859 goto multi_set_cleanup; 3860 } 3861 3862 /* check inactive port */ 3863 if (SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit,all), 3864 resource[i].port)) { 3865 LOG_VERBOSE(BSL_LS_BCM_PORT, 3866 (BSL_META_UP(unit, resource[i].port, 3867 "Port %d is inactive port\n"), 3868 resource[i].port)); 3869 goto multi_set_cleanup; 3870 } 3871 3872 /* if speed is 0, set the port speed to max */ 3873 if (resource[i].speed == 0) { 3874 rv = 3875 bcmi_esw_portctrl_speed_max(unit, resource[i].port, 3876 &resource[i].speed); 3877 if (!BCM_SUCCESS(rv)) { 3878 goto multi_set_cleanup; 3879 } 3880 } 3881 3882 /* get current speed */ 3883 rv = bcmi_esw_portctrl_speed_get(unit, resource[i].port, 3884 &(cur_speed[i])); 3885 if (!BCM_SUCCESS(rv)) { 3886 goto multi_set_cleanup; 3887 } 3888 /* validation : speed change is supported */ 3889 rv = _bcm_esw_portctrl_speed_validate(unit, 3890 resource[i].port, resource[i].speed); 3891 if (!BCM_SUCCESS(rv)) { 3892 goto multi_set_cleanup; 3893 } 3894 /* clear loopback */ 3895 rv = bcmi_esw_portctrl_loopback_get(unit, resource[i].port, 3896 &(loopback[i])); 3897 if (!BCM_SUCCESS(rv)) { 3898 goto multi_set_cleanup; 3899 } 3900 3901 if (loopback[i] != BCM_PORT_LOOPBACK_NONE) { 3902 rv = bcmi_esw_portctrl_loopback_set(unit, 3903 resource[i].port, 3904 BCM_PORT_LOOPBACK_NONE); 3905 if (!BCM_SUCCESS(rv)) { 3906 goto multi_set_cleanup; 3907 } 3908 } 3909 rv = bcmi_esw_portctrl_enable_get(unit, resource[i].port, 3910 &enable[i]); 3911 if (!BCM_SUCCESS(rv)) { 3912 goto multi_set_cleanup; 3913 } 3914 3915 if (enable[i] == TRUE) { 3916 /* disable MAC and PHY */ 3917 rv = bcmi_esw_portctrl_enable_set(unit, resource[i].port, FALSE); 3918 if (!BCM_SUCCESS(rv)) { 3919 goto multi_set_cleanup; 3920 } 3921 } 3922 3923 /* disable AN */ 3924 rv = _bcm_esw_portctrl_disable_autoneg(unit, pport[i]); 3925 if (!BCM_SUCCESS(rv)) { 3926 goto multi_set_cleanup; 3927 } 3928 } 3929 3930 /* Perform the single call to speed multi set for all ports */ 3931 /* Reconfigure chip (PGW/TDM/IP/EP/MMU) */ 3932 rv = _bcm_esw_portctrl_speed_multi_set_chip_reconfigure(unit, nport, 3933 resource); 3934 if (!BCM_SUCCESS(rv)) { 3935 goto multi_set_cleanup; 3936 } 3937 3938 3939 /* Perform everything AFTER the speed multi set call */ 3940 for (i = 0; i < nport; i++) { 3941 3942 #ifdef PORTMOD_PM8X50_SUPPORT 3943 /* Find out what kind of Port Macro we're dealing with */ 3944 phy_port = SOC_INFO(unit).port_l2p_mapping[resource[i].port]; 3945 #ifdef BCM_TOMAHAWK3_SUPPORT 3946 /* Tomahawk 3's Management Port Macro requires a spacing between 3947 * the lanes, so even though the two management ports' physical 3948 * ports are 257 and 258, the lane needs to be the next one, 3949 * so logical port 118 being mapped to physical port 258 needs 3950 * to pass 259 to portmod because portmod only recognizes lane 3951 * 0 (physical port 257) and lane 2 (physial port 259). 3952 */ 3953 if (SOC_IS_TOMAHAWK3(unit) && (phy_port == 258)) { 3954 phy_port = 259; 3955 } 3956 #endif 3957 rv = portmod_phy_pm_type_get(unit, phy_port, &pm_type); 3958 if (!BCM_SUCCESS(rv)) { 3959 goto multi_set_cleanup; 3960 } 3961 3962 /* reconfigure MAC & PHY */ 3963 /* for PM8x50, use speed_config_set */ 3964 if (pm_type == portmodDispatchTypePm8x50) { 3965 sp_cfg.speed = resource[i].speed; 3966 sp_cfg.num_lane = SOC_INFO(unit).port_num_lanes[resource[i].port]; 3967 sp_cfg.fec = resource[i].fec_type; 3968 sp_cfg.lane_config = resource[i].phy_lane_config; 3969 sp_cfg.link_training = resource[i].link_training; 3970 rv = _bcm_esw_portctrl_speed_config_set(unit, resource[i].port, 3971 pport[i], 3972 &sp_cfg); 3973 } else 3974 #endif 3975 { 3976 rv = _bcm_esw_portctrl_speed_interface_config_set( 3977 unit, resource[i].port, pport[i], resource[i].speed); 3978 } 3979 3980 if (!BCM_SUCCESS(rv)) { 3981 goto multi_set_cleanup; 3982 } 3983 3984 if (enable[i] == TRUE) { 3985 /* Restore port's enable state based on what was read prior to 3986 setting speed */ 3987 rv = bcmi_esw_portctrl_enable_set(unit, resource[i].port, TRUE); 3988 if (!BCM_SUCCESS(rv)) { 3989 goto multi_set_cleanup; 3990 } 3991 } 3992 /* restore loopback */ 3993 if (loopback[i] != BCM_PORT_LOOPBACK_NONE) { 3994 rv = bcmi_esw_portctrl_loopback_set(unit, 3995 resource[i].port, 3996 loopback[i]); 3997 if (!BCM_SUCCESS(rv)) { 3998 goto multi_set_cleanup; 3999 } 4000 } 4001 } 4002 4003 multi_set_cleanup: 4004 if (NULL != pport) { 4005 sal_free(pport); 4006 } 4007 if (NULL != enable) { 4008 sal_free(enable); 4009 } 4010 if (NULL != loopback) { 4011 sal_free(loopback); 4012 } 4013 if (NULL != cur_speed) { 4014 sal_free(cur_speed); 4015 } 4016 4017 return rv; 4018 4019 #else /* PORTMOD_SUPPORT */ 4020 return BCM_E_UNAVAIL; 4021 #endif /* PORTMOD_SUPPORT */ 4022 } 4023 4024 4025 /* 4026 * Function: 4027 * bcmi_esw_portctrl_stk_my_modid_set 4028 * Purpose: 4029 * Set the module-id in the Port block 4030 * Parameters: 4031 * unit - SOC unit# 4032 * port - port # 4033 * my_modid - the value to set 4034 * Returns: 4035 * BCM_E_XXX 4036 */ 4037 int 4038 bcmi_esw_portctrl_stk_my_modid_set(int unit, bcm_gport_t port, int my_modid) 4039 { 4040 #ifdef PORTMOD_SUPPORT 4041 int rv = BCM_E_NONE; 4042 portctrl_pport_t pport; 4043 4044 PORTCTRL_INIT_CHECK(unit); 4045 4046 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4047 4048 if (IS_HG_PORT(unit, port)) { 4049 PORT_LOCK(unit); 4050 rv = portmod_port_modid_set(unit, pport, my_modid); 4051 PORT_UNLOCK(unit); 4052 } 4053 4054 return rv; 4055 4056 #else /* PORTMOD_SUPPORT */ 4057 return BCM_E_UNAVAIL; 4058 #endif /* PORTMOD_SUPPORT */ 4059 } 4060 4061 /* 4062 * Function: 4063 * bcmi_esw_portctrl_pause_get 4064 * Purpose: 4065 * Get the TX and RX settings for pause frames. 4066 * Parameters: 4067 * unit - (IN) Unit number. 4068 * port - (IN) Port number. 4069 * pause_tx - (OUT) Boolean value. 4070 * pause_rx - (OUT) Boolean value. 4071 * Returns: 4072 * BCM_E_XXX 4073 */ 4074 int 4075 bcmi_esw_portctrl_pause_get(int unit, bcm_gport_t port, 4076 int *pause_tx, int *pause_rx) 4077 { 4078 #ifdef PORTMOD_SUPPORT 4079 int rv = BCM_E_NONE; 4080 portctrl_pport_t pport; 4081 portmod_pause_control_t pause_control; 4082 4083 PORTCTRL_INIT_CHECK(unit); 4084 4085 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4086 4087 PORT_LOCK(unit); 4088 rv = portmod_port_pause_control_get(unit, pport, &pause_control); 4089 PORT_UNLOCK(unit); 4090 4091 if (PORTMOD_SUCCESS(rv)) { 4092 *pause_tx = pause_control.tx_enable; 4093 *pause_rx = pause_control.rx_enable; 4094 } 4095 4096 return rv; 4097 4098 #else /* PORTMOD_SUPPORT */ 4099 return BCM_E_UNAVAIL; 4100 #endif /* PORTMOD_SUPPORT */ 4101 } 4102 4103 4104 /* 4105 * Function: 4106 * bcmi_esw_portctrl_pause_set 4107 * Purpose: 4108 * Enable or disable transmission of pause frames and 4109 * honoring received pause frames on a port. 4110 * Parameters: 4111 * unit - (IN) Unit number. 4112 * port - (IN) Port number. 4113 * pause_tx - (IN) 0 to disable transmission of pauseframes, 1 to enable. 4114 * pause_rx - (IN) 0 to ignore received pause frames, 1 to honor 4115 * received pause frames. 4116 * Returns: 4117 * BCM_E_XXX 4118 */ 4119 int 4120 bcmi_esw_portctrl_pause_set(int unit, bcm_gport_t port, 4121 int pause_tx, int pause_rx) 4122 { 4123 #ifdef PORTMOD_SUPPORT 4124 int rv = BCM_E_NONE; 4125 portctrl_pport_t pport; 4126 portmod_pause_control_t pause_control; 4127 4128 PORTCTRL_INIT_CHECK(unit); 4129 4130 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4131 4132 PORT_LOCK(unit); 4133 4134 rv = portmod_port_pause_control_get(unit, pport, &pause_control); 4135 if (PORTMOD_SUCCESS(rv)) { 4136 pause_control.rx_enable = pause_rx; 4137 pause_control.tx_enable = pause_tx; 4138 rv = portmod_port_pause_control_set(unit, pport, &pause_control); 4139 } 4140 4141 PORT_UNLOCK(unit); 4142 4143 return rv; 4144 4145 #else /* PORTMOD_SUPPORT */ 4146 return BCM_E_UNAVAIL; 4147 #endif /* PORTMOD_SUPPORT */ 4148 } 4149 4150 4151 /* 4152 * Function: 4153 * bcmi_esw_portctrl_pause_addr_get 4154 * Purpose: 4155 * Get the source address for transmitted PAUSE frames. 4156 * Parameters: 4157 * unit - (IN) Unit number. 4158 * port - (IN) Port number. 4159 * mac - (OUT) MAC address sent with pause frames. 4160 * Returns: 4161 * BCM_E_XXX 4162 */ 4163 int 4164 bcmi_esw_portctrl_pause_addr_get(int unit, bcm_gport_t port, bcm_mac_t mac) 4165 { 4166 #ifdef PORTMOD_SUPPORT 4167 int rv = BCM_E_NONE; 4168 portctrl_pport_t pport; 4169 4170 PORTCTRL_INIT_CHECK(unit); 4171 4172 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4173 4174 /* sal_mac_addr_t and bcm_mac_t typedefs definitions are the same */ 4175 PORT_LOCK(unit); 4176 rv = portmod_port_tx_mac_sa_get(unit, pport, mac); 4177 PORT_UNLOCK(unit); 4178 4179 return rv; 4180 4181 #else /* PORTMOD_SUPPORT */ 4182 return BCM_E_UNAVAIL; 4183 #endif /* PORTMOD_SUPPORT */ 4184 } 4185 4186 4187 /* 4188 * Function: 4189 * bcmi_esw_portctrl_pause_addr_set 4190 * Purpose: 4191 * Set the source address for transmitted PAUSE frames. 4192 * Parameters: 4193 * unit - (IN) Unit number. 4194 * port - (IN) Port number. 4195 * mac - (IN) Station MAC address used for pause frames. 4196 * Returns: 4197 * BCM_E_XXX 4198 */ 4199 int 4200 bcmi_esw_portctrl_pause_addr_set(int unit, bcm_gport_t port, bcm_mac_t mac) 4201 { 4202 #ifdef PORTMOD_SUPPORT 4203 int rv = BCM_E_NONE; 4204 portctrl_pport_t pport; 4205 4206 PORTCTRL_INIT_CHECK(unit); 4207 4208 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4209 4210 /* sal_mac_addr_t and bcm_mac_t typedefs definitions are the same */ 4211 PORT_LOCK(unit); 4212 rv = portmod_port_tx_mac_sa_set(unit, pport, mac); 4213 PORT_UNLOCK(unit); 4214 4215 return rv; 4216 4217 #else /* PORTMOD_SUPPORT */ 4218 return BCM_E_UNAVAIL; 4219 #endif /* PORTMOD_SUPPORT */ 4220 } 4221 4222 4223 /* 4224 * Function: 4225 * bcmi_esw_portctrl_eee_enable_get 4226 * Purpose: 4227 * Retrieve eee enable field. 4228 * Parameters: 4229 * unit - (IN) Unit number. 4230 * port - (IN) Port number. 4231 * enable - (OUT) Returns eee enable field. 4232 * Returns: 4233 * BCM_E_NONE 4234 * BCM_E_XXX 4235 */ 4236 int 4237 bcmi_esw_portctrl_eee_enable_get(int unit, bcm_gport_t port, int *enable) 4238 { 4239 #ifdef PORTMOD_SUPPORT 4240 int rv = BCM_E_NONE; 4241 portctrl_pport_t pport; 4242 portmod_eee_t eee; 4243 4244 PORTCTRL_INIT_CHECK(unit); 4245 4246 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4247 4248 PORT_LOCK(unit); 4249 rv = portmod_port_eee_get(unit, pport, &eee); 4250 *enable = eee.enable; 4251 PORT_UNLOCK(unit); 4252 4253 return rv; 4254 #else /* PORTMOD_SUPPORT */ 4255 return BCM_E_UNAVAIL; 4256 #endif /* PORTMOD_SUPPORT */ 4257 } 4258 4259 4260 /* 4261 * Function: 4262 * bcmi_esw_portctrl_eee_enable_set 4263 * Purpose: 4264 * Set the eee enable field if different from what is to be set. 4265 * Parameters: 4266 * unit - (IN) Unit number. 4267 * port - (IN) Port number. 4268 * enable - (IN) eee enable field. 4269 * Returns: 4270 * BCM_E_NONE 4271 * BCM_E_XXX 4272 */ 4273 int 4274 bcmi_esw_portctrl_eee_enable_set(int unit, bcm_gport_t port, int enable) 4275 { 4276 #ifdef PORTMOD_SUPPORT 4277 int rv = BCM_E_NONE; 4278 portctrl_pport_t pport; 4279 portmod_eee_t eee; 4280 4281 PORTCTRL_INIT_CHECK(unit); 4282 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4283 4284 PORT_LOCK(unit); 4285 rv = portmod_port_eee_get(unit, pport, &eee); 4286 if (PORTMOD_SUCCESS(rv)) { 4287 if (eee.enable != enable) { 4288 eee.enable = enable; 4289 rv = portmod_port_eee_set(unit, pport, &eee); 4290 } 4291 } 4292 PORT_UNLOCK(unit); 4293 4294 return rv; 4295 #else /* PORTMOD_SUPPORT */ 4296 return BCM_E_UNAVAIL; 4297 #endif /* PORTMOD_SUPPORT */ 4298 } 4299 4300 /* 4301 * Function: 4302 * bcmi_portctrl_master_get 4303 * Purpose: 4304 * Getting the master status of the port 4305 * Parameters: 4306 * unit - StrataSwitch Unit #. 4307 * port - StrataSwitch port #. 4308 * ms - (OUT) BCM_PORT_MS_* 4309 * Returns: 4310 * BCM_E_NONE 4311 * BCM_E_XXX 4312 * Notes: 4313 * WARNING: assumes BCM_PORT_MS_* matches SOC_PORT_MS_* 4314 */ 4315 4316 int 4317 bcmi_esw_portctrl_master_get(int unit, bcm_gport_t port, int *ms) 4318 { 4319 #ifdef PORTMOD_SUPPORT 4320 int rv = BCM_E_NONE; 4321 portctrl_pport_t pport; 4322 portmod_dispatch_type_t pm_type; 4323 int pm_type_supported = 0; 4324 4325 /* Make sure port module is initialized. */ 4326 PORTCTRL_INIT_CHECK(unit); 4327 4328 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4329 4330 rv = portmod_port_pm_type_get(unit, port, &port, &pm_type); 4331 if (rv != BCM_E_NONE) { 4332 return rv; 4333 } 4334 4335 /* 4336 * portmod_port_master_get() fetches the master_mode regsiter value ONLY WHEN 4337 * there is a legacy ext PHY attaching to a port. Currently there is no 4338 * master_mode_get API implemented for PHYMOD-based int/ext PHY. When a portmod 4339 * port is NOT attaching to an ext PHY, it simply updates the master mode as 4340 * slave since the internal PHY only operates in the slave mode. When the portmod 4341 * port is attaching to a PHYMOD-based ext PHY, the master mode will be updated as 4342 * BCM_PORT_MS_NONE to reflect the unknown status. 4343 */ 4344 4345 #ifdef PORTMOD_PM4X10_SUPPORT 4346 if (pm_type == portmodDispatchTypePm4x10 4347 #ifdef PORTMOD_PM4X10TD_SUPPORT 4348 || pm_type == portmodDispatchTypePm4x10td 4349 #endif /* PORTMOD_PM4X10TD_SUPPORT */ 4350 ) { 4351 rv = portmod_port_master_get(unit, port, ms); 4352 pm_type_supported = 1; 4353 } 4354 #endif /* PORTMOD_PM4X10_SUPPORT */ 4355 4356 #ifdef PORTMOD_PM4X25_SUPPORT 4357 if (pm_type == portmodDispatchTypePm4x25 4358 #ifdef PORTMOD_PM4X25TD_SUPPORT 4359 || pm_type == portmodDispatchTypePm4x25td 4360 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 4361 ) { 4362 rv = portmod_port_master_get(unit, port, ms); 4363 pm_type_supported = 1; 4364 } 4365 #endif /* PORTMOD_PM4X25_SUPPORT */ 4366 #ifdef PORTMOD_CPM4X25_SUPPORT 4367 if (pm_type == portmodDispatchTypeCpm4x25 4368 ) { 4369 rv = portmod_port_master_get(unit, port, ms); 4370 pm_type_supported = 1; 4371 } 4372 #endif /* PORTMOD_PM4X25_SUPPORT */ 4373 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 4374 if (pm_type == portmodDispatchTypePm4x10_qtc) { 4375 rv = portmod_port_master_get(unit, port, ms); 4376 pm_type_supported = 1; 4377 } 4378 #endif /* PORTMOD_PM4X10_QTC_SUPPORT */ 4379 if (!pm_type_supported) { 4380 *ms = BCM_PORT_MS_NONE; 4381 } 4382 4383 return rv; 4384 4385 #else /* PORTMOD_SUPPORT */ 4386 return BCM_E_UNAVAIL; 4387 #endif /* PORTMOD_SUPPORT */ 4388 } 4389 4390 /* 4391 * Function: 4392 * bcmi_portctrl_medium_config_set 4393 * Description: 4394 * Set the medium config of a combo port 4395 * Parameters: 4396 * unit - Device number 4397 * port - Port number 4398 * medium - The medium (BCM_PORT_MEDIUM_COPPER or BCM_PORT_MEDIUM_FIBER) 4399 * which is currently selected 4400 * config - Medium config 4401 * Return Value: 4402 * BCM_E_XXX 4403 */ 4404 int 4405 bcmi_esw_portctrl_medium_config_set(int unit, bcm_gport_t port, bcm_port_medium_t medium, 4406 bcm_phy_config_t *config) 4407 { 4408 #ifdef PORTMOD_SUPPORT 4409 int rv = BCM_E_NONE; 4410 portctrl_pport_t pport; 4411 4412 /* Make sure port module is initialized. */ 4413 PORTCTRL_INIT_CHECK(unit); 4414 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4415 4416 PORT_LOCK(unit); 4417 rv = portmod_port_medium_config_set(unit, pport, medium, config); 4418 PORT_UNLOCK(unit); 4419 4420 return rv; 4421 4422 #else /* PORTMOD_SUPPORT */ 4423 return BCM_E_UNAVAIL; 4424 #endif /* PORTMOD_SUPPORT */ 4425 } 4426 4427 /* 4428 * Function: 4429 * bcmi_portctrl_medium_config_get 4430 * Description: 4431 * Get the medium config of a combo port 4432 * Parameters: 4433 * unit - Device number 4434 * port - Port number 4435 * medium - The medium (BCM_PORT_MEDIUM_COPPER or BCM_PORT_MEDIUM_FIBER) 4436 * which is currently selected 4437 * config - Medium config 4438 * Return Value: 4439 * BCM_E_XXX 4440 */ 4441 int 4442 bcmi_esw_portctrl_medium_config_get(int unit, bcm_gport_t port, bcm_port_medium_t medium, 4443 bcm_phy_config_t *config) 4444 { 4445 #ifdef PORTMOD_SUPPORT 4446 int rv = BCM_E_NONE; 4447 portctrl_pport_t pport; 4448 int ext_phy_present; 4449 4450 /* Make sure port module is initialized. */ 4451 PORTCTRL_INIT_CHECK(unit); 4452 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4453 4454 /* PORTMOD currently only supports medium config get for ports with legacy ext PHY */ 4455 SOC_IF_ERROR_RETURN(portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present)); 4456 if (!ext_phy_present) { 4457 return BCM_E_UNAVAIL; 4458 } 4459 4460 PORT_LOCK(unit); 4461 rv = portmod_port_medium_config_get(unit, pport, medium, config); 4462 PORT_UNLOCK(unit); 4463 4464 return rv; 4465 4466 #else /* PORTMOD_SUPPORT */ 4467 return BCM_E_UNAVAIL; 4468 #endif /* PORTMOD_SUPPORT */ 4469 } 4470 4471 /* 4472 * Function: 4473 * bcmi_port_medium_get 4474 * Description: 4475 * Get the current medium used by a combo port 4476 * Parameters: 4477 * unit - Device number 4478 * port - Port number 4479 * medium - The medium (BCM_PORT_MEDIUM_COPPER or BCM_PORT_MEDIUM_FIBER) 4480 * which is currently selected 4481 * Return Value: 4482 * BCM_E_XXX 4483 */ 4484 int 4485 bcmi_esw_portctrl_medium_get(int unit, bcm_gport_t port, 4486 bcm_port_medium_t *medium) 4487 { 4488 #ifdef PORTMOD_SUPPORT 4489 int rv = BCM_E_NONE; 4490 portctrl_pport_t pport; 4491 int ext_phy_present; 4492 4493 /* Make sure port module is initialized. */ 4494 PORTCTRL_INIT_CHECK(unit); 4495 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4496 4497 *medium = SOC_PORT_MEDIUM_NONE; 4498 4499 /* dig further if there is an ext PHY present and medium type is not yet found */ 4500 rv = portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present); 4501 if (ext_phy_present && *medium == SOC_PORT_MEDIUM_NONE){ 4502 PORT_LOCK(unit); 4503 portmod_port_medium_get(unit, pport, medium); 4504 PORT_UNLOCK(unit); 4505 } 4506 4507 return rv; 4508 4509 #else /* PORTMOD_SUPPORT */ 4510 return BCM_E_UNAVAIL; 4511 #endif /* PORTMOD_SUPPORT */ 4512 } 4513 4514 /* 4515 * Function: 4516 * bcmi_portctrl_master_set 4517 * Purpose: 4518 * Setting the master status for a given port 4519 * Parameters: 4520 * unit - StrataSwitch Unit #. 4521 * port - StrataSwitch port #. 4522 * ms - BCM_PORT_MS_* 4523 * Returns: 4524 * BCM_E_NONE 4525 * BCM_E_XXX 4526 * Notes: 4527 * Ignored if not supported on port. 4528 * WARNING: assumes BCM_PORT_MS_* matches SOC_PORT_MS_* 4529 */ 4530 int 4531 bcmi_esw_portctrl_master_set(int unit, bcm_gport_t port, int ms) 4532 { 4533 #ifdef PORTMOD_SUPPORT 4534 int rv = BCM_E_NONE; 4535 pbmp_t pbm; 4536 portctrl_pport_t pport; 4537 portmod_dispatch_type_t pm_type; 4538 int pm_type_supported = 0; 4539 4540 /* Make sure port module is initialized. */ 4541 PORTCTRL_INIT_CHECK(unit); 4542 4543 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4544 4545 rv = portmod_port_pm_type_get(unit, port, &port, &pm_type); 4546 if (rv != BCM_E_NONE) { 4547 return rv; 4548 } 4549 4550 #ifdef BCM_RCPU_SUPPORT 4551 if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) { 4552 return BCM_E_PORT; 4553 } 4554 #endif /* BCM_RCPU_SUPPORT */ 4555 4556 #ifdef PORTMOD_PM4X10_SUPPORT 4557 if (pm_type == portmodDispatchTypePm4x10 4558 #ifdef PORTMOD_PM4X10TD_SUPPORT 4559 || pm_type == portmodDispatchTypePm4x10td 4560 #endif /* PORTMOD_PM4X10TD_SUPPORT */ 4561 ) { 4562 rv = portmod_port_master_set(unit, port, ms); 4563 pm_type_supported = 1; 4564 } 4565 #endif /* PORTMOD_PM4X10_SUPPORT */ 4566 4567 #ifdef PORTMOD_PM4X25_SUPPORT 4568 if (pm_type == portmodDispatchTypePm4x25 4569 #ifdef PORTMOD_PM4X25TD_SUPPORT 4570 || pm_type == portmodDispatchTypePm4x25td 4571 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 4572 ) { 4573 rv = portmod_port_master_set(unit, port, ms); 4574 pm_type_supported = 1; 4575 } 4576 #endif /* PORTMOD_PM4X25_SUPPORT */ 4577 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 4578 if (pm_type == portmodDispatchTypePm4x10_qtc) { 4579 rv = portmod_port_master_set(unit, port, ms); 4580 pm_type_supported = 1; 4581 } 4582 #endif /* PORTMOD_PM4X10_QTC_SUPPORT */ 4583 SOC_PBMP_CLEAR(pbm); 4584 SOC_PBMP_PORT_ADD(pbm, port); 4585 (void)bcm_esw_link_change(unit, pbm); 4586 4587 if (pm_type_supported == 1) { 4588 return rv; 4589 } else { 4590 return BCM_E_UNAVAIL; 4591 } 4592 4593 #else /* PORTMOD_SUPPORT */ 4594 return BCM_E_UNAVAIL; 4595 #endif /* PORTMOD_SUPPORT */ 4596 4597 } 4598 4599 4600 /* 4601 * Function: 4602 * bcmi_portctrl_interface_get 4603 * Purpose: 4604 * Getting the interface type of a port 4605 * Parameters: 4606 * unit - StrataSwitch Unit #. 4607 * port - StrataSwitch port #. 4608 * intf - (OUT) BCM_PORT_IF_* 4609 * Returns: 4610 * BCM_E_NONE 4611 * BCM_E_XXX 4612 * Notes: 4613 * WARNING: assumes BCM_PORT_IF_* matches SOC_PORT_IF_* 4614 */ 4615 4616 int 4617 bcmi_esw_portctrl_interface_get(int unit, bcm_gport_t port, bcm_port_if_t *intf) 4618 { 4619 #ifdef PORTMOD_SUPPORT 4620 int rv; 4621 portmod_port_interface_config_t port_if_cfg; 4622 portctrl_pport_t pport; 4623 4624 /* Make sure port module is initialized. */ 4625 PORTCTRL_INIT_CHECK(unit); 4626 4627 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4628 4629 if (!SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port)) { 4630 return BCM_E_PORT; 4631 } 4632 4633 portmod_port_interface_config_t_init(unit, &port_if_cfg); 4634 4635 PORT_LOCK(unit); 4636 rv = portmod_port_interface_config_get(unit, pport, &port_if_cfg, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY); 4637 PORT_UNLOCK(unit); 4638 4639 if (PORTMOD_SUCCESS(rv)) { 4640 *intf = port_if_cfg.interface; 4641 } 4642 4643 return rv; 4644 #else /* PORTMOD_SUPPORT */ 4645 return BCM_E_UNAVAIL; 4646 #endif /* PORTMOD_SUPPORT */ 4647 4648 } 4649 4650 /* 4651 * Function: 4652 * bcmi_portctrl_interface_set 4653 * Purpose: 4654 * Setting the interface type for a given port 4655 * Parameters: 4656 * unit - StrataSwitch Unit #. 4657 * port - StrataSwitch port #. 4658 * if - BCM_PORT_IF_* 4659 * Returns: 4660 * BCM_E_NONE 4661 * BCM_E_XXX 4662 * Notes: 4663 * WARNING: assumes BCM_PORT_IF_* matches SOC_PORT_IF_* 4664 */ 4665 int 4666 bcmi_esw_portctrl_interface_set(int unit, bcm_gport_t port, bcm_port_if_t intf) 4667 { 4668 #ifdef PORTMOD_SUPPORT 4669 int rv = BCM_E_NONE; 4670 char *str = ""; 4671 pbmp_t pbm; 4672 portmod_port_interface_config_t port_if_cfg; 4673 portctrl_pport_t pport; 4674 _bcm_port_info_t *port_info = NULL; 4675 4676 /* Make sure port module is initialized. */ 4677 PORTCTRL_INIT_CHECK(unit); 4678 4679 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4680 4681 if (!SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port)) { 4682 return BCM_E_PORT; 4683 } 4684 4685 #ifdef BCM_RCPU_SUPPORT 4686 if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) { 4687 return BCM_E_PORT; 4688 } 4689 #endif /* BCM_RCPU_SUPPORT */ 4690 4691 portmod_port_interface_config_t_init(unit, &port_if_cfg); 4692 4693 PORT_LOCK(unit); 4694 rv = portmod_port_interface_config_get(unit, pport, &port_if_cfg, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY); 4695 4696 if (PORTMOD_SUCCESS(rv)) { 4697 4698 /* Set interface type */ 4699 port_if_cfg.interface = intf; 4700 port_if_cfg.flags = PHYMOD_INTF_F_INTF_PARAM_SET_ONLY ; 4701 4702 rv = _bcm_esw_portctrl_interface_config_set(unit, port, pport, 4703 &port_if_cfg, 0); 4704 PORT_UNLOCK(unit); 4705 4706 /* Unlock before link call */ 4707 if (PORTMOD_SUCCESS(rv)) { 4708 SOC_PBMP_CLEAR(pbm); 4709 SOC_PBMP_PORT_ADD(pbm, port); 4710 (void)bcm_esw_link_change(unit, pbm); 4711 if (soc_property_get(unit, spn_SAME_SPEED_INTF_DO_NOT_OVERWRITE, 4712 (SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM))) { 4713 _bcm_port_info_access(unit, port, &port_info); 4714 port_info->intf = intf; 4715 } 4716 } else { 4717 str = "set"; 4718 } 4719 } else { 4720 PORT_UNLOCK(unit); 4721 str = "get"; 4722 } 4723 4724 if (BCM_FAILURE(rv)) { 4725 LOG_VERBOSE(BSL_LS_SOC_COMMON, 4726 (BSL_META_UP(unit, port, 4727 "Interface_%s failed:%s\n"), str, bcm_errmsg(rv))); 4728 } 4729 4730 return rv; 4731 4732 #else /* PORTMOD_SUPPORT */ 4733 return BCM_E_UNAVAIL; 4734 #endif /* PORTMOD_SUPPORT */ 4735 } 4736 4737 /* 4738 * Function: 4739 * bcmi_portctrl_mdix_get 4740 * Description: 4741 * Get the Auto-MDIX mode of a port/PHY 4742 * Parameters: 4743 * unit - Device number 4744 * port - Port number 4745 * mode - (Out) One of: 4746 * BCM_PORT_MDIX_AUTO 4747 * Enable auto-MDIX when autonegotiation is enabled 4748 * BCM_PORT_MDIX_FORCE_AUTO 4749 * Enable auto-MDIX always 4750 * BCM_PORT_MDIX_NORMAL 4751 * Disable auto-MDIX 4752 * BCM_PORT_MDIX_XOVER 4753 * Disable auto-MDIX, and swap cable pairs 4754 * Return Value: 4755 * BCM_E_UNAVAIL - feature unsupported by hardware 4756 * BCM_E_XXX - other error 4757 */ 4758 int 4759 bcmi_esw_portctrl_mdix_get(int unit, bcm_gport_t port, bcm_port_mdix_t *mode) 4760 { 4761 #ifdef PORTMOD_SUPPORT 4762 int rv = BCM_E_NONE; 4763 portctrl_pport_t pport; 4764 int ext_phy_present = 0; 4765 char *str = ""; 4766 4767 /* Make sure port module is initialized. */ 4768 PORTCTRL_INIT_CHECK(unit); 4769 4770 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4771 4772 PORT_LOCK(unit); 4773 rv = portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present); 4774 4775 if (PORTMOD_SUCCESS(rv)) { 4776 if (ext_phy_present) { 4777 rv = portmod_port_ext_phy_mdix_get(unit, pport, mode); 4778 4779 str = "portmod_port_ext_phy_mdix_get"; 4780 } else { 4781 /* MDIX is supported for external phys only, so we return a fixed 4782 * value for internal phys 4783 */ 4784 *mode = SOC_PORT_MDIX_NORMAL; 4785 } 4786 } else { 4787 str = "portmod_port_is_legacy_ext_phy_present"; 4788 } 4789 4790 PORT_UNLOCK(unit); 4791 if (PORTMOD_FAILURE(rv)) { 4792 4793 LOG_VERBOSE(BSL_LS_BCM_PORT, 4794 (BSL_META_UP(unit, port, "MDIX get: %s failed:\n" 4795 "port=%d, pport=%d, rv=%d\n"), str, port, pport, rv)); 4796 } 4797 4798 return rv; 4799 #else /* PORTMOD_SUPPORT */ 4800 return BCM_E_UNAVAIL; 4801 #endif /* PORTMOD_SUPPORT */ 4802 } 4803 4804 /* 4805 * Function: 4806 * bcmi_portctrl_mdix_set 4807 * Description: 4808 * Set the Auto-MDIX mode of a port/PHY 4809 * Parameters: 4810 * unit - Device number 4811 * port - Port number 4812 * mode - One of: 4813 * BCM_PORT_MDIX_FORCE_AUTO 4814 * Enable auto-MDIX always 4815 * BCM_PORT_MDIX_NORMAL 4816 * Disable auto-MDIX 4817 * BCM_PORT_MDIX_XOVER 4818 * Disable auto-MDIX, and swap cable pairs 4819 * Return Value: 4820 * BCM_E_UNAVAIL - feature unsupported by hardware 4821 * BCM_E_XXX - other error 4822 */ 4823 int 4824 bcmi_esw_portctrl_mdix_set(int unit, bcm_gport_t port, bcm_port_mdix_t mode) 4825 { 4826 #ifdef PORTMOD_SUPPORT 4827 int rv = BCM_E_NONE; 4828 portctrl_pport_t pport; 4829 int ext_phy_present = 0; 4830 char *str = ""; 4831 4832 /* Make sure port module is initialized. */ 4833 PORTCTRL_INIT_CHECK(unit); 4834 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4835 4836 PORT_LOCK(unit); 4837 rv = portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present); 4838 4839 if (PORTMOD_SUCCESS(rv)) { 4840 if (ext_phy_present) { 4841 rv = portmod_port_ext_phy_mdix_set(unit, pport, mode); 4842 4843 str = "portmod_port_ext_phy_mdix_set failed:"; 4844 } else { 4845 /* The behavior of this function should match legacy mdix API's, 4846 * so if mdix mode is other than normal, we return error 4847 */ 4848 if (mode != SOC_PORT_MDIX_NORMAL) { 4849 rv = BCM_E_UNAVAIL; 4850 str = "mode is not 'normal' "; 4851 } 4852 } 4853 4854 /* For internal phys, we do not program h/w; we return success */ 4855 } else { 4856 str = "portmod_port_is_legacy_ext_phy_present failed:"; 4857 } 4858 4859 PORT_UNLOCK(unit); 4860 if (PORTMOD_FAILURE(rv)) { 4861 4862 LOG_VERBOSE(BSL_LS_BCM_PORT, 4863 (BSL_META_UP(unit, port, "MDIX set: %s\nport=%d," 4864 " pport=%d, rv=%d\n"), str, port, pport, rv)); 4865 } 4866 4867 return rv; 4868 #else /* PORTMOD_SUPPORT */ 4869 return BCM_E_UNAVAIL; 4870 #endif /* PORTMOD_SUPPORT */ 4871 } 4872 4873 /* 4874 * Function: 4875 * bcmi_portctrl_mdix_status_get 4876 * Description: 4877 * Get the current MDIX status on a port/PHY 4878 * Parameters: 4879 * unit - Device number 4880 * port - Port number 4881 * status - (OUT) One of: 4882 * BCM_PORT_MDIX_STATUS_NORMAL 4883 * Straight connection 4884 * BCM_PORT_MDIX_STATUS_XOVER 4885 * Crossover has been performed 4886 * Return Value: 4887 * BCM_E_UNAVAIL - feature unsupported by hardware 4888 * BCM_E_XXX - other error 4889 */ 4890 int 4891 bcmi_esw_portctrl_mdix_status_get(int unit, bcm_gport_t port, 4892 bcm_port_mdix_status_t *status) 4893 { 4894 #ifdef PORTMOD_SUPPORT 4895 int rv = BCM_E_NONE; 4896 portctrl_pport_t pport; 4897 int ext_phy_present = 0; 4898 char *str = ""; 4899 4900 /* Make sure port module is initialized. */ 4901 PORTCTRL_INIT_CHECK(unit); 4902 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4903 4904 PORT_LOCK(unit); 4905 rv = portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present); 4906 4907 if (PORTMOD_SUCCESS(rv)) { 4908 4909 /* MDIX is supported for external phys only */ 4910 if (ext_phy_present) { 4911 rv = portmod_port_ext_phy_mdix_status_get(unit, pport, status); 4912 4913 str = "portmod_port_ext_phy_mdix_status_get"; 4914 } else { 4915 *status = SOC_PORT_MDIX_STATUS_NORMAL; 4916 } 4917 } else { 4918 str = "portmod_port_is_legacy_ext_phy_present"; 4919 } 4920 4921 PORT_UNLOCK(unit); 4922 if (PORTMOD_FAILURE(rv)) { 4923 4924 LOG_VERBOSE(BSL_LS_BCM_PORT, 4925 (BSL_META_UP(unit, port, "MDIX status get: %s failed:\n" 4926 "port=%d, pport=%d, rv=%d\n"), str, port, pport, rv)); 4927 } 4928 return rv; 4929 #else /* PORTMOD_SUPPORT */ 4930 return BCM_E_UNAVAIL; 4931 #endif /* PORTMOD_SUPPORT */ 4932 } 4933 4934 /* 4935 * Function: 4936 * bcmi_esw_portctrl_phy_get 4937 * Description: 4938 * General PHY register read 4939 * Parameters: 4940 * unit - Device number 4941 * port - Port number or PHY MDIO address (refer BCM_PORT_PHY_NOMAP) 4942 * flags - Logical OR of one or more of the following flags: 4943 * BCM_PORT_PHY_INTERNAL 4944 * Address internal SERDES PHY for port 4945 * BCM_PORT_PHY_NOMAP 4946 * Instead of mapping port to PHY MDIO address, 4947 * treat port parameter as actual PHY MDIO address. 4948 * BCM_PORT_PHY_CLAUSE45 4949 * Assume Clause 45 device instead of Clause 22 4950 * phy_addr - PHY internal register address 4951 * phy_data - (OUT) Data that was read 4952 * Returns: 4953 * BCM_E_XXX 4954 */ 4955 int 4956 bcmi_esw_portctrl_phy_get(int unit, bcm_gport_t port, uint32 flags, 4957 uint32 phy_reg_addr, uint32 *phy_data) 4958 { 4959 #ifdef PORTMOD_SUPPORT 4960 uint16 phy_id; 4961 uint8 phy_devad; 4962 uint16 phy_reg; 4963 uint16 phy_rd_data; 4964 uint32 reg_flag; 4965 int rv; 4966 portctrl_pport_t pport=0; 4967 int lane = -1; 4968 int phyn = -1, sys_side = 0; 4969 bcm_port_t local_port = -1; 4970 4971 /* Make sure port module is initialized. */ 4972 PORTCTRL_INIT_CHECK(unit); 4973 4974 if (!(flags & BCM_PORT_PHY_NOMAP)) { 4975 BCM_IF_ERROR_RETURN 4976 (_bcm_esw_port_gport_phyn_validate(unit, port, 4977 &local_port, &phyn, 4978 &lane, &sys_side)); 4979 if (local_port != -1) { 4980 port = local_port; 4981 } 4982 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 4983 if(!(SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port))) { 4984 return BCM_E_PORT; 4985 } 4986 } 4987 4988 if (flags & (BCM_PORT_PHY_I2C_DATA8 | BCM_PORT_PHY_I2C_DATA16 | BCM_PORT_PHY_PVT_DATA)) { 4989 PORT_LOCK(unit); 4990 rv = portmod_port_phy_reg_read(unit, pport, lane, flags, phy_reg_addr, phy_data); 4991 PORT_UNLOCK(unit); 4992 return rv; 4993 } 4994 4995 rv = BCM_E_UNAVAIL; 4996 reg_flag = BCM_PORT_PHY_REG_FLAGS(phy_reg_addr); 4997 if (reg_flag & BCM_ESW_PORTCTRL_PHY_REG_INDIRECT) { 4998 if (flags & BCM_PORT_PHY_NOMAP) { 4999 /* Indirect register access is performed through PHY driver. 5000 * Therefore, indirect register access is not supported if 5001 * BCM_PORT_PHY_NOMAP flag is set. 5002 */ 5003 return BCM_E_PARAM; 5004 } 5005 phy_reg_addr &= ~BCM_ESW_PORTCTRL_PHY_REG_INDIRECT; 5006 if (phyn == 1) { 5007 flags |= BCM_PORT_PHY_INTERNAL; 5008 } 5009 PORT_LOCK(unit); 5010 rv = portmod_port_phy_reg_read(unit, pport, lane, flags, phy_reg_addr, phy_data); 5011 PORT_UNLOCK(unit); 5012 } 5013 5014 if (rv == BCM_E_UNAVAIL) { 5015 if (flags & BCM_PORT_PHY_NOMAP) { 5016 phy_id = (uint16) port; 5017 } else if (flags & BCM_PORT_PHY_INTERNAL) { 5018 PORT_LOCK(unit); 5019 phy_id = portmod_port_to_phyaddr_int(unit, pport); 5020 PORT_UNLOCK(unit); 5021 } else { 5022 PORT_LOCK(unit); 5023 phy_id = portmod_port_to_phyaddr(unit, pport); 5024 PORT_UNLOCK(unit); 5025 } 5026 5027 PORT_LOCK(unit); 5028 if (flags & BCM_PORT_PHY_CLAUSE45) { 5029 phy_devad = BCM_PORT_PHY_CLAUSE45_DEVAD(phy_reg_addr); 5030 phy_reg = BCM_PORT_PHY_CLAUSE45_REGAD(phy_reg_addr); 5031 rv = soc_miimc45_read(unit, phy_id, phy_devad, 5032 phy_reg, &phy_rd_data); 5033 5034 } else { 5035 phy_reg = phy_reg_addr; 5036 rv = soc_miim_read(unit, phy_id, phy_reg, &phy_rd_data); 5037 } 5038 PORT_UNLOCK(unit); 5039 5040 if (BCM_SUCCESS(rv)) { 5041 *phy_data = phy_rd_data; 5042 } 5043 } 5044 5045 LOG_INFO(BSL_LS_BCM_PORT, 5046 (BSL_META_U(unit, 5047 "portctrl_phy_get: u=%d p=%d flags=0x%08x " 5048 "phy_reg=0x%08x, phy_data=0x%08x, rv=%d\n"), 5049 unit, port, flags, phy_reg_addr, *phy_data, rv)); 5050 5051 return rv; 5052 #else /* PORTMOD_SUPPORT */ 5053 return BCM_E_UNAVAIL; 5054 #endif /* PORTMOD_SUPPORT */ 5055 } 5056 5057 /* 5058 * Function: 5059 * bcmi_esw_portctrl_phy_multi_get 5060 * Description: 5061 * General PHY register read 5062 * Parameters: 5063 * unit - Device number 5064 * port - Port number 5065 * flags - Phy's read-specific flags 5066 * dev_addr - Device address on the PHY's bus (ex. I2C addr) 5067 * offset - Offset within device 5068 * max_size - Requested data size 5069 * data - Data buffer 5070 * actual_size - Received data size 5071 * Returns: 5072 * BCM_E_XXX 5073 */ 5074 int 5075 bcmi_esw_portctrl_phy_multi_get(int unit, bcm_gport_t port, uint32 flags, 5076 uint32 dev_addr, uint32 offset, int max_size, 5077 uint8 *data, int *actual_size) 5078 { 5079 #ifdef PORTMOD_SUPPORT 5080 int rv; 5081 portctrl_pport_t pport; 5082 portmod_multi_get_t phy_reg_read; 5083 5084 /* Make sure port module is initialized. */ 5085 PORTCTRL_INIT_CHECK(unit); 5086 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 5087 5088 /* Initialize and fill the structure */ 5089 portmod_multi_get_t_init(unit, &phy_reg_read); 5090 5091 phy_reg_read.flags = flags; 5092 phy_reg_read.dev_addr = dev_addr; 5093 phy_reg_read.offset = offset; 5094 phy_reg_read.max_size = max_size; 5095 phy_reg_read.data = data; 5096 phy_reg_read.actual_size = (uint32 *)actual_size; 5097 5098 PORT_LOCK(unit); 5099 rv = portmod_port_multi_get(unit, pport, &phy_reg_read); 5100 PORT_UNLOCK(unit); 5101 5102 return rv; 5103 #else /* PORTMOD_SUPPORT */ 5104 return BCM_E_UNAVAIL; 5105 #endif /* PORTMOD_SUPPORT */ 5106 } 5107 5108 /* 5109 * Function: 5110 * bcmi_esw_portctrl_phy_modify 5111 * Description: 5112 * General PHY register modify 5113 * Parameters: 5114 * unit - Device number 5115 * port - Port number or PHY MDIO address (refer BCM_PORT_PHY_NOMAP) 5116 * flags - Logical OR of one or more of the following flags: 5117 * BCM_PORT_PHY_INTERNAL 5118 * Address internal SERDES PHY for port 5119 * BCM_PORT_PHY_NOMAP 5120 * Instead of mapping port to PHY MDIO address, 5121 * treat port parameter as actual PHY MDIO address. 5122 * BCM_PORT_PHY_CLAUSE45 5123 * Assume Clause 45 device instead of Clause 22 5124 * phy_reg_addr - PHY internal register address 5125 * phy_data - Data to write 5126 * phy_mask - Bits to modify using phy_data 5127 * Returns: 5128 * BCM_E_XXX 5129 */ 5130 int 5131 bcmi_esw_portctrl_phy_modify(int unit, bcm_gport_t port, uint32 flags, 5132 uint32 phy_reg_addr, uint32 phy_data, 5133 uint32 phy_mask) 5134 { 5135 #ifdef PORTMOD_SUPPORT 5136 uint16 phy_id; 5137 uint8 phy_devad; 5138 uint16 phy_reg; 5139 uint16 phy_rd_data; 5140 uint16 phy_wr_data; 5141 uint32 reg_flag; 5142 int rv; 5143 portctrl_pport_t pport=0; 5144 int lane = -1; 5145 uint32 rd_data; 5146 int phyn = -1, sys_side = 0; 5147 bcm_port_t local_port = -1; 5148 5149 /* Make sure port module is initialized. */ 5150 PORTCTRL_INIT_CHECK(unit); 5151 5152 if (!(flags & BCM_PORT_PHY_NOMAP)) { 5153 BCM_IF_ERROR_RETURN 5154 (_bcm_esw_port_gport_phyn_validate(unit, port, 5155 &local_port, &phyn, 5156 &lane, &sys_side)); 5157 5158 if (local_port != -1) { 5159 port = local_port; 5160 } 5161 5162 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 5163 if(!(SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port))) { 5164 return BCM_E_PORT; 5165 } 5166 } 5167 5168 LOG_INFO(BSL_LS_BCM_PORT, 5169 (BSL_META_U(unit, 5170 "portctrl_phy_modify: u=%d p=%d flags=0x%08x " 5171 "phy_reg=0x%08x phy_data=0x%08x phy_mask=0x%08x\n"), 5172 unit, port, flags, phy_reg_addr, phy_data, phy_mask)); 5173 5174 rv = BCM_E_UNAVAIL; 5175 reg_flag = BCM_PORT_PHY_REG_FLAGS(phy_reg_addr); 5176 if (reg_flag & BCM_ESW_PORTCTRL_PHY_REG_INDIRECT) { 5177 if (flags & BCM_PORT_PHY_NOMAP) { 5178 /* Indirect register access is performed through PHY driver. 5179 * Therefore, indirect register access is not supported if 5180 * BCM_PORT_PHY_NOMAP flag is set. 5181 */ 5182 return BCM_E_PARAM; 5183 } 5184 phy_reg_addr &= ~BCM_ESW_PORTCTRL_PHY_REG_INDIRECT; 5185 if (phyn == 1) { 5186 flags |= BCM_PORT_PHY_INTERNAL; 5187 } else { 5188 flags = 0; 5189 } 5190 PORT_LOCK(unit); 5191 rv = portmod_port_phy_reg_read(unit, pport, lane, flags, phy_reg_addr, &rd_data); 5192 PORT_UNLOCK(unit); 5193 5194 phy_data = (rd_data & ~phy_mask) | (phy_data & phy_mask); 5195 5196 PORT_LOCK(unit); 5197 rv = portmod_port_phy_reg_write(unit, pport, lane, flags, phy_reg_addr, phy_data); 5198 PORT_UNLOCK(unit); 5199 } 5200 5201 if (rv == BCM_E_UNAVAIL) { 5202 if (flags & BCM_PORT_PHY_NOMAP) { 5203 phy_id = (uint16) port; 5204 } else if (flags & BCM_PORT_PHY_INTERNAL) { 5205 PORT_LOCK(unit); 5206 phy_id = portmod_port_to_phyaddr_int(unit, pport); 5207 PORT_UNLOCK(unit); 5208 } else { 5209 PORT_LOCK(unit); 5210 phy_id = portmod_port_to_phyaddr(unit, pport); 5211 PORT_UNLOCK(unit); 5212 } 5213 5214 phy_wr_data = (uint16) (phy_data & phy_mask & 0xffff); 5215 PORT_LOCK(unit); 5216 if (flags & BCM_PORT_PHY_CLAUSE45) { 5217 phy_devad = BCM_PORT_PHY_CLAUSE45_DEVAD(phy_reg_addr); 5218 phy_reg = BCM_PORT_PHY_CLAUSE45_REGAD(phy_reg_addr); 5219 rv = soc_miimc45_read(unit, phy_id, phy_devad, 5220 phy_reg, &phy_rd_data); 5221 phy_wr_data |= (phy_rd_data & ~phy_mask); 5222 rv = soc_miimc45_write(unit, phy_id, phy_devad, 5223 phy_reg, phy_wr_data); 5224 } else { 5225 phy_reg = phy_reg_addr; 5226 rv = soc_miim_read(unit, phy_id, phy_reg, &phy_rd_data); 5227 if (BCM_SUCCESS(rv)) { 5228 phy_wr_data |= (phy_rd_data & ~phy_mask); 5229 rv = soc_miim_write(unit, phy_id, phy_reg, phy_wr_data); 5230 } 5231 } 5232 PORT_UNLOCK(unit); 5233 } 5234 return rv; 5235 #else /* PORTMOD_SUPPORT */ 5236 return BCM_E_UNAVAIL; 5237 #endif /* PORTMOD_SUPPORT */ 5238 } 5239 5240 /* 5241 * Function: 5242 * bcmi_esw_portctrl_phy_set 5243 * Description: 5244 * General PHY register write 5245 * Parameters: 5246 * unit - Device number 5247 * port - Port number or PHY MDIO address (refer BCM_PORT_PHY_NOMAP) 5248 * flags - Logical OR of one or more of the following flags: 5249 * BCM_PORT_PHY_INTERNAL 5250 * Address internal SERDES PHY for port 5251 * BCM_PORT_PHY_NOMAP 5252 * Instead of mapping port to PHY MDIO address, 5253 * treat port parameter as actual PHY MDIO address. 5254 * BCM_PORT_PHY_CLAUSE45 5255 * Assume Clause 45 device instead of Clause 22 5256 * phy_reg_addr - PHY internal register address 5257 * phy_data - Data to write 5258 * Returns: 5259 * BCM_E_XXX 5260 */ 5261 int 5262 bcmi_esw_portctrl_phy_set(int unit, bcm_gport_t port, uint32 flags, 5263 uint32 phy_reg_addr, uint32 phy_data) 5264 { 5265 #ifdef PORTMOD_SUPPORT 5266 uint16 phy_id; 5267 uint8 phy_devad; 5268 uint16 phy_reg; 5269 uint16 phy_wr_data; 5270 uint32 reg_flag; 5271 int rv; 5272 portctrl_pport_t pport=0; 5273 int lane = -1; 5274 int phyn = -1, sys_side = 0; 5275 bcm_port_t local_port = -1; 5276 5277 /* Make sure port module is initialized. */ 5278 PORTCTRL_INIT_CHECK(unit); 5279 5280 if (!(flags & BCM_PORT_PHY_NOMAP)) { 5281 BCM_IF_ERROR_RETURN 5282 (_bcm_esw_port_gport_phyn_validate(unit, port, 5283 &local_port, &phyn, 5284 &lane, &sys_side)); 5285 5286 if (local_port != -1) { 5287 port = local_port; 5288 } 5289 5290 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 5291 if(!(SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port))) { 5292 return BCM_E_PORT; 5293 } 5294 } 5295 5296 LOG_INFO(BSL_LS_BCM_PORT, 5297 (BSL_META_U(unit, 5298 "portctrl_phy_set: u=%d p=%d flags=0x%08x " 5299 "phy_reg=0x%08x phy_data=0x%08x\n"), 5300 unit, port, flags, phy_reg_addr, phy_data)); 5301 5302 if (flags & (BCM_PORT_PHY_I2C_DATA8 | BCM_PORT_PHY_I2C_DATA16 | BCM_PORT_PHY_PVT_DATA)) { 5303 PORT_LOCK(unit); 5304 rv = portmod_port_phy_reg_write(unit, pport, lane, flags, phy_reg_addr, phy_data); 5305 PORT_UNLOCK(unit); 5306 return rv; 5307 } 5308 5309 rv = BCM_E_UNAVAIL; 5310 reg_flag = BCM_PORT_PHY_REG_FLAGS(phy_reg_addr); 5311 if (reg_flag & BCM_ESW_PORTCTRL_PHY_REG_INDIRECT) { 5312 if (flags & BCM_PORT_PHY_NOMAP) { 5313 /* Indirect register access is performed through PHY driver. 5314 * Therefore, indirect register access is not supported if 5315 * BCM_PORT_PHY_NOMAP flag is set. 5316 */ 5317 return BCM_E_PARAM; 5318 } 5319 phy_reg_addr &= ~BCM_ESW_PORTCTRL_PHY_REG_INDIRECT; 5320 if (phyn == 1) { 5321 flags |= BCM_PORT_PHY_INTERNAL; 5322 } else { 5323 flags = 0; 5324 } 5325 PORT_LOCK(unit); 5326 rv = portmod_port_phy_reg_write(unit, pport, lane, flags, phy_reg_addr, phy_data); 5327 PORT_UNLOCK(unit); 5328 } 5329 5330 if (rv == BCM_E_UNAVAIL) { 5331 if (flags & BCM_PORT_PHY_NOMAP) { 5332 phy_id = (uint16) port; 5333 } else if (flags & BCM_PORT_PHY_INTERNAL) { 5334 PORT_LOCK(unit); 5335 phy_id = portmod_port_to_phyaddr_int(unit, port); 5336 PORT_UNLOCK(unit); 5337 } else { 5338 PORT_LOCK(unit); 5339 phy_id = portmod_port_to_phyaddr(unit, port); 5340 PORT_UNLOCK(unit); 5341 } 5342 5343 phy_wr_data = (uint16) (phy_data & 0xffff); 5344 PORT_LOCK(unit); 5345 if (flags & BCM_PORT_PHY_CLAUSE45) { 5346 phy_devad = BCM_PORT_PHY_CLAUSE45_DEVAD(phy_reg_addr); 5347 phy_reg = BCM_PORT_PHY_CLAUSE45_REGAD(phy_reg_addr); 5348 rv = soc_miimc45_write(unit, phy_id, phy_devad, 5349 phy_reg, phy_wr_data); 5350 } else { 5351 phy_reg = phy_reg_addr; 5352 rv = soc_miim_write(unit, phy_id, phy_reg, phy_wr_data); 5353 } 5354 PORT_UNLOCK(unit); 5355 } 5356 return rv; 5357 #else /* PORTMOD_SUPPORT */ 5358 return BCM_E_UNAVAIL; 5359 #endif /* PORTMOD_SUPPORT */ 5360 } 5361 5362 /* 5363 * Function: 5364 * bcmi_portctrl_phy_drv_name_get 5365 * Purpose: 5366 * Return the name of the PHY driver being used on a port. 5367 * Parameters: 5368 * unit - StrataSwitch unit # 5369 * port - StrataSwitch port # 5370 * Returns: 5371 * Pointer to static string 5372 */ 5373 int 5374 bcmi_esw_portctrl_phy_drv_name_get(int unit, bcm_gport_t port, char *name, 5375 int len) 5376 { 5377 #ifdef PORTMOD_SUPPORT 5378 int str_len; 5379 int rv; 5380 portctrl_pport_t pport; 5381 5382 /* Make sure port module is initialized. */ 5383 PORTCTRL_INIT_CHECK(unit); 5384 5385 rv = PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport); 5386 5387 if (BCM_FAILURE(rv)) { 5388 str_len = sal_strlen("invalid port"); 5389 if (str_len <= len) { 5390 sal_strncpy(name, "invalid port", len); 5391 } 5392 return BCM_E_PORT; 5393 } 5394 5395 PORT_LOCK(unit); 5396 5397 rv = portmod_port_phy_drv_name_get(unit, pport, name, len); 5398 5399 PORT_UNLOCK(unit); 5400 5401 return rv; 5402 #else /* PORTMOD_SUPPORT */ 5403 return BCM_E_UNAVAIL; 5404 #endif /* PORTMOD_SUPPORT */ 5405 } 5406 5407 /* 5408 * Function: 5409 * bcmi_portctrl_phy_reset 5410 * Description: 5411 * This function performs the low-level PHY reset and is intended to be 5412 * called ONLY from callback function registered with 5413 * bcm_port_phy_reset_register. Attempting to call it from any other 5414 * place will break lots of things. 5415 * Parameters: 5416 * unit - Device number 5417 * port - Port number 5418 * Returns: 5419 * BCM_E_XXX 5420 */ 5421 int 5422 bcmi_esw_portctrl_phy_reset(int unit, bcm_gport_t port) 5423 { 5424 #ifdef PORTMOD_SUPPORT 5425 int rv; 5426 portctrl_pport_t pport; 5427 5428 /* Make sure port module is initialized. */ 5429 PORTCTRL_INIT_CHECK(unit); 5430 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 5431 5432 PORT_LOCK(unit); 5433 rv = portmod_port_reset_set(unit, pport, 5434 phymodResetModeHard /* Hard reset */, 5435 0 /* Not used */, 5436 phymodResetDirectionInOut /* Toggle reset */); 5437 PORT_UNLOCK(unit); 5438 return rv; 5439 #else /* PORTMOD_SUPPORT */ 5440 return BCM_E_UNAVAIL; 5441 #endif /* PORTMOD_SUPPORT */ 5442 } 5443 5444 5445 /* 5446 * Function: 5447 * bcmi_esw_portctrl_ability_advert_get 5448 * Purpose: 5449 * Retrieve the local port advertisement for autonegotiation. 5450 * Parameters: 5451 * unit - StrataSwitch Unit #. 5452 * port - StrataSwitch port #. 5453 * port_ability - (OUT) Local advertisement in bcm_port_ability_t structure. 5454 * ability_mask - (OUT) Local advertisement in bcm_port_abil_t. 5455 * If !NULL, returns mask of BCM_PORT_ABIL_. 5456 * Returns: 5457 * BCM_E_NONE 5458 * BCM_E_XXX 5459 */ 5460 int 5461 bcmi_esw_portctrl_ability_advert_get(int unit, bcm_gport_t port, 5462 bcm_port_ability_t *port_ability, 5463 bcm_port_abil_t *ability_mask) 5464 { 5465 #ifdef PORTMOD_SUPPORT 5466 int rv; 5467 portctrl_pport_t pport; 5468 portmod_port_ability_t portmod_ability; 5469 5470 /* Make sure port module is initialized. */ 5471 PORTCTRL_INIT_CHECK(unit); 5472 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 5473 5474 bcm_port_ability_t_init(port_ability); 5475 sal_memset(&portmod_ability, 0, sizeof(portmod_port_ability_t)); 5476 5477 PORT_LOCK(unit); 5478 #ifdef SW_AUTONEG_SUPPORT 5479 { 5480 int an_mode = 0; 5481 5482 an_mode = soc_property_port_get(unit, port, 5483 spn_PHY_AN_C73, an_mode); 5484 if (soc_feature(unit, soc_feature_sw_autoneg)) { 5485 /* phy_an_c73 value of 3 indicated MSA AN mode 5486 */ 5487 if ((an_mode == SW_AN_MODE_CL73_MSA) || (an_mode == SW_AN_MODE_MSA_ONLY)) { 5488 rv = bcm_sw_an_ability_advert_get(unit, port, port_ability); 5489 if (PORTMOD_SUCCESS(rv)) { 5490 /* Convert to BCM_PORT_ABIL_ mask if needed 5491 */ 5492 if (ability_mask != NULL) { 5493 rv = soc_port_ability_to_mode(port_ability, ability_mask); 5494 } 5495 PORT_UNLOCK(unit); 5496 return rv; 5497 } 5498 } 5499 } 5500 } 5501 #endif 5502 rv = portmod_port_ability_advert_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &portmod_ability); 5503 PORT_UNLOCK(unit); 5504 5505 if (PORTMOD_SUCCESS(rv)) { 5506 _bcm_esw_portctrl_from_portmod_ability(&portmod_ability, port_ability); 5507 5508 /* Convert to BCM_PORT_ABIL_ mask if needed */ 5509 if (ability_mask != NULL) { 5510 rv = soc_port_ability_to_mode(port_ability, ability_mask); 5511 } 5512 } 5513 5514 LOG_VERBOSE(BSL_LS_BCM_PORT, 5515 (BSL_META_UP(unit, port, 5516 "Get port ability advert: u=%d p=%d rv=%d\n"), 5517 unit, port, rv)); 5518 5519 return rv; 5520 5521 #else /* PORTMOD_SUPPORT */ 5522 return BCM_E_UNAVAIL; 5523 #endif /* PORTMOD_SUPPORT */ 5524 } 5525 5526 5527 /* 5528 * Function: 5529 * bcmi_esw_portctrl_ability_advert_set 5530 * Purpose: 5531 * Set the local port advertisement for autonegotiation. 5532 * Parameters: 5533 * unit - StrataSwitch Unit #. 5534 * port - StrataSwitch port #. 5535 * port_ability - Local advertisement in bcm_port_ability_t structure. 5536 * ability_mask - Local advertisement in bcm_port_abil_t. 5537 * If !NULL, returns mask of BCM_PORT_ABIL_. 5538 * Returns: 5539 * BCM_E_NONE 5540 * BCM_E_XXX 5541 * Notes: 5542 * This call MAY NOT restart autonegotiation (depending on the phy). 5543 * To do that, follow this call with bcm_port_autoneg_set(TRUE). 5544 */ 5545 int 5546 bcmi_esw_portctrl_ability_advert_set(int unit, bcm_gport_t port, 5547 bcm_port_ability_t *ability_mask, 5548 bcm_port_abil_t port_abil) 5549 { 5550 #ifdef PORTMOD_SUPPORT 5551 int rv; 5552 portctrl_pport_t pport; 5553 bcm_port_ability_t local_ability, temp_ability_mask, temp_ability; 5554 5555 /* Make sure port module is initialized. */ 5556 PORTCTRL_INIT_CHECK(unit); 5557 5558 sal_memset(&local_ability, 0, sizeof(bcm_port_ability_t)); 5559 sal_memset(&temp_ability_mask, 0, sizeof(bcm_port_ability_t)); 5560 5561 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 5562 5563 BCM_IF_ERROR_RETURN 5564 (bcmi_esw_portctrl_ability_get(unit, port, &local_ability, NULL)); 5565 5566 /* If ability_mask is NULL then it means the call came through 5567 * old API bcm_esw_port_advert_set. We need to convert 5568 * BCM_PORT_ABIL_ mask to bcm_port_ability_t structure */ 5569 if (ability_mask == NULL) { 5570 SOC_IF_ERROR_RETURN(soc_port_mode_to_ability(port_abil, &temp_ability_mask)); 5571 } else { 5572 temp_ability_mask = *ability_mask; 5573 } 5574 /* temporary store speed_half_duplex ability */ 5575 temp_ability.speed_half_duplex = temp_ability_mask.speed_half_duplex; 5576 /* Make sure to advertise only abilities supported by the port */ 5577 SOC_IF_ERROR_RETURN(soc_port_ability_mask(&local_ability, &temp_ability_mask)); 5578 /* restore half duplex speed ability, even if some mac don't support it */ 5579 local_ability.speed_half_duplex = temp_ability.speed_half_duplex; 5580 5581 PORT_LOCK(unit); 5582 #ifdef SW_AUTONEG_SUPPORT 5583 { 5584 int an_mode = 0; 5585 5586 an_mode = soc_property_port_get(unit, port, 5587 spn_PHY_AN_C73, an_mode); 5588 if (soc_feature(unit, soc_feature_sw_autoneg)) { 5589 /* phy_an_c73 value of 3 indicated MSA AN mode 5590 */ 5591 if ((an_mode == SW_AN_MODE_CL73_MSA) || 5592 (an_mode == SW_AN_MODE_MSA_ONLY)) { 5593 rv = bcm_sw_an_ability_advert_set(unit, port, &local_ability); 5594 PORT_UNLOCK(unit); 5595 return rv; 5596 } 5597 } 5598 } 5599 #endif 5600 rv = portmod_port_ability_advert_set(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &local_ability); 5601 PORT_UNLOCK(unit); 5602 5603 LOG_INFO(BSL_LS_BCM_PORT, 5604 (BSL_META_UP(unit, port, 5605 "Set port ability advert: u=%d p=%d rv=%d\n"), 5606 unit, port, rv)); 5607 5608 LOG_VERBOSE(BSL_LS_BCM_PORT, 5609 (BSL_META_UP(unit, port, 5610 "Speed(HD=0x%08x, FD=0x%08x) Pause=0x%08x abl_advert_set\n" 5611 "Interface=0x%08x Medium=0x%08x Loopback=0x%08x Flags=0x%08x\n"), 5612 local_ability.speed_half_duplex, 5613 local_ability.speed_full_duplex, 5614 local_ability.pause, local_ability.interface, 5615 local_ability.medium, local_ability.loopback, 5616 local_ability.flags)); 5617 5618 return rv; 5619 5620 #else /* PORTMOD_SUPPORT */ 5621 return BCM_E_UNAVAIL; 5622 #endif /* PORTMOD_SUPPORT */ 5623 } 5624 5625 /* 5626 * Function: 5627 * bcmi_esw_portctrl_autoneg_get 5628 * Purpose: 5629 * Get the autonegotiation state of the port 5630 * Parameters: 5631 * unit - Unit # 5632 * port - GPORT # 5633 * autoneg - (OUT) Boolean value 5634 * Returns: 5635 * BCM_E_NONE 5636 * BCM_E_XXX 5637 */ 5638 int 5639 bcmi_esw_portctrl_autoneg_get(int unit, bcm_gport_t port, int *autoneg) 5640 { 5641 #ifdef PORTMOD_SUPPORT 5642 int rv; 5643 portctrl_pport_t pport; 5644 int phy_lane = -1; 5645 int phyn = 0, sys_side = 0; 5646 bcm_port_t local_port = -1; 5647 phymod_autoneg_control_t an; 5648 5649 /* Make sure port module is initialized. */ 5650 PORTCTRL_INIT_CHECK(unit); 5651 5652 phymod_autoneg_control_t_init(&an); 5653 5654 BCM_IF_ERROR_RETURN( 5655 _bcm_esw_port_gport_phyn_validate(unit, port, 5656 &local_port, &phyn, 5657 &phy_lane, &sys_side)); 5658 5659 if (local_port != -1) { 5660 port = local_port; 5661 } 5662 5663 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 5664 5665 PORT_LOCK(unit); 5666 if (local_port == -1) { 5667 /* Configure outermost PHY (common case) */ 5668 rv = portmod_port_autoneg_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an); 5669 } else { 5670 /* Configure PHY specified by GPORT */ 5671 rv = portmod_port_redirect_autoneg_get(unit, pport, phyn, 5672 phy_lane, sys_side, &an); 5673 } 5674 PORT_UNLOCK(unit); 5675 5676 if (PORTMOD_SUCCESS(rv)) { 5677 *autoneg = an.enable; 5678 } 5679 5680 LOG_INFO(BSL_LS_BCM_PORT, 5681 (BSL_META_UP(unit, port, 5682 "Get port autoneg: u=%d p=%d an=%d rv=%d\n"), 5683 unit, port, *autoneg, rv)); 5684 5685 return rv; 5686 5687 #else /* PORTMOD_SUPPORT */ 5688 return BCM_E_UNAVAIL; 5689 #endif /* PORTMOD_SUPPORT */ 5690 } 5691 5692 /* 5693 * Function: 5694 * bcmi_esw_portctrl_autoneg_set 5695 * Purpose: 5696 * Set the autonegotiation state for a given port 5697 * Parameters: 5698 * unit - Unit # 5699 * port - GPORT # 5700 * autoneg - Boolean value 5701 * Returns: 5702 * BCM_E_NONE 5703 * BCM_E_XXX 5704 */ 5705 int 5706 bcmi_esw_portctrl_autoneg_set(int unit, bcm_port_t port, int autoneg) 5707 { 5708 #ifdef PORTMOD_SUPPORT 5709 int rv; 5710 portctrl_pport_t pport; 5711 int phy_lane = -1; 5712 int phyn = 0, sys_side = 0; 5713 bcm_port_t local_port = -1; 5714 phymod_autoneg_control_t an; 5715 5716 /* Make sure port module is initialized. */ 5717 PORTCTRL_INIT_CHECK(unit); 5718 5719 #ifdef BCM_RCPU_SUPPORT 5720 if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) { 5721 return BCM_E_PORT; 5722 } 5723 #endif /* BCM_RCPU_SUPPORT */ 5724 5725 phymod_autoneg_control_t_init(&an); 5726 5727 BCM_IF_ERROR_RETURN( 5728 _bcm_esw_port_gport_phyn_validate(unit, port, 5729 &local_port, &phyn, 5730 &phy_lane, &sys_side)); 5731 5732 if (local_port != -1) { 5733 port = local_port; 5734 } 5735 5736 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 5737 5738 BCM_IF_ERROR_RETURN(portmod_port_autoneg_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an)); 5739 an.enable = autoneg; 5740 5741 PORT_LOCK(unit); 5742 #ifdef SW_AUTONEG_SUPPORT 5743 { 5744 int an_mode = 0; 5745 5746 an_mode = soc_property_port_get(unit, port, 5747 spn_PHY_AN_C73, an_mode); 5748 if (soc_feature(unit, soc_feature_sw_autoneg)) { 5749 /* phy_an_c73 value of 3 indicated MSA AN mode 5750 */ 5751 if ((an_mode == SW_AN_MODE_CL73_MSA) || 5752 (an_mode == SW_AN_MODE_MSA_ONLY)) { 5753 if (autoneg) { 5754 rv = bcm_sw_an_port_register(unit, port); 5755 if (rv == BCM_E_NONE) { 5756 PORT_UNLOCK(unit); 5757 return rv; 5758 } else if (rv == BCM_E_PORT) { 5759 /* when an_set is called during the init 5760 * ports wouldn't have been added to SW AN 5761 */ 5762 rv = BCM_E_NONE; 5763 PORT_UNLOCK(unit); 5764 return rv; 5765 } else { 5766 /* add bsl log 5767 */ 5768 PORT_UNLOCK(unit); 5769 return rv; 5770 } 5771 } else { 5772 rv = bcm_sw_an_port_unregister(unit, port); 5773 if (rv == BCM_E_NONE) { 5774 PORT_UNLOCK(unit); 5775 return rv; 5776 } else if (rv == BCM_E_PORT) { 5777 /* when an_set is called during the init 5778 * ports wouldn't have been added to SW AN 5779 */ 5780 rv = BCM_E_NONE; 5781 PORT_UNLOCK(unit); 5782 return rv; 5783 } else { 5784 /* add bsl log */ 5785 PORT_UNLOCK(unit); 5786 return rv; 5787 } 5788 } 5789 } 5790 } 5791 } 5792 #endif 5793 if (local_port == -1) { 5794 /* Configure outermost PHY (common case) */ 5795 rv = portmod_port_autoneg_set(unit, port, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an); 5796 } else { 5797 /* Configure PHY specified by GPORT */ 5798 rv = portmod_port_redirect_autoneg_set(unit, pport, phyn, 5799 phy_lane, sys_side, &an); 5800 } 5801 PORT_UNLOCK(unit); 5802 5803 LOG_INFO(BSL_LS_BCM_PORT, 5804 (BSL_META_UP(unit, port, 5805 "Set port autoneg: u=%d p=%d an=%d rv=%d\n"), 5806 unit, port, autoneg, rv)); 5807 5808 return rv; 5809 5810 #else /* PORTMOD_SUPPORT */ 5811 return BCM_E_UNAVAIL; 5812 #endif /* PORTMOD_SUPPORT */ 5813 } 5814 5815 /* Function: 5816 * bcmi_esw_portctrl_autoneg_ability_advert_get 5817 * Purpose: 5818 * Retrieve the local port advertisement for autonegotiation. 5819 * Parameters: 5820 * unit - StrataSwitch Unit #. 5821 * port - StrataSwtich port #. 5822 * max_num_ability - Maximum number of abilities that can be returned. 5823 * abilities - AN abilities array. 5824 * actual_num_ability - Actual number of abilities in abilities array. 5825 * Returns: 5826 * BCM_E_NONE 5827 * BCM_E_XXX 5828 */ 5829 int 5830 bcmi_esw_portctrl_autoneg_ability_advert_get(int unit, 5831 bcm_gport_t port, 5832 int max_num_ability, 5833 bcm_port_speed_ability_t *abilities, 5834 int *actual_num_ability) 5835 { 5836 #ifdef PORTMOD_SUPPORT 5837 int rv, an_abilities_size = 0; 5838 portctrl_pport_t pport; 5839 portmod_port_speed_ability_t *an_abilities = NULL; 5840 int valid_abilities; 5841 5842 /* Make sure port module is initialized. */ 5843 PORTCTRL_INIT_CHECK(unit); 5844 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 5845 5846 if (abilities == NULL) { 5847 rv = BCM_E_PARAM; 5848 return rv; 5849 } 5850 5851 an_abilities_size = PORTCTRL_AUTONEG_ABILITY_MAX_COUNT; 5852 5853 an_abilities = sal_alloc(an_abilities_size * sizeof(portmod_port_speed_ability_t), "abilities array"); 5854 5855 if (an_abilities == NULL) { 5856 rv = SOC_E_MEMORY; 5857 return rv; 5858 } 5859 5860 sal_memset(an_abilities, 0, an_abilities_size * sizeof(portmod_port_speed_ability_t)); 5861 *actual_num_ability = 0; 5862 5863 PORT_LOCK(unit); 5864 rv = portmod_port_autoneg_ability_advert_get(unit, pport, an_abilities_size, an_abilities, actual_num_ability); 5865 PORT_UNLOCK(unit); 5866 5867 if (PORTMOD_SUCCESS(rv)) { 5868 BCM_IF_ERROR_RETURN(_bcm_esw_portctrl_from_portmod_autoneg_ability(unit, 5869 *actual_num_ability, an_abilities, max_num_ability, 5870 abilities, &valid_abilities)); 5871 *actual_num_ability = valid_abilities; 5872 } 5873 5874 LOG_VERBOSE(BSL_LS_BCM_PORT, 5875 (BSL_META_UP(unit, port, 5876 "Get port autoneg advert ability: u=%d p=%d rv=%d\n"), 5877 unit, port, rv)); 5878 if (NULL != an_abilities) { 5879 sal_free(an_abilities); 5880 } 5881 return rv; 5882 #else /* PORTMOD_SUPPORT */ 5883 return BCM_E_UNAVAIL; 5884 #endif /* PORTMOD_SUPPORT */ 5885 } 5886 5887 /* 5888 * Function: 5889 * bcmi_esw_portctrl_autoneg_ability_advert_set 5890 * Purpose: 5891 * Set the local port advertisement for autonegotiation. 5892 * Only applicable to PM8x50. 5893 * Parameters: 5894 * unit - StrataSwitch Unit #. 5895 * port - StrataSwtich port #. 5896 * num_ability - Number of local advertising abilities. 5897 * abilities - AN abilities array. 5898 * Returns: 5899 * BCM_E_NONE 5900 * BCM_E_XXX 5901 * Notes: 5902 * This call will not start autonegotiation. 5903 * To do that, follow this call with bcm_port_autoneg_set(TRUE). 5904 */ 5905 int 5906 bcmi_esw_portctrl_autoneg_ability_advert_set(int unit, 5907 bcm_gport_t port, 5908 int num_ability, 5909 bcm_port_speed_ability_t *abilities) 5910 { 5911 #ifdef PORTMOD_SUPPORT 5912 int rv = BCM_E_NONE; 5913 portctrl_pport_t pport; 5914 int num_lanes, max_speed, i; 5915 char *str=""; 5916 portmod_port_speed_ability_t *an_abilities = NULL; 5917 5918 /* Make sure port module is initialized. */ 5919 PORTCTRL_INIT_CHECK(unit); 5920 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 5921 5922 if (abilities == NULL) { 5923 rv = BCM_E_PARAM; 5924 return rv; 5925 } 5926 5927 num_lanes = SOC_INFO(unit).port_num_lanes[port]; 5928 max_speed = SOC_INFO(unit).port_speed_max[port]; 5929 5930 /* In this layer, we only do max_speed and num_lane check */ 5931 /* PORTMOD will do more validation during autoneg_ability_advert_set */ 5932 for (i = 0; i < num_ability; i++) { 5933 if (abilities[i].speed > max_speed) { 5934 str = "abilities.speed exceeds port's maximum speed:"; 5935 rv = BCM_E_CONFIG; 5936 break; 5937 } 5938 if (abilities[i].resolved_num_lanes > num_lanes) { 5939 str = "abilities.resolved_num_lanes exceeds port's number of lanes:"; 5940 rv = BCM_E_CONFIG; 5941 break; 5942 } 5943 } 5944 5945 if (num_ability > PORTCTRL_AUTONEG_ABILITY_MAX_COUNT) { 5946 str = "Too many abilities requested:"; 5947 rv = BCM_E_CONFIG; 5948 } 5949 5950 if (PORTMOD_FAILURE(rv)) { 5951 LOG_VERBOSE(BSL_LS_BCM_PORT, 5952 (BSL_META_UP(unit, port, "autoneg_ablity_advert_set: %s\nport=%d," 5953 "rv=%d\n"), str, port, rv)); 5954 return rv; 5955 } 5956 5957 an_abilities = sal_alloc(num_ability * sizeof(portmod_port_speed_ability_t), "abilities array"); 5958 if (an_abilities == NULL) { 5959 rv = SOC_E_MEMORY; 5960 return rv; 5961 } 5962 sal_memset(an_abilities, 0, num_ability * sizeof(portmod_port_speed_ability_t)); 5963 5964 _bcm_esw_portmod_from_portctrl_autoneg_ability(num_ability, abilities, an_abilities); 5965 5966 PORT_LOCK(unit); 5967 rv = portmod_port_autoneg_ability_advert_set(unit, pport, num_ability, an_abilities); 5968 PORT_UNLOCK(unit); 5969 5970 LOG_INFO(BSL_LS_BCM_PORT, 5971 (BSL_META_UP(unit, port, 5972 "Set port autoneg advert ability: u=%d p=%d rv=%d\n"), 5973 unit, port, rv)); 5974 if (NULL != an_abilities) { 5975 sal_free(an_abilities); 5976 } 5977 return rv; 5978 #else /* PORTMOD_SUPPORT */ 5979 return BCM_E_UNAVAIL; 5980 #endif /* PORTMOD_SUPPORT */ 5981 } 5982 5983 /* 5984 * Function: 5985 * bcmi_esw_portctrl_duplex_get 5986 * Purpose: 5987 * Get the port duplex settings 5988 * Parameters: 5989 * unit - StrataSwitch Unit #. 5990 * port - StrataSwitch port #. 5991 * duplex - (OUT) Duplex setting, one of SOC_PORT_DUPLEX_xxx 5992 * Returns: 5993 * BCM_E_NONE 5994 * BCM_E_XXX 5995 */ 5996 int 5997 bcmi_esw_portctrl_duplex_get(int unit, bcm_gport_t port, int *duplex) 5998 { 5999 #ifdef PORTMOD_SUPPORT 6000 int rv; 6001 portctrl_pport_t pport; 6002 6003 /* Make sure port module is initialized. */ 6004 PORTCTRL_INIT_CHECK(unit); 6005 6006 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6007 6008 PORT_LOCK(unit); 6009 rv = soc_esw_portctrl_duplex_get(unit, port, duplex); 6010 PORT_UNLOCK(unit); 6011 6012 LOG_INFO(BSL_LS_BCM_PORT, 6013 (BSL_META_UP(unit, port, 6014 "Get port duplex: u=%d p=%d dup=%d rv=%d\n"), 6015 unit, port, *duplex, rv)); 6016 6017 return rv; 6018 6019 #else /* PORTMOD_SUPPORT */ 6020 return BCM_E_UNAVAIL; 6021 #endif /* PORTMOD_SUPPORT */ 6022 } 6023 6024 /* 6025 * Function: 6026 * bcmi_esw_portctrl_duplex_set 6027 * Purpose: 6028 * Set the port duplex settings. 6029 * Parameters: 6030 * unit - StrataSwitch Unit #. 6031 * port - StrataSwitch port #. 6032 * duplex - Duplex setting, one of SOC_PORT_DUPLEX_xxx 6033 * Returns: 6034 * BCM_E_NONE 6035 * BCM_E_XXX 6036 * Notes: 6037 * Turns off autonegotiation. Caller must make sure other forced 6038 * parameters (such as speed) are set. 6039 */ 6040 int 6041 bcmi_esw_portctrl_duplex_set(int unit, bcm_port_t port, int duplex) 6042 { 6043 #ifdef PORTMOD_SUPPORT 6044 int rv; 6045 pbmp_t pbm; 6046 portctrl_pport_t pport; 6047 6048 /* Make sure port module is initialized. */ 6049 PORTCTRL_INIT_CHECK(unit); 6050 6051 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6052 6053 #ifdef BCM_RCPU_SUPPORT 6054 if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) { 6055 return BCM_E_PORT; 6056 } 6057 #endif /* BCM_RCPU_SUPPORT */ 6058 6059 #if 0 6060 /* Disable auto-negotiation if duplex is forced */ 6061 rv = bcmi_esw_portctrl_autoneg_set(unit, port, FALSE); 6062 if (BCM_FAILURE(rv)) { 6063 LOG_VERBOSE(BSL_LS_BCM_PORT, 6064 (BSL_META_UP(unit, port, 6065 "Set port autonego failed:%s\n"), 6066 bcm_errmsg(rv))); 6067 return rv; 6068 } 6069 #endif 6070 6071 PORT_LOCK(unit); 6072 6073 rv = soc_esw_portctrl_duplex_set(unit, pport, duplex); 6074 6075 PORT_UNLOCK(unit); /* Unlock before link call */ 6076 6077 if (PORTMOD_SUCCESS(rv) && !SAL_BOOT_SIMULATION) { 6078 /* Force link change event */ 6079 SOC_PBMP_CLEAR(pbm); 6080 SOC_PBMP_PORT_ADD(pbm, port); 6081 (void)bcm_esw_link_change(unit, pbm); 6082 } 6083 6084 LOG_INFO(BSL_LS_BCM_PORT, 6085 (BSL_META_UP(unit, port, 6086 "Set port duplex: u=%d p=%d dup=%d rv=%d\n"), 6087 unit, port, duplex, rv)); 6088 6089 return rv; 6090 6091 #else /* PORTMOD_SUPPORT */ 6092 return BCM_E_UNAVAIL; 6093 #endif /* PORTMOD_SUPPORT */ 6094 } 6095 6096 /* 6097 * Function: 6098 * bcmi_esw_portctrl_clear_rx_lss_status_set 6099 * Purpose: 6100 * set the local and remote fault fields of the lss status register. 6101 * Parameters: 6102 * unit - (IN) Unit number. 6103 * port - (IN) Port number. 6104 * local_fault - (IN) value of local fault field to be set. 6105 * remote_fault - (IN) value of remote fault field to be set. 6106 * Returns: 6107 * BCM_E_NONE 6108 * BCM_E_XXX 6109 */ 6110 6111 int 6112 bcmi_esw_portctrl_clear_rx_lss_status_set(int unit, bcm_gport_t port, 6113 int local_fault, int remote_fault) 6114 { 6115 #ifdef PORTMOD_SUPPORT 6116 int rv = BCM_E_NONE; 6117 portctrl_pport_t pport; 6118 6119 PORTCTRL_INIT_CHECK(unit); 6120 6121 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6122 6123 PORT_LOCK(unit); 6124 rv = portmod_port_clear_rx_lss_status_set(unit, pport, local_fault, 6125 remote_fault); 6126 PORT_UNLOCK(unit); 6127 return rv; 6128 #else /* PORTMOD_SUPPORT */ 6129 return BCM_E_UNAVAIL; 6130 #endif /* PORTMOD_SUPPORT */ 6131 } 6132 6133 /* 6134 * Function: 6135 * bcmi_esw_portctrl_mode_setup 6136 * Purpose: 6137 * Set initial operating mode for a port. 6138 * Parameters: 6139 * unit - StrataSwitch unit #. 6140 * port - StrataSwitch port #. 6141 * enable - Whether to enable or disable 6142 * Returns: 6143 * BCM_E_XXX 6144 * Notes: 6145 * Must be called with PORT_LOCK held. 6146 */ 6147 int 6148 bcmi_esw_portctrl_mode_setup(int unit, bcm_gport_t port, int enable) 6149 { 6150 #ifdef PORTMOD_SUPPORT 6151 #if 0 6152 soc_port_if_t pif; 6153 #endif 6154 portmod_port_ability_t local_port_ability, advert_port_ability; 6155 portctrl_pport_t pport; 6156 int rv = BCM_E_NONE; 6157 6158 PORTCTRL_INIT_CHECK(unit); 6159 6160 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6161 6162 if (IS_TDM_PORT(unit, port)) { 6163 return BCM_E_NONE; 6164 } 6165 6166 LOG_INFO(BSL_LS_BCM_PORT, 6167 (BSL_META_U(unit, 6168 "_bcm_port_mode_setup: u=%d p=%d\n"), unit, port)); 6169 6170 sal_memset(&local_port_ability, 0, sizeof(bcm_port_ability_t)); 6171 sal_memset(&advert_port_ability, 0, sizeof(bcm_port_ability_t)); 6172 6173 PORT_LOCK(unit); 6174 if (!IS_CD_PORT(unit, pport)) { 6175 rv = portmod_port_ability_local_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &local_port_ability); 6176 } 6177 PORT_UNLOCK(unit); 6178 6179 PORTMOD_IF_ERROR_RETURN(rv); 6180 6181 #if 0 6182 /* If MII supported, enable it, otherwise use TBI */ 6183 if (local_port_ability.interface & (SOC_PA_INTF_MII | SOC_PA_INTF_GMII | 6184 SOC_PA_INTF_SGMII | SOC_PA_INTF_XGMII)) { 6185 if (IS_GE_PORT(unit, port)) { 6186 pif = SOC_PORT_IF_GMII; 6187 } else if (IS_HG_PORT(unit, port) || IS_XE_PORT(unit, port)) { 6188 if (local_port_ability.interface & SOC_PA_INTF_XGMII) { 6189 pif = SOC_PORT_IF_XGMII; 6190 } else { /* external GbE phy in xe port mode */ 6191 pif = SOC_PORT_IF_SGMII; 6192 } 6193 } else { 6194 pif = SOC_PORT_IF_MII; 6195 } 6196 } else if (local_port_ability.interface & SOC_PA_INTF_CGMII) { 6197 pif = SOC_PORT_IF_CGMII; 6198 } else { 6199 pif = SOC_PORT_IF_TBI; 6200 } 6201 6202 SOC_IF_ERROR_RETURN 6203 (soc_phyctrl_interface_set(unit, port, pif)); 6204 _bcm_esw_portctrl_interface_config_set(unit, port, pport, config, 0); 6205 #endif 6206 6207 if (IS_ST_PORT(unit, port)) { 6208 6209 /* Since stacking port doesn't support flow control, 6210 * make sure that PHY is not advertising flow control capabilities. 6211 */ 6212 6213 PORT_LOCK(unit); 6214 rv = portmod_port_ability_advert_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &advert_port_ability); 6215 if (PORTMOD_SUCCESS(rv)) { 6216 advert_port_ability.pause &= ~(SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM); 6217 rv = portmod_port_ability_advert_set(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, 6218 &advert_port_ability); 6219 } 6220 PORT_UNLOCK(unit); 6221 } 6222 6223 PORTMOD_IF_ERROR_RETURN(rv); 6224 6225 if (!SOC_WARM_BOOT(unit) && 6226 !(SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit, all), port)) ) { 6227 #ifdef BCM_RCPU_SUPPORT 6228 if (SOC_IS_RCPU_ONLY(unit) && IS_RCPU_PORT(unit, port)) { 6229 /* Do not enable/disable rcpu port. */ 6230 return BCM_E_NONE; 6231 } 6232 #endif /* BCM_RCPU_SUPPORT */ 6233 PORT_LOCK(unit); 6234 rv = _bcm_esw_portctrl_enable_set(unit, port, pport, 6235 PORTMOD_PORT_ENABLE_MAC, enable); 6236 PORT_UNLOCK(unit); 6237 BCM_IF_ERROR_RETURN(rv); 6238 } 6239 6240 return BCM_E_NONE; 6241 #else /* PORTMOD_SUPPORT */ 6242 return BCM_E_UNAVAIL; 6243 #endif /* PORTMOD_SUPPORT */ 6244 } 6245 6246 6247 /* 6248 * Function: 6249 * bcmi_esw_portctrl_clear_rx_lss_status_get 6250 * Purpose: 6251 * get the local and remote fault fields of the lss status register. 6252 * Parameters: 6253 * unit - (IN) Unit number. 6254 * port - (IN) Port number. 6255 * local_fault - (OUT) value of local fault field to get. 6256 * remote_fault - (OUT) value of remote fault field to get. 6257 * Returns: 6258 * BCM_E_NONE 6259 * BCM_E_XXX 6260 */ 6261 6262 int 6263 bcmi_esw_portctrl_clear_rx_lss_status_get(int unit, bcm_gport_t port, 6264 int *local_fault, 6265 int *remote_fault) 6266 { 6267 #ifdef PORTMOD_SUPPORT 6268 int rv = BCM_E_NONE; 6269 portctrl_pport_t pport; 6270 6271 PORTCTRL_INIT_CHECK(unit); 6272 6273 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6274 6275 PORT_LOCK(unit); 6276 rv = portmod_port_clear_rx_lss_status_get(unit, pport, local_fault, 6277 remote_fault); 6278 PORT_UNLOCK(unit); 6279 return rv; 6280 #else /* PORTMOD_SUPPORT */ 6281 return BCM_E_UNAVAIL; 6282 #endif /* PORTMOD_SUPPORT */ 6283 } 6284 6285 /* 6286 * Function: 6287 * _bcm_esw_portctrl_detach 6288 * Purpose: 6289 * Main part of bcm_port_detach 6290 */ 6291 6292 #ifdef PORTMOD_SUPPORT 6293 STATIC int 6294 _bcm_esw_portctrl_detach(int unit, pbmp_t pbmp, pbmp_t *detached) 6295 { 6296 soc_port_t port; 6297 portctrl_pport_t pport; 6298 soc_persist_t *sop = SOC_PERSIST(unit); 6299 int rv; 6300 int flags = 0; 6301 portmod_port_add_info_t port_add_info; 6302 int num_lanes; 6303 int lane; 6304 #if defined(PORTMOD_SUPPORT) && defined(PORTMOD_PM8X50_SUPPORT) 6305 int phy_port; 6306 int lanes_per_pm; 6307 int pm; 6308 portmod_dispatch_type_t pm_type; 6309 portmod_pm_capability_t pm_cap; 6310 #endif 6311 6312 PORTMOD_PORT_ENABLE_PHY_SET(flags); 6313 PORTMOD_PORT_ENABLE_MAC_SET(flags); 6314 6315 SOC_PBMP_CLEAR(*detached); 6316 6317 SOC_PBMP_ITER(pbmp, port) { 6318 6319 BCM_IF_ERROR_RETURN 6320 (bcm_esw_port_stp_set(unit, port, BCM_STG_STP_DISABLE)); 6321 rv = bcmi_esw_portctrl_mode_setup(unit, port, FALSE); 6322 BCM_IF_ERROR_RETURN(rv); 6323 6324 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6325 BCM_IF_ERROR_RETURN 6326 (_bcm_esw_portctrl_enable_set(unit, port, pport, flags, 0)); 6327 PORTMOD_IF_ERROR_RETURN(portmod_port_remove(unit, port)); 6328 6329 PORTMOD_IF_ERROR_RETURN(portmod_port_add_info_t_init(unit, &port_add_info)); 6330 port_add_info.interface_config.interface = SOC_PORT_IF_NULL; 6331 PORTMOD_IF_ERROR_RETURN(portmod_port_add(unit, port, &port_add_info)); 6332 6333 SOC_PBMP_PORT_ADD(*detached, port); 6334 6335 if (SOC_PBMP_MEMBER(sop->lc_pbm_fc, port)) { 6336 /* Bring down the internal PHY */ 6337 rv = bcm_esw_port_update(unit, port, FALSE); 6338 BCM_IF_ERROR_RETURN(rv); 6339 SOC_PBMP_PORT_REMOVE(sop->lc_pbm_fc, port); 6340 } 6341 6342 #if defined(PORTMOD_SUPPORT) && defined(PORTMOD_PM8X50_SUPPORT) 6343 if (IS_CD_PORT(unit, port)) { 6344 soc_counter_port_pbmp_remove(unit, port); 6345 6346 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 6347 BCM_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type)); 6348 PORTMOD_IF_ERROR_RETURN( 6349 portmod_pm_capability_get(unit, pm_type, &pm_cap)); 6350 lanes_per_pm = pm_cap.pm_capability.pm8x50_cap.num_lanes; 6351 pm = (phy_port - 1) / lanes_per_pm; 6352 SOC_INFO(unit).pm_vco_info[pm].is_tvco_new = 1; 6353 SOC_INFO(unit).pm_vco_info[pm].is_ovco_new = 1; 6354 SOC_IF_ERROR_RETURN( 6355 soc_esw_portctrl_pm_vco_reconfigure(unit)); 6356 } 6357 #endif 6358 6359 /* 6360 * Detach xphy lanes from the port. 6361 */ 6362 num_lanes = SOC_INFO(unit).port_num_lanes[port]; 6363 /* 6364 * Need to change to 12 because not pm12x10 mode are consecutive lanes. 6365 * Only 442 is, other like 343 and 244 skip 1 and 2 lanes in the middle. 6366 */ 6367 if (num_lanes == 10) { 6368 num_lanes=12; 6369 } 6370 for (lane = 0; lane < num_lanes; lane++) { 6371 #ifdef BCM_TOMAHAWK3_SUPPORT 6372 /* Tomahawk 3's Management Port Macro requires a spacing between 6373 * the lanes, so even though the two management ports' physical 6374 * ports are 257 and 258, the lane needs to be the next one, 6375 * so logical port 118 being mapped to physical port 258 needs 6376 * to pass 259 to portmod because portmod only recognizes lane 6377 * 0 (physical port 257) and lane 2 (physial port 259). 6378 */ 6379 if (SOC_IS_TOMAHAWK3(unit) && port == 118) { 6380 portmod_xphy_lane_detach(unit, 259, 1); 6381 } 6382 else 6383 #endif 6384 { 6385 portmod_xphy_lane_detach(unit, 6386 SOC_INFO(unit).port_l2p_mapping[port]+lane, 1); 6387 } 6388 } 6389 } 6390 6391 return BCM_E_NONE; 6392 } 6393 #endif /* PORTMOD_SUPPORT */ 6394 6395 /* 6396 * Function: 6397 * bcmi_esw_portctrl_detach 6398 * Purpose: 6399 * Detach a port. Set phy driver to no connection. 6400 * Parameters: 6401 * unit - StrataSwitch unit number. 6402 * pbmp - Bitmap of ports to detach. 6403 * detached (OUT) - Bitmap of ports successfully detached. 6404 * Returns: 6405 * BCM_E_NONE 6406 * BCM_E_INTERNAL - internal error. 6407 * Notes: 6408 * If a port to be detached does not appear in detached, its 6409 * state is not defined. 6410 */ 6411 6412 int 6413 bcmi_esw_portctrl_detach(int unit, pbmp_t pbmp, pbmp_t *detached) 6414 { 6415 #ifdef PORTMOD_SUPPORT 6416 char pfmtp[SOC_PBMP_FMT_LEN], 6417 pfmtd[SOC_PBMP_FMT_LEN]; 6418 int rv = BCM_E_NONE; 6419 6420 PORTCTRL_INIT_CHECK(unit); 6421 6422 PORT_LOCK(unit); 6423 6424 rv = _bcm_esw_portctrl_detach(unit, pbmp, detached); 6425 6426 PORT_UNLOCK(unit); 6427 6428 LOG_INFO(BSL_LS_BCM_PORT, 6429 (BSL_META_U(unit, 6430 "bcm_port_detach: u=%d pbmp=%s det=%s rv=%d\n"), 6431 unit, 6432 SOC_PBMP_FMT(pbmp, pfmtp), 6433 SOC_PBMP_FMT(*detached, pfmtd), 6434 rv)); 6435 6436 return rv; 6437 #else /* PORTMOD_SUPPORT */ 6438 return BCM_E_UNAVAIL; 6439 #endif /* PORTMOD_SUPPORT */ 6440 } 6441 6442 /* 6443 * Function: 6444 * bcmi_esw_portctrl_frame_max_get 6445 * Purpose: 6446 * Get the maximum receive frame size for the port. 6447 * Parameters: 6448 * unit - (IN) Unit number. 6449 * port - (IN) Port number. 6450 * size - (OUT) Maximum frame size in bytes. 6451 * Returns: 6452 * BCM_E_XXX 6453 * Notes: 6454 * Depending on chip or port type the actual maximum receive frame size 6455 * might be slightly higher. 6456 * 6457 * For GE ports that use 2 separate MACs (one for GE and another one for 6458 * 10/100 modes) the function returns the maximum rx frame size set for 6459 * the current mode. 6460 */ 6461 int 6462 bcmi_esw_portctrl_frame_max_get(int unit, bcm_gport_t port, int *size) 6463 { 6464 #ifdef PORTMOD_SUPPORT 6465 int rv; 6466 portctrl_pport_t pport; 6467 6468 PORTCTRL_INIT_CHECK(unit); 6469 6470 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6471 6472 PORT_LOCK(unit); 6473 rv = soc_esw_portctrl_frame_max_get(unit, port, size); 6474 PORT_UNLOCK(unit); 6475 6476 return rv; 6477 #else /* PORTMOD_SUPPORT */ 6478 return BCM_E_UNAVAIL; 6479 #endif /* PORTMOD_SUPPORT */ 6480 } 6481 6482 /* 6483 * Function: 6484 * bcmi_esw_portctrl_ifg_set 6485 * Purpose: 6486 * Set Inter Frame Gap 6487 * Parameters: 6488 * unit - StrataSwitch unit number. 6489 * port - Port. 6490 * speed - Speed 6491 * duplex - Duplex Setting 6492 * ifg - InterFrame Gap 6493 * Returns: 6494 * BCM_E_NONE 6495 * BCM_E_INTERNAL - internal error. 6496 * Notes: 6497 */ 6498 int 6499 bcmi_esw_portctrl_ifg_set(int unit, bcm_gport_t port, int speed, 6500 bcm_port_duplex_t duplex, int ifg) 6501 { 6502 #ifdef PORTMOD_SUPPORT 6503 int rv; 6504 portctrl_pport_t pport; 6505 6506 PORTCTRL_INIT_CHECK(unit); 6507 6508 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6509 6510 PORT_LOCK(unit); 6511 rv = soc_esw_portctrl_ifg_set(unit, port, speed, duplex, ifg); 6512 PORT_UNLOCK(unit); 6513 6514 return rv; 6515 #else /* PORTMOD_SUPPORT */ 6516 return BCM_E_UNAVAIL; 6517 #endif /* PORTMOD_SUPPORT */ 6518 } 6519 6520 /* 6521 * Function: 6522 * bcmi_esw_portctrl_frame_max_set 6523 * Purpose: 6524 * Set the maximum receive frame size for the port. 6525 6526 * Parameters: 6527 * unit - (IN) Unit number. 6528 * port - (IN) Port number. 6529 * mac - (IN) Station MAC address used for pause frames. 6530 * Returns: 6531 * BCM_E_XXX 6532 */ 6533 int 6534 bcmi_esw_portctrl_frame_max_set(int unit, bcm_gport_t port, int size) 6535 { 6536 #ifdef PORTMOD_SUPPORT 6537 int rv; 6538 portctrl_pport_t pport; 6539 6540 PORTCTRL_INIT_CHECK(unit); 6541 6542 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6543 6544 PORT_LOCK(unit); 6545 rv = soc_esw_portctrl_frame_max_set(unit, port, size); 6546 PORT_UNLOCK(unit); 6547 6548 return rv; 6549 6550 #else /* PORTMOD_SUPPORT */ 6551 return BCM_E_UNAVAIL; 6552 #endif /* PORTMOD_SUPPORT */ 6553 } 6554 6555 /* 6556 * Function: 6557 * bcmi_esw_portctrl_ifg_get 6558 * Purpose: 6559 * Set Inter Frame Gap 6560 * Parameters: 6561 * unit - StrataSwitch unit number. 6562 * port - Port. 6563 * speed - Speed 6564 * duplex - Duplex Setting 6565 * ifg - InterFrame Gap 6566 * Returns: 6567 * BCM_E_NONE 6568 * BCM_E_INTERNAL - internal error. 6569 * Notes: 6570 */ 6571 int 6572 bcmi_esw_portctrl_ifg_get(int unit, bcm_gport_t port, int speed, 6573 bcm_port_duplex_t duplex, int *ifg) 6574 { 6575 #ifdef PORTMOD_SUPPORT 6576 int rv; 6577 portctrl_pport_t pport; 6578 6579 PORTCTRL_INIT_CHECK(unit); 6580 6581 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6582 6583 PORT_LOCK(unit); 6584 rv = soc_esw_portctrl_ifg_get(unit, port, speed, duplex, ifg); 6585 PORT_UNLOCK(unit); 6586 6587 return rv; 6588 #else /* PORTMOD_SUPPORT */ 6589 return BCM_E_UNAVAIL; 6590 #endif /* PORTMOD_SUPPORT */ 6591 } 6592 6593 /* 6594 * Function: 6595 * bcmi_esw_portctrl_mac_rx_control 6596 * Purpose: 6597 * Set Inter Frame Gap 6598 * Parameters: 6599 * unit - StrataSwitch unit number. 6600 * port - Port. 6601 * optype - operation type 6602 * enable - enable/disable 6603 * Returns: 6604 * BCM_E_NONE 6605 * BCM_E_INTERNAL - internal error. 6606 * Notes: 6607 */ 6608 6609 int 6610 bcmi_esw_portctrl_mac_rx_control(int unit, bcm_port_t port, uint8 optype, int *enable) 6611 { 6612 #ifdef PORTMOD_SUPPORT 6613 int rv = BCM_E_NONE; 6614 6615 PORT_LOCK(unit); 6616 if(optype) { 6617 rv = portmod_port_rx_mac_enable_get(unit, port, enable); 6618 } else { 6619 rv = portmod_port_rx_mac_enable_set(unit, port, *enable); 6620 } 6621 PORT_UNLOCK(unit); 6622 return(rv); 6623 #else /* PORTMOD_SUPPORT */ 6624 return BCM_E_UNAVAIL; 6625 #endif /* PORTMOD_SUPPORT */ 6626 } 6627 6628 /* 6629 * Function: 6630 * bcmi_esw_portctrl_mac_up 6631 * Purpose: 6632 * Bring up MAC 6633 * Parameters: 6634 * unit - (IN) StrataSwitch unit number. 6635 * nport - (IN) Number of elements in array port 6636 * port - (IN) Array of logical port. 6637 * Returns: 6638 * BCM_E_NONE 6639 * BCM_E_INTERNAL - internal error. 6640 * Notes: 6641 */ 6642 int 6643 bcmi_esw_portctrl_mac_up(int unit, int nport, bcm_port_t *port) 6644 { 6645 #ifdef PORTMOD_SUPPORT 6646 int i; 6647 bcm_port_t lport; 6648 portctrl_pport_t pport; 6649 6650 for (i = 0; i < nport; i++) { 6651 lport = port[i]; 6652 6653 BCM_IF_ERROR_RETURN 6654 (PORTCTRL_PORT_RESOLVE(unit, lport, &lport, &pport)); 6655 6656 /* Remove MAC reset */ 6657 BCM_IF_ERROR_RETURN 6658 (portmod_port_mac_reset_set(unit, pport, 0)); 6659 6660 /* Disable port flush state */ 6661 BCM_IF_ERROR_RETURN 6662 (portmod_port_discard_set(unit, pport, 0) ); 6663 6664 /* Enable MAC TX */ 6665 BCM_IF_ERROR_RETURN 6666 (portmod_port_rx_mac_enable_set(unit, pport, 1)); 6667 6668 /* Enable MAC RX */ 6669 BCM_IF_ERROR_RETURN 6670 (portmod_port_tx_mac_enable_set(unit, pport, 1)); 6671 } 6672 return BCM_E_NONE; 6673 #else /* PORTMOD_SUPPORT */ 6674 return BCM_E_UNAVAIL; 6675 #endif /* PORTMOD_SUPPORT */ 6676 } 6677 6678 /* 6679 * Function: 6680 * bcmi_esw_portctrl_mac_rx_down 6681 * Purpose: 6682 * Disable MAC receive 6683 * Parameters: 6684 * unit - (IN) StrataSwitch unit number. 6685 * nport - (IN) Number of elements in array port 6686 * port - (IN) Array of logical port. 6687 * Returns: 6688 * BCM_E_NONE 6689 * BCM_E_INTERNAL - internal error. 6690 * Notes: 6691 */ 6692 int 6693 bcmi_esw_portctrl_mac_rx_down(int unit, int nport, bcm_port_t *port) 6694 { 6695 #ifdef PORTMOD_SUPPORT 6696 int i; 6697 bcm_port_t lport; 6698 portctrl_pport_t pport; 6699 portmod_pfc_control_t pfc_control; 6700 6701 for (i = 0; i < nport; i++) { 6702 lport = port[i]; 6703 6704 BCM_IF_ERROR_RETURN 6705 (PORTCTRL_PORT_RESOLVE(unit, lport, &lport, &pport)); 6706 6707 /* Disable MAC RX */ 6708 BCM_IF_ERROR_RETURN 6709 (portmod_port_rx_mac_enable_set(unit, pport, 0)); 6710 6711 /* TH3 will not suffer from overflow like other devices, 6712 * but putting the mac into reset will prevent packets 6713 * from being drained, so only set discard */ 6714 if (!SOC_IS_TOMAHAWK3(unit)) { 6715 /* Hold MAC in reset state */ 6716 BCM_IF_ERROR_RETURN 6717 (portmod_port_mac_reset_set(unit, pport, 1)); 6718 } 6719 6720 /* Put port in flush state */ 6721 BCM_IF_ERROR_RETURN 6722 (portmod_port_discard_set(unit, pport, 1) ); 6723 6724 if (!SOC_IS_TOMAHAWK3(unit)) { 6725 /* Remove MAC reset */ 6726 BCM_IF_ERROR_RETURN 6727 (portmod_port_mac_reset_set(unit, pport, 0)); 6728 } 6729 6730 /* WAR for SDK-183541/TH3-5475*/ 6731 if (SOC_IS_TOMAHAWK3(unit)) { 6732 if (soc_feature(unit, soc_feature_priority_flow_control)) { 6733 /* Toggle Force PFC XON */ 6734 BCM_IF_ERROR_RETURN 6735 (portmod_port_pfc_control_get(unit, pport, &pfc_control)); 6736 pfc_control.force_xon = 1; 6737 BCM_IF_ERROR_RETURN 6738 (portmod_port_pfc_control_set(unit, pport, &pfc_control)); 6739 pfc_control.force_xon = 0; 6740 BCM_IF_ERROR_RETURN 6741 (portmod_port_pfc_control_set(unit, pport, &pfc_control)); 6742 } 6743 } 6744 6745 } 6746 return BCM_E_NONE; 6747 #else /* PORTMOD_SUPPORT */ 6748 return BCM_E_UNAVAIL; 6749 #endif /* PORTMOD_SUPPORT */ 6750 } 6751 6752 /* 6753 * Function: 6754 * bcmi_esw_portctrl_mac_tx_down 6755 * Purpose: 6756 * Poll until MAC TX FIFO is empty 6757 * Disable MAC transmit 6758 * Parameters: 6759 * unit - (IN) StrataSwitch unit number. 6760 * nport - (IN) Number of elements in array port 6761 * port - (IN) Array of logical port. 6762 * Returns: 6763 * BCM_E_NONE 6764 * BCM_E_INTERNAL - internal error. 6765 * Notes: 6766 */ 6767 int 6768 bcmi_esw_portctrl_mac_tx_down(int unit, int nport, bcm_port_t *port) 6769 { 6770 #ifdef PORTMOD_SUPPORT 6771 int i; 6772 bcm_port_t lport; 6773 portctrl_pport_t pport; 6774 6775 for (i = 0; i < nport; i++) { 6776 lport = port[i]; 6777 6778 BCM_IF_ERROR_RETURN 6779 (PORTCTRL_PORT_RESOLVE(unit, lport, &lport, &pport)); 6780 if (!SOC_IS_TOMAHAWK3(unit)) { 6781 /* Drain MAC TX FIFO cells */ 6782 BCM_IF_ERROR_RETURN 6783 (_bcm_esw_portctrl_drain_cells(unit, pport, lport)); 6784 } 6785 6786 /* MAC TX disable */ 6787 BCM_IF_ERROR_RETURN 6788 (portmod_port_tx_mac_enable_set(unit, pport, 0)); 6789 6790 /* Hold MAC in reset state */ 6791 BCM_IF_ERROR_RETURN 6792 (portmod_port_mac_reset_set(unit, pport, 1)); 6793 6794 } 6795 return BCM_E_NONE; 6796 #else /* PORTMOD_SUPPORT */ 6797 return BCM_E_UNAVAIL; 6798 #endif /* PORTMOD_SUPPORT */ 6799 } 6800 6801 /* 6802 * Function: 6803 * bcmi_esw_portctrl_encap_get 6804 * Purpose: 6805 * Get the port encapsulation mode 6806 * Parameters: 6807 * unit - StrataSwitch unit # 6808 * port - StrataSwitch port # 6809 * mode (OUT) - One of BCM_PORT_ENCAP_xxx (see port.h) 6810 * Returns: 6811 * BCM_E_XXX 6812 */ 6813 6814 int 6815 bcmi_esw_portctrl_encap_get(int unit, bcm_gport_t port, int *mode) 6816 { 6817 #ifdef PORTMOD_SUPPORT 6818 int rv = BCM_E_NONE, flags=0, valid = 0; 6819 portctrl_pport_t pport; 6820 portmod_port_interface_config_t port_if_cfg; 6821 6822 /* Make sure port module is initialized. */ 6823 PORTCTRL_INIT_CHECK(unit); 6824 6825 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 6826 6827 BCM_IF_ERROR_RETURN(portmod_port_is_valid(unit, pport, &valid)); 6828 if (!valid) { 6829 return BCM_E_PORT; 6830 } 6831 6832 if ((IS_GE_PORT(unit, port) && IS_ST_PORT(unit, port)) || 6833 IS_CD_PORT(unit, port)) { 6834 if (soc_feature(unit, soc_feature_embedded_higig)) { 6835 *mode = BCM_PORT_ENCAP_IEEE; 6836 } else { 6837 portmod_encap_t val; 6838 6839 PORT_LOCK(unit); 6840 rv = portmod_port_encap_get(unit, pport, &flags, &val); 6841 PORT_UNLOCK(unit); 6842 6843 if (PORTMOD_SUCCESS(rv)) { 6844 *mode = val ? BCM_PORT_ENCAP_HIGIG2 : BCM_PORT_ENCAP_IEEE; 6845 } else { 6846 return (BCM_E_CONFIG); 6847 } 6848 } 6849 } else { 6850 portmod_port_interface_config_t_init(unit, &port_if_cfg); 6851 6852 PORT_LOCK(unit); 6853 rv = portmod_port_interface_config_get(unit, pport, &port_if_cfg, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY); 6854 PORT_UNLOCK(unit); 6855 6856 if (PORTMOD_SUCCESS(rv)) { 6857 *mode = port_if_cfg.encap_mode; 6858 } 6859 } 6860 6861 LOG_INFO(BSL_LS_BCM_PORT, 6862 (BSL_META_UP(unit, port, 6863 "Port encap get: u=%d p=%d mode=%d rv=%d\n"), 6864 unit, port, *mode, rv)); 6865 6866 return rv; 6867 #else /* PORTMOD_SUPPORT */ 6868 return BCM_E_UNAVAIL; 6869 #endif /* PORTMOD_SUPPORT */ 6870 } 6871 6872 #ifdef PORTMOD_SUPPORT 6873 /* 6874 * Function: 6875 * _bcm_esw_portctrl_interface_cfg_set 6876 * Purpose: 6877 * This function is called by encap set functions to set encap mode, 6878 * interface type and speed 6879 * Parameters: 6880 * unit - (IN) Unit number 6881 * port - (IN) Logical BCM Port number (non-GPORT). 6882 * pport - (IN) Portmod Port number 6883 * field - (IN) Field of portmod_port_interface_config_t to modify 6884 * Only encap_mode, speed and interface can be 6885 * modified 6886 * field_val - Value of the Portmod field to program 6887 * Returns: 6888 * BCM_E_XXX 6889 */ 6890 STATIC 6891 int _bcm_esw_portctrl_interface_cfg_set(int unit, bcm_port_t port, 6892 portctrl_pport_t pport, 6893 int field, void *field_val) 6894 { 6895 portmod_port_interface_config_t port_if_cfg; 6896 soc_port_if_t default_interface; 6897 char *str; 6898 int rv = BCM_E_NONE; 6899 6900 portmod_port_interface_config_t_init(unit, &port_if_cfg); 6901 6902 PORT_LOCK(unit); 6903 6904 rv = portmod_port_interface_config_get(unit, pport, &port_if_cfg, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY); 6905 6906 if ((port_if_cfg.encap_mode == SOC_ENCAP_HIGIG2) || 6907 (port_if_cfg.encap_mode == SOC_ENCAP_HIGIG)) { 6908 PHYMOD_INTF_MODES_HIGIG_SET(&port_if_cfg); 6909 } else { 6910 PHYMOD_INTF_MODES_HIGIG_CLR(&port_if_cfg); 6911 } 6912 6913 if (PORTMOD_SUCCESS(rv)) { 6914 6915 /* Set value of appropriate field */ 6916 switch (field) { 6917 case BCM_ESW_PORTCTRL_CFG_ENCAP_MODE: 6918 if (port_if_cfg.encap_mode != *((portmod_encap_t *)field_val)) { 6919 port_if_cfg.encap_mode = *((portmod_encap_t *)field_val); 6920 6921 /* need to update the port mode since encap is changed */ 6922 if ((port_if_cfg.encap_mode == SOC_ENCAP_HIGIG2) || 6923 (port_if_cfg.encap_mode == SOC_ENCAP_HIGIG)) { 6924 PHYMOD_INTF_MODES_HIGIG_SET(&port_if_cfg); 6925 } else { 6926 PHYMOD_INTF_MODES_HIGIG_CLR(&port_if_cfg); 6927 } 6928 6929 /* When changing the encap, the existing interface type of the 6930 * port may not be valid anymore. Need to retrieve the default 6931 * interface type based on the new encap mode and update 6932 * port_if_cfg. 6933 */ 6934 default_interface = SOC_PORT_IF_NULL; 6935 rv = portmod_port_default_interface_get( 6936 unit, port, &port_if_cfg, &default_interface); 6937 if(SOC_FAILURE(rv)) { 6938 PORT_UNLOCK(unit); 6939 return rv; 6940 } 6941 if (default_interface != SOC_PORT_IF_NULL) { 6942 port_if_cfg.interface = default_interface; 6943 } else { 6944 rv = portmod_common_default_interface_get(&port_if_cfg); 6945 if(SOC_FAILURE(rv)) { 6946 PORT_UNLOCK(unit); 6947 return rv; 6948 } 6949 } 6950 } 6951 break; 6952 6953 case BCM_ESW_PORTCTRL_CFG_INTERFACE: 6954 port_if_cfg.interface = *((soc_port_if_t *)field_val); 6955 break; 6956 6957 case BCM_ESW_PORTCTRL_CFG_SPEED: 6958 port_if_cfg.speed = *((int *)field_val); 6959 break; 6960 6961 default: 6962 PORT_UNLOCK(unit); 6963 return BCM_E_PARAM; 6964 } 6965 6966 6967 if (port_if_cfg.speed == 0) { 6968 port_if_cfg.speed = SOC_CONTROL(unit)->info.port_speed_max[port]; 6969 } 6970 6971 rv = _bcm_esw_portctrl_interface_config_set(unit, port, pport, 6972 &port_if_cfg, 0); 6973 PORT_UNLOCK(unit); 6974 6975 if (PORTMOD_FAILURE(rv)) { 6976 str = "set"; 6977 } 6978 } else { 6979 PORT_UNLOCK(unit); 6980 str = "get"; 6981 } 6982 6983 if (PORTMOD_FAILURE(rv)) { 6984 LOG_VERBOSE(BSL_LS_SOC_COMMON, 6985 (BSL_META_U(unit, 6986 "Interface_%s failed:err=%d: %s\n"), str, rv, 6987 bcm_errmsg(rv))); 6988 6989 rv = BCM_E_CONFIG; /* Returning BCM_ error code */ 6990 } 6991 6992 return rv; 6993 } 6994 #endif /* PORTMOD_SUPPORT */ 6995 6996 /* 6997 * Function: 6998 * bcmi_esw_portctrl_encap_xport_set 6999 * Purpose: 7000 * Convert Ether port to Higig port or Cpri, or reverse 7001 * Parameters: 7002 * unit - (IN) Unit number. 7003 * port - (IN) Port number. 7004 * mode - (IN) Encapsulation mode 7005 * Returns: 7006 * BCM_E_XXX 7007 * Notes: 7008 * Must be called with PORT_LOCK held. 7009 */ 7010 7011 int 7012 bcmi_esw_portctrl_encap_xport_set(int unit, bcm_gport_t port, int mode) 7013 { 7014 #ifdef PORTMOD_SUPPORT 7015 int rv = BCM_E_NONE; 7016 portctrl_pport_t pport; 7017 bcm_stg_t stg; 7018 int to_higig = 0; 7019 soc_field_t port_type_field; 7020 soc_reg_t egr_port_reg; 7021 soc_port_ability_t ability; 7022 soc_port_mode_t non_ieee_speed; 7023 int force_speed, port_type, higig_type; 7024 phymod_autoneg_control_t an_info; 7025 bcm_port_abil_t ability_mask=0; 7026 soc_mem_t ing_port_mem = PORT_TABm; 7027 7028 7029 /* Make sure port module is initialized. */ 7030 PORTCTRL_INIT_CHECK(unit); 7031 7032 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 7033 if ( mode != BCM_PORT_ENCAP_IEEE && mode != BCM_PORT_ENCAP_CPRI) { 7034 to_higig = 1; 7035 } 7036 7037 7038 port_type_field = PORT_TYPEf; 7039 7040 rv = _bcm_esw_portctrl_interface_cfg_set(unit, port, pport, 7041 BCM_ESW_PORTCTRL_CFG_ENCAP_MODE, 7042 (void *)&mode); 7043 if (BCM_FAILURE(rv)) { 7044 return rv; 7045 } 7046 7047 #if 0 7048 if (to_higig) { 7049 soc_port_if_t port_intf; 7050 7051 port_intf = SOC_PORT_IF_XGMII; 7052 rv = _bcm_esw_portctrl_interface_cfg_set(unit, port, pport, 7053 BCM_ESW_PORTCTRL_CFG_INTERFACE, 7054 (void *)&port_intf); 7055 if (BCM_FAILURE(rv)) { 7056 return rv; 7057 } 7058 } 7059 #endif 7060 7061 /* Specific for GH on avoiding port speed change */ 7062 if (!soc_feature(unit, soc_feature_hg_no_speed_change)) { 7063 BCM_IF_ERROR_RETURN(bcm_esw_port_ability_local_get(unit, port, 7064 &ability)); 7065 7066 non_ieee_speed = ability.speed_full_duplex & 7067 ~(SOC_PA_SPEED_100GB | SOC_PA_SPEED_40GB | SOC_PA_SPEED_10GB | 7068 SOC_PA_SPEED_2500MB | SOC_PA_SPEED_1000MB | 7069 SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB); 7070 7071 BCM_IF_ERROR_RETURN(bcm_esw_port_ability_advert_get(unit, port, 7072 &ability)); 7073 SOC_IF_ERROR_RETURN(soc_esw_portctrl_speed_get(unit, port, 7074 &force_speed)); 7075 if (to_higig) { 7076 ability.speed_full_duplex |= non_ieee_speed; 7077 ability.pause &= ~(SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM); 7078 force_speed = force_speed == 0 ? 7079 SOC_CONTROL(unit)->info.port_speed_max[port] : 7080 force_speed; 7081 ability.speed_full_duplex |= SOC_PA_SPEED(force_speed); 7082 } else { 7083 ability.speed_full_duplex &= ~non_ieee_speed; 7084 force_speed = SOC_PORTCTRL_HG2_TO_IEEE_BW_GET(force_speed); 7085 } 7086 7087 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_ability_advert_set(unit, port, 7088 &ability, 7089 ability_mask)); 7090 7091 phymod_autoneg_control_t_init(&an_info); 7092 7093 PORT_LOCK(unit); 7094 rv = portmod_port_autoneg_get( 7095 unit, port, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, &an_info); 7096 PORT_UNLOCK(unit); 7097 if (BCM_FAILURE(rv)) { 7098 return rv; 7099 } 7100 7101 /* Some mac driver re-init phy while executing MAC_ENCAP_SET, in that 7102 * case autoneg is probably always true here 7103 */ 7104 if (an_info.enable) { 7105 SOC_IF_ERROR_RETURN(bcm_esw_port_autoneg_set(unit, port, TRUE)); 7106 } else { 7107 rv = _bcm_esw_portctrl_interface_cfg_set(unit, port, pport, 7108 BCM_ESW_PORTCTRL_CFG_SPEED, 7109 (void *)&force_speed); 7110 if (BCM_FAILURE(rv)) { 7111 return rv; 7112 } 7113 } 7114 } 7115 7116 /* Now we propagate the changes */ 7117 port_type = to_higig ? 1 : 0; 7118 7119 if (port_type == 1) { 7120 if (mode == BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET) { 7121 higig_type = BCM_PORT_HG_TYPE_HGOE_TRANSPORT; 7122 } else if (mode == BCM_PORT_ENCAP_HIGIG) { 7123 higig_type = BCM_PORT_HG_TYPE_HIGIGPLUS; 7124 } else { 7125 higig_type = BCM_PORT_HG_TYPE_HIGIG2_NORMAL; 7126 } 7127 } else { 7128 higig_type = 0; 7129 } 7130 7131 if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) { 7132 ing_port_mem = ING_DEVICE_PORTm; 7133 } 7134 if (soc_mem_field_valid(unit, ing_port_mem, port_type_field)) { 7135 SOC_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 7136 _BCM_CPU_TABS_NONE, port_type_field, port_type)); 7137 } 7138 7139 if (SOC_MEM_IS_VALID(unit, EGR_PORTm)) { 7140 if (soc_mem_field_valid(unit, EGR_PORTm, port_type_field)) { 7141 BCM_IF_ERROR_RETURN(_bcm_esw_egr_port_tab_set(unit, port, 7142 port_type_field, port_type)); 7143 } 7144 if(soc_mem_field_valid(unit, EGR_PORTm, HG_TYPEf)) { 7145 SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_PORTm, port, 7146 HG_TYPEf, higig_type)); 7147 } 7148 } else { 7149 if (SOC_REG_IS_VALID(unit, EGR_PORT_64r)) { 7150 egr_port_reg = EGR_PORT_64r; 7151 } else { 7152 egr_port_reg = EGR_PORTr; 7153 } 7154 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, egr_port_reg, port, 7155 port_type_field, port_type)); 7156 } 7157 7158 if (!IS_CPU_PORT(unit, port) && !IS_LB_PORT(unit, port) && !IS_RDB_PORT(unit, port)) { 7159 if (SOC_MEM_IS_VALID(unit, EGR_ING_PORTm)) { 7160 SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_ING_PORTm, 7161 port, PORT_TYPEf, port_type)); 7162 } 7163 if(SOC_MEM_FIELD_VALID(unit, EGR_ING_PORTm, HG_TYPEf)) { 7164 SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_ING_PORTm, 7165 port, HG_TYPEf, higig_type)); 7166 } 7167 } 7168 7169 7170 if (SOC_MEM_IS_VALID(unit, ICONTROL_OPCODE_BITMAPm)) { 7171 icontrol_opcode_bitmap_entry_t entry; 7172 soc_pbmp_t pbmp; 7173 7174 SOC_IF_ERROR_RETURN(READ_ICONTROL_OPCODE_BITMAPm(unit, MEM_BLOCK_ANY, 7175 port, &entry)); 7176 SOC_PBMP_CLEAR(pbmp); 7177 if (to_higig) { 7178 SOC_PBMP_PORT_SET(pbmp, CMIC_PORT(unit)); 7179 } 7180 soc_mem_pbmp_field_set(unit, ICONTROL_OPCODE_BITMAPm, &entry, BITMAPf, 7181 &pbmp); 7182 SOC_IF_ERROR_RETURN(WRITE_ICONTROL_OPCODE_BITMAPm(unit, MEM_BLOCK_ANY, 7183 port, &entry)); 7184 } else { 7185 7186 /* Set HG ingress CPU Opcode map to the CPU */ 7187 /* int pbm_len; */ 7188 uint32 cpu_pbm = 0; 7189 7190 if (to_higig) { 7191 SOC_IF_ERROR_RETURN(soc_xgs3_port_to_higig_bitmap(unit, 7192 CMIC_PORT(unit), &cpu_pbm)); 7193 } /* else, cpu_pbm = 0 */ 7194 7195 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 7196 ICONTROL_OPCODE_BITMAPr, port, BITMAPf, cpu_pbm)); 7197 } 7198 7199 if (to_higig) { 7200 /* Embedded Higig ports should be configured and marked as ST ports */ 7201 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_pause_set(unit, port, 0, 0)); 7202 /* HG ports to forwarding */ 7203 BCM_IF_ERROR_RETURN(bcm_esw_port_stp_set(unit, port, 7204 BCM_STG_STP_FORWARD)); 7205 } else { 7206 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_pause_set(unit, port, 1, 1)); 7207 } 7208 7209 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7210 /* 7211 * Higig ports need the MIRROR_CONTROL.M_ENABLE=1 in order to respond to 7212 * the mirror bit in the Higig headers. 7213 */ 7214 if (to_higig) { 7215 BCM_IF_ERROR_RETURN(_bcm_esw_mirror_enable_set(unit, port, TRUE)); 7216 } 7217 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7218 7219 /* Clear mirror enable settings */ 7220 /* coverity[stack_use_callee] */ 7221 /* coverity[stack_use_overflow] */ 7222 BCM_IF_ERROR_RETURN(bcm_esw_mirror_port_set(unit, port, -1, -1, 0)); 7223 7224 /* Set untagged state in default VLAN properly */ 7225 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_untag_update(unit, port, to_higig)); 7226 7227 /* Resolve STG 0 */ 7228 BCM_IF_ERROR_RETURN(bcm_esw_stg_default_get(unit, &stg)); 7229 BCM_IF_ERROR_RETURN(bcm_esw_stg_stp_set(unit, 0, port, 7230 to_higig ? BCM_STG_STP_FORWARD : BCM_STG_STP_DISABLE)); 7231 7232 #ifdef BCM_TRX_SUPPORT 7233 /* Reset the vlan default action */ 7234 if (soc_feature(unit, soc_feature_vlan_action) && (!SOC_IS_TRIDENT3X(unit))) { 7235 bcm_vlan_action_set_t action; 7236 7237 BCM_IF_ERROR_RETURN(_bcm_trx_vlan_port_egress_default_action_get(unit, 7238 port, &action)); 7239 /* Backward compatible defaults */ 7240 if (to_higig) { 7241 action.ot_outer = bcmVlanActionDelete; 7242 action.dt_outer = bcmVlanActionDelete; 7243 } else { 7244 action.ot_outer = bcmVlanActionNone; 7245 action.dt_outer = bcmVlanActionNone; 7246 } 7247 BCM_IF_ERROR_RETURN(_bcm_trx_vlan_port_egress_default_action_set(unit, 7248 port, &action)); 7249 } 7250 #endif 7251 7252 #ifdef INCLUDE_L3 7253 if ((soc_feature(unit, soc_feature_ip_mcast)) && 7254 (!soc_feature(unit, soc_feature_no_egr_ipmc_cfg))) { 7255 BCM_IF_ERROR_RETURN(bcm_esw_ipmc_egress_port_set( 7256 unit, port, 7257 to_higig ? _soc_mac_all_ones :_soc_mac_all_zeroes, 7258 0, 0, 0)); 7259 } 7260 #endif /* INCLUDE_L3 */ 7261 7262 return rv; 7263 7264 #else /* PORTMOD_SUPPORT */ 7265 return BCM_E_UNAVAIL; 7266 #endif /* PORTMOD_SUPPORT */ 7267 } 7268 7269 /* 7270 * Function: 7271 * bcmi_esw_portctrl_encap_higig_lite_set 7272 * Purpose: 7273 * Helper function to force a port into HIGIG2_LITE mode 7274 * Parameters: 7275 * unit - (IN) device id 7276 * port - (IN) port number 7277 * Returns: 7278 * BCM_E_XXX 7279 */ 7280 int 7281 bcmi_esw_portctrl_encap_higig_lite_set(int unit, bcm_gport_t port) 7282 { 7283 #ifdef PORTMOD_SUPPORT 7284 portctrl_pport_t pport; 7285 portmod_port_ability_t ability; 7286 phymod_autoneg_control_t an_info; 7287 int rv; 7288 7289 PORTCTRL_INIT_CHECK(unit); 7290 7291 sal_memset(&ability, 0, sizeof(soc_port_ability_t)); 7292 sal_memset(&an_info, 0, sizeof(phymod_autoneg_control_t)); 7293 7294 if (soc_feature(unit, soc_feature_hg_no_speed_change)) { 7295 /* HG-Lite process without 2.5G speed setting can calls to 7296 * bcmi_esw_portctrl_encap_xport_set() directly. 7297 */ 7298 return bcmi_esw_portctrl_encap_xport_set(unit, port, 7299 BCM_PORT_ENCAP_HIGIG2_LITE); 7300 } 7301 7302 if (IS_XE_PORT(unit, port) || IS_HG_PORT(unit, port)) { 7303 7304 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, 7305 &pport)); 7306 7307 /* Restrict the speed to <= 2.5G and set the encap to HG2 */ 7308 BCM_IF_ERROR_RETURN(portmod_port_ability_local_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, 7309 &ability)); 7310 7311 ability.speed_full_duplex &= ~(SOC_PA_SPEED_10GB | 7312 SOC_PA_SPEED_12GB | SOC_PA_SPEED_13GB | SOC_PA_SPEED_15GB | 7313 SOC_PA_SPEED_16GB | SOC_PA_SPEED_20GB | SOC_PA_SPEED_21GB | 7314 SOC_PA_SPEED_25GB | SOC_PA_SPEED_30GB | SOC_PA_SPEED_40GB); 7315 7316 BCM_IF_ERROR_RETURN(portmod_port_ability_advert_set(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, 7317 &ability)); 7318 BCM_IF_ERROR_RETURN(portmod_port_autoneg_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, 7319 &an_info)); 7320 7321 if (!an_info.enable) { 7322 int speed; 7323 7324 speed = 2500; 7325 rv = _bcm_esw_portctrl_interface_cfg_set(unit, port, pport, 7326 BCM_ESW_PORTCTRL_CFG_SPEED, 7327 (void *)&speed); 7328 7329 if (BCM_FAILURE(rv)) { 7330 return rv; 7331 } 7332 } 7333 7334 return bcmi_esw_portctrl_encap_xport_set(unit, port, 7335 BCM_PORT_ENCAP_HIGIG2); 7336 } else if (IS_ST_PORT(unit, port) || IS_E_PORT(unit, port)) { 7337 7338 return _bcm_port_encap_stport_set(unit, port, BCM_PORT_ENCAP_HIGIG2); 7339 } 7340 7341 return BCM_E_CONFIG; 7342 #else /* PORTMOD_SUPPORT */ 7343 return BCM_E_UNAVAIL; 7344 #endif /* PORTMOD_SUPPORT */ 7345 } 7346 7347 /* 7348 * Function: 7349 * bcmi_esw_portctrl_higig_mode_set 7350 * Purpose: 7351 * Set port Higig mode 7352 * Parameters: 7353 * unit - StrataSwitch unit # 7354 * port - StrataSwitch port # 7355 * higig_mode - Higig mode 7356 * Returns: 7357 * BCM_E_XXX 7358 */ 7359 int 7360 bcmi_esw_portctrl_higig_mode_set(int unit, bcm_gport_t port, int higig_mode) 7361 { 7362 #ifdef PORTMOD_SUPPORT 7363 int rv; 7364 portctrl_pport_t pport; 7365 7366 PORTCTRL_INIT_CHECK(unit); 7367 7368 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, 7369 &pport)); 7370 7371 PORT_LOCK(unit); 7372 rv = portmod_port_higig_mode_set(unit, pport, higig_mode); 7373 PORT_UNLOCK(unit); 7374 7375 return rv; 7376 #else /* PORTMOD_SUPPORT */ 7377 return BCM_E_UNAVAIL; 7378 #endif /* PORTMOD_SUPPORT */ 7379 } 7380 /* 7381 * Function: 7382 * bcmi_esw_portctrl_higig2_mode_set 7383 * Purpose: 7384 * Set port Higig2 mode 7385 * Parameters: 7386 * unit - StrataSwitch unit # 7387 * port - StrataSwitch port # 7388 * higig2_mode - Higig2 mode 7389 * Returns: 7390 * BCM_E_XXX 7391 */ 7392 int 7393 bcmi_esw_portctrl_higig2_mode_set(int unit, bcm_gport_t port, int higig2_mode) 7394 { 7395 #ifdef PORTMOD_SUPPORT 7396 soc_reg_t egr_port_reg; 7397 soc_mem_t egr_port_mem; 7398 int rv; 7399 portctrl_pport_t pport; 7400 int port_hg2_mode = higig2_mode; 7401 7402 PORTCTRL_INIT_CHECK(unit); 7403 7404 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, 7405 &pport)); 7406 7407 if (soc_mem_field_valid(unit, PORT_TABm, HIGIG2f) || 7408 soc_mem_field_valid(unit, LPORT_TABm, HIGIG2f)) { 7409 BCM_IF_ERROR_RETURN(_bcm_esw_port_tab_set(unit, port, 7410 _BCM_CPU_TABS_NONE, HIGIG2f, higig2_mode)); 7411 } 7412 7413 if (SOC_IS_TRIDENT3X(unit)) { 7414 if (higig2_mode) { 7415 BCM_IF_ERROR_RETURN( 7416 _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE, 7417 PORT_TYPEf, 1)); 7418 } 7419 } 7420 7421 if (SOC_REG_IS_VALID(unit, EGR_PORT_64r)) { 7422 egr_port_reg = EGR_PORT_64r; 7423 } else { 7424 egr_port_reg = EGR_PORTr; 7425 } 7426 7427 if (SOC_REG_FIELD_VALID(unit, egr_port_reg, HIGIG2f)) { 7428 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, egr_port_reg, port, 7429 HIGIG2f, higig2_mode)); 7430 } else if (SOC_MEM_FIELD_VALID(unit, EGR_PORTm, HIGIG2f)) { 7431 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, EGR_PORTm, port, 7432 HIGIG2f, higig2_mode)); 7433 } 7434 7435 PORT_LOCK(unit); 7436 rv = portmod_port_higig2_mode_set(unit, pport, port_hg2_mode); 7437 PORT_UNLOCK(unit); 7438 7439 if (PORTMOD_FAILURE(rv)) { 7440 return rv; 7441 } 7442 7443 egr_port_mem = EGR_ING_PORTm; 7444 if (SOC_MEM_FIELD_VALID(unit, egr_port_mem, HIGIG2f)) { 7445 if (IS_CPU_PORT(unit, port)) { 7446 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, egr_port_mem, 7447 SOC_INFO(unit).cpu_hg_index, HIGIG2f, 7448 higig2_mode)); 7449 } else { 7450 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, egr_port_mem, 7451 port, HIGIG2f, 7452 higig2_mode)); 7453 } 7454 } 7455 7456 return BCM_E_NONE; 7457 #else /* PORTMOD_SUPPORT */ 7458 return BCM_E_UNAVAIL; 7459 #endif /* PORTMOD_SUPPORT */ 7460 } 7461 7462 #ifdef PORTMOD_SUPPORT 7463 /* 7464 * Function: 7465 * bcmi_esw_portctrl_encap_set_execute 7466 * Purpose: 7467 * Set the port encapsulation mode 7468 * Parameters: 7469 * unit - StrataSwitch unit # 7470 * port - StrataSwitch port # 7471 * mode - One of BCM_PORT_ENCAP_xxx (see port.h) 7472 * force - TRUE : force encap operation(set xport_swap = TRUE) 7473 * regardless of IS_HG_PORT and mode value. 7474 * 7475 * Returns: 7476 * BCM_E_XXX 7477 */ 7478 int 7479 bcmi_esw_portctrl_encap_set_execute(int unit, bcm_gport_t port, int mode, int force) 7480 { 7481 int rv, xport_swap = FALSE; 7482 uint64 val64; 7483 portctrl_pport_t pport; 7484 int to_higig; 7485 int size; 7486 7487 PORTCTRL_INIT_CHECK(unit); 7488 7489 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 7490 7491 LOG_INFO(BSL_LS_BCM_PORT, 7492 (BSL_META_UP(unit, port, 7493 "bcm_esw_port_encap_set: u=%d p=%d mode=%d\n"), 7494 unit, port, mode)); 7495 7496 if ((soc_feature(unit, soc_feature_roe)) && ((mode == BCM_PORT_ENCAP_CPRI) || (mode == BCM_PORT_ENCAP_RSVD4))) { 7497 return portmod_port_encap_set(unit, pport, 0, BCM_PORT_ENCAP_CPRI); 7498 } 7499 7500 _bcm_esw_port_mirror_lock(unit); 7501 7502 if (force) { 7503 xport_swap = TRUE; 7504 } 7505 7506 if ((IS_HG_PORT(unit,port) && (mode == BCM_PORT_ENCAP_IEEE || 7507 (SOC_IS_MONTEREY(unit) && mode == BCM_PORT_ENCAP_CPRI))) || 7508 ((IS_XE_PORT(unit, port) || IS_CE_PORT(unit, port) || 7509 IS_C_PORT(unit, port)) && 7510 (mode != BCM_PORT_ENCAP_IEEE))) { 7511 if (mode == BCM_PORT_ENCAP_CPRI) { 7512 return portmod_port_encap_set(unit, pport, 0, mode); 7513 } 7514 7515 if (soc_feature(unit, soc_feature_xport_convertible)) { 7516 xport_swap = TRUE; 7517 } else { 7518 /* Ether <=> Higig not allowed on all systems */ 7519 _bcm_esw_port_mirror_unlock(unit); 7520 return BCM_E_UNAVAIL; 7521 } 7522 } 7523 7524 if ((mode == BCM_PORT_ENCAP_HIGIG) 7525 && soc_feature(unit, soc_feature_no_higig_plus)) { 7526 _bcm_esw_port_mirror_unlock(unit); 7527 return BCM_E_UNAVAIL; 7528 } 7529 7530 if (xport_swap) { 7531 COUNTER_LOCK(unit); 7532 if ((BCM_PORT_ENCAP_HIGIG2_LITE == mode)) { 7533 rv = bcmi_esw_portctrl_encap_higig_lite_set(unit, port); 7534 } else { 7535 rv = bcmi_esw_portctrl_encap_xport_set(unit, port, mode); 7536 } 7537 7538 COUNTER_UNLOCK(unit); 7539 if (PORTMOD_FAILURE(rv)) { 7540 _bcm_esw_port_mirror_unlock(unit); 7541 return rv; 7542 } 7543 } else if (IS_HG_PORT(unit, port)) { 7544 7545 rv = _bcm_esw_portctrl_interface_cfg_set(unit, port, pport, 7546 BCM_ESW_PORTCTRL_CFG_ENCAP_MODE, 7547 (void *)&mode); 7548 if (BCM_FAILURE(rv)) { 7549 _bcm_esw_port_mirror_unlock(unit); 7550 return rv; 7551 } 7552 } else if (IS_GE_PORT(unit, port) && IS_ST_PORT(unit, port)) { 7553 if (mode == BCM_PORT_ENCAP_IEEE) { 7554 bcm_port_encap_config_t encap_config; 7555 7556 rv = bcm_esw_port_encap_config_get(unit, port, 7557 &encap_config); 7558 if (BCM_SUCCESS(rv)) { 7559 if ((BCM_PORT_ENCAP_HIGIG2_L2 == encap_config.encap) || 7560 (BCM_PORT_ENCAP_HIGIG2_IP_GRE == encap_config.encap) || 7561 (BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET == encap_config.encap) || 7562 (BCM_PORT_ENCAP_HIGIG2_LITE == encap_config.encap)) { 7563 rv = _bcm_port_encap_stport_set(unit, port, 7564 BCM_PORT_ENCAP_IEEE); 7565 } else { 7566 rv = BCM_E_UNAVAIL; 7567 } 7568 } 7569 } else { 7570 if ((mode == BCM_PORT_ENCAP_HIGIG2) || 7571 (mode == BCM_PORT_ENCAP_HIGIG2_LITE)) { 7572 rv = BCM_E_NONE; 7573 } else { 7574 rv = BCM_E_UNAVAIL; 7575 } 7576 } 7577 } else if (IS_CE_PORT(unit, port) || IS_C_PORT(unit, port)) { 7578 if ((mode == BCM_PORT_ENCAP_HIGIG2) || 7579 (mode == BCM_PORT_ENCAP_HIGIG) || 7580 (mode == BCM_PORT_ENCAP_IEEE)) { 7581 rv = _bcm_port_encap_stport_set(unit, port, mode); 7582 } else { 7583 rv = BCM_E_UNAVAIL; 7584 } 7585 } else if (mode == BCM_PORT_ENCAP_IEEE) { 7586 rv = BCM_E_NONE; 7587 } else { 7588 rv = BCM_E_UNAVAIL; 7589 } 7590 7591 #ifdef BCM_GXPORT_SUPPORT 7592 if (IS_GX_PORT(unit, port) || IS_XG_PORT(unit,port) || 7593 IS_HG_PORT(unit, port) || IS_XE_PORT(unit, port) || 7594 IS_CE_PORT(unit, port) || IS_C_PORT(unit, port)) { 7595 int hg2 = FALSE; 7596 7597 if (mode == BCM_PORT_ENCAP_HIGIG2 || 7598 mode == BCM_PORT_ENCAP_HIGIG2_LITE) { 7599 hg2 = TRUE; 7600 } 7601 7602 if (BCM_SUCCESS(rv)) { 7603 rv = bcmi_esw_portctrl_higig2_mode_set(unit, port, hg2); 7604 } 7605 7606 if (BCM_SUCCESS(rv)) { 7607 /* No need for locking; _bcm_esw_port_mirror_lock does it */ 7608 uint32 port_hg_mode = (mode == BCM_PORT_ENCAP_IEEE) ? 0 : 1; 7609 7610 rv = portmod_port_higig_mode_set(unit, pport, port_hg_mode); 7611 } 7612 7613 if (PORTMOD_SUCCESS(rv)) { 7614 if (SOC_MEM_IS_VALID(unit, EGR_PORTm)) { 7615 rv = soc_mem_field32_modify(unit, EGR_PORTm, port, 7616 PORT_TYPEf, 7617 mode == BCM_PORT_ENCAP_IEEE ? 7618 0 : 1); 7619 } 7620 } 7621 } 7622 #endif /* BCM_GXPORT_SUPPORT */ 7623 7624 if (soc_feature(unit, soc_feature_embedded_higig)) { 7625 /* Clear embedded Higig regs, if present */ 7626 soc_reg_t ehg_tx_reg = EHG_TX_CONTROLr; 7627 soc_reg_t ehg_rx_reg = EHG_RX_CONTROLr; 7628 7629 if (BCM_SUCCESS(rv) && SOC_REG_IS_VALID(unit, ehg_tx_reg)) { 7630 rv = soc_reg32_set(unit, ehg_tx_reg, port, 0, 0); 7631 } 7632 if (BCM_SUCCESS(rv) && SOC_REG_IS_VALID(unit, ehg_rx_reg)) { 7633 rv = soc_reg32_set(unit, ehg_rx_reg, port, 0, 0); 7634 } 7635 } 7636 7637 if (BCM_SUCCESS(rv) && soc_feature(unit, soc_feature_higig_over_ethernet)) { 7638 /* Disable HGoE if needed*/ 7639 7640 uint32 tab_port_type; 7641 uint32 tab_higig_type; 7642 7643 tab_port_type = (mode == BCM_PORT_ENCAP_IEEE) ? 0 : 1; 7644 7645 if (tab_port_type == 1) { 7646 if (mode == BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET) { 7647 tab_higig_type = BCM_PORT_HG_TYPE_HGOE_TRANSPORT; 7648 } else if (mode == BCM_PORT_ENCAP_HIGIG) { 7649 tab_higig_type = BCM_PORT_HG_TYPE_HIGIGPLUS; 7650 } else { 7651 tab_higig_type = BCM_PORT_HG_TYPE_HIGIG2_NORMAL; 7652 } 7653 } else { 7654 tab_higig_type = 0; 7655 } 7656 7657 if(SOC_REG_IS_VALID(unit, PGW_CELL_ASM_EMBEDDED_HG_CONTROL0r)) { 7658 uint64 field64; 7659 uint32 tmp32; 7660 tmp32 = (BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET == mode); 7661 COMPILER_64_SET(field64, 0, tmp32); 7662 if (SOC_FAILURE(soc_reg_get(unit, PGW_CELL_ASM_EMBEDDED_HG_CONTROL0r, 7663 port, 0, &val64))) { 7664 _bcm_esw_port_mirror_unlock(unit); 7665 return rv; 7666 } 7667 soc_reg64_field_set(unit, PGW_CELL_ASM_EMBEDDED_HG_CONTROL0r, 7668 &val64, TRANSPORT_ENf, 7669 field64); 7670 rv = soc_reg_set(unit, PGW_CELL_ASM_EMBEDDED_HG_CONTROL0r, port, 0, 7671 val64); 7672 } 7673 if (BCM_SUCCESS(rv) && 7674 SOC_MEM_FIELD_VALID(unit, EGR_PORTm, PORT_TYPEf)) { 7675 rv = soc_mem_field32_modify(unit, EGR_PORTm, port, PORT_TYPEf, tab_port_type); 7676 } 7677 if (BCM_SUCCESS(rv) && SOC_MEM_FIELD_VALID(unit, EGR_PORTm, HG_TYPEf)) { 7678 rv = soc_mem_field32_modify(unit, EGR_PORTm, port, 7679 HG_TYPEf, tab_higig_type); 7680 } 7681 if (BCM_SUCCESS(rv) && 7682 SOC_MEM_FIELD_VALID(unit, EGR_ING_PORTm, PORT_TYPEf)) { 7683 rv = soc_mem_field32_modify(unit, EGR_ING_PORTm, port, PORT_TYPEf, tab_port_type); 7684 7685 } 7686 if (BCM_SUCCESS(rv) && 7687 SOC_MEM_FIELD_VALID(unit, EGR_ING_PORTm, HG_TYPEf)) { 7688 rv = soc_mem_field32_modify(unit, EGR_ING_PORTm, port, 7689 HG_TYPEf, tab_higig_type); 7690 } 7691 7692 if (BCM_SUCCESS(rv) && 7693 SOC_MEM_FIELD_VALID(unit, PORT_TABm, PORT_TYPEf)) { 7694 rv = _bcm_esw_port_tab_set(unit, port, 7695 _BCM_CPU_TABS_NONE, PORT_TYPEf, tab_port_type); 7696 7697 } 7698 if (BCM_SUCCESS(rv) && SOC_MEM_FIELD_VALID(unit, PORT_TABm, HG_TYPEf)) { 7699 7700 rv = _bcm_esw_port_tab_set(unit, port, 7701 _BCM_CPU_TABS_NONE, HG_TYPEf, tab_higig_type); 7702 } 7703 #ifdef BCM_TRX_SUPPORT 7704 /* Reset the vlan default action, if not done already */ 7705 if (xport_swap == FALSE) { 7706 if (soc_feature(unit, soc_feature_vlan_action)) { 7707 bcm_vlan_action_set_t action; 7708 7709 if (BCM_FAILURE(_bcm_trx_vlan_port_egress_default_action_get( 7710 unit, port, &action))) { 7711 _bcm_esw_port_mirror_unlock(unit); 7712 return rv; 7713 } 7714 /* Backward compatible defaults */ 7715 if (((mode == BCM_PORT_ENCAP_HIGIG) || 7716 (mode == BCM_PORT_ENCAP_HIGIG2) || 7717 (mode == BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET)) && 7718 (!SOC_IS_TRIDENT3X(unit))) { 7719 action.ot_outer = bcmVlanActionDelete; 7720 action.dt_outer = bcmVlanActionDelete; 7721 } else { 7722 action.ot_outer = bcmVlanActionNone; 7723 action.dt_outer = bcmVlanActionNone; 7724 } 7725 if (BCM_FAILURE(_bcm_trx_vlan_port_egress_default_action_set( 7726 unit, port, &action))) { 7727 _bcm_esw_port_mirror_unlock(unit); 7728 return rv; 7729 } 7730 } 7731 } 7732 #endif 7733 } 7734 7735 /* Update cached version of HiGig2 encapsulation */ 7736 if (BCM_SUCCESS(rv)) { 7737 if (mode == BCM_PORT_ENCAP_HIGIG2 || 7738 mode == BCM_PORT_ENCAP_HIGIG2_LITE) { 7739 SOC_HG2_ENABLED_PORT_ADD(unit, port); 7740 } else { 7741 SOC_HG2_ENABLED_PORT_REMOVE(unit, port); 7742 } 7743 } 7744 7745 size = SOC_INFO(unit).max_mtu; 7746 if ((mode == BCM_PORT_ENCAP_IEEE) || 7747 (mode == BCM_PORT_ENCAP_CPRI) || 7748 (mode == BCM_PORT_ENCAP_HIGIG_OVER_ETHERNET) || 7749 (mode == BCM_PORT_ENCAP_HIGIG2_L2) || 7750 (mode == BCM_PORT_ENCAP_HIGIG2_IP_GRE)) { 7751 to_higig = 0; 7752 size -= 4; 7753 } else { 7754 to_higig = 1; 7755 } 7756 7757 if (BCM_SUCCESS(rv)) { 7758 soc_xport_type_update(unit, port, to_higig); 7759 rv = bcmi_esw_portctrl_frame_max_set(unit, port, size); 7760 } 7761 7762 _bcm_esw_port_mirror_unlock(unit); 7763 7764 return rv; 7765 } 7766 #endif /* PORTMOD_SUPPORT */ 7767 7768 /* 7769 * Function: 7770 * bcmi_portctrl_encap_set 7771 * Purpose: 7772 * Set the port encapsulation mode 7773 * Parameters: 7774 * unit - StrataSwitch unit # 7775 * port - StrataSwitch port # 7776 * mode - One of BCM_PORT_ENCAP_xxx (see port.h) 7777 * force - TRUE : force encap operation(set xport_swap = TRUE) 7778 * regardless of IS_HG_PORT and mode value. 7779 * 7780 * Returns: 7781 * BCM_E_XXX 7782 */ 7783 int 7784 bcmi_esw_portctrl_encap_set(int unit, bcm_gport_t port, int mode, int force) 7785 { 7786 #ifdef PORTMOD_SUPPORT 7787 int pport; 7788 bcm_port_ability_t port_ability; 7789 7790 PORTCTRL_INIT_CHECK(unit); 7791 7792 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 7793 7794 BCM_IF_ERROR_RETURN( 7795 bcmi_esw_portctrl_ability_get(unit, port, &port_ability, NULL)); 7796 7797 if (!((port_ability.encap) & BCM_PA_ENCAP(mode))) { 7798 LOG_VERBOSE(BSL_LS_BCM_PORT, 7799 (BSL_META_UP(unit, port, 7800 "Encap mode %d not supported on port %d\n"), 7801 mode, port)); 7802 return BCM_E_UNAVAIL; 7803 } 7804 7805 BCM_IF_ERROR_RETURN( 7806 bcmi_esw_portctrl_encap_set_execute(unit, port, mode, force)); 7807 7808 return BCM_E_NONE; 7809 #else /* PORTMOD_SUPPORT */ 7810 return BCM_E_UNAVAIL; 7811 #endif /* PORTMOD_SUPPORT */ 7812 } 7813 7814 /* 7815 * Function: 7816 * bcmi_esw_portctrl_llfc_get 7817 * Purpose: 7818 * 7819 * Parameters: 7820 * unit - StrataSwitch unit number. 7821 * port - Port. 7822 * type - Command Type 7823 * value - Value 7824 * Returns: 7825 * BCM_E_NONE 7826 * BCM_E_INTERNAL - internal error. 7827 * Notes: 7828 */ 7829 7830 int 7831 bcmi_esw_portctrl_llfc_get(int unit, bcm_gport_t port, bcm_port_control_t type, int *value) 7832 { 7833 #ifdef PORTMOD_SUPPORT 7834 int rv = BCM_E_UNAVAIL; 7835 portmod_llfc_control_t control; 7836 7837 PORT_LOCK(unit); 7838 switch(type) { 7839 case bcmPortControlLLFCReceive: 7840 case bcmPortControlSAFCReceive: 7841 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7842 if (SOC_IS_XGS3_SWITCH(unit)) { 7843 if (!SOC_PORT_VALID(unit, port)) { 7844 PORT_UNLOCK(unit); 7845 return BCM_E_PORT; 7846 } 7847 if (!IS_HG_PORT(unit, port)) { 7848 PORT_UNLOCK(unit); 7849 return BCM_E_UNAVAIL; 7850 } 7851 rv = portmod_port_llfc_control_get(unit, port, &control); 7852 *value = control.rx_enable; 7853 } 7854 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7855 break; 7856 case bcmPortControlLLFCTransmit: 7857 case bcmPortControlSAFCTransmit: 7858 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7859 if (SOC_IS_XGS3_SWITCH(unit)) { 7860 if (!SOC_PORT_VALID(unit, port)) { 7861 PORT_UNLOCK(unit); 7862 return BCM_E_PORT; 7863 } 7864 if (!IS_HG_PORT(unit, port)) { 7865 PORT_UNLOCK(unit); 7866 return BCM_E_UNAVAIL; 7867 } 7868 rv = portmod_port_llfc_control_get(unit, port, &control); 7869 *value = control.tx_enable; 7870 } 7871 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7872 break; 7873 default: 7874 break; 7875 } 7876 PORT_UNLOCK(unit); 7877 return(rv); 7878 #else /* PORTMOD_SUPPORT */ 7879 return BCM_E_UNAVAIL; 7880 #endif /* PORTMOD_SUPPORT */ 7881 } 7882 7883 7884 /* 7885 * Function: 7886 * bcmi_esw_portctrl_llfc_set 7887 * Purpose: 7888 * 7889 * Parameters: 7890 * unit - StrataSwitch unit number. 7891 * port - Port. 7892 * type - Command Type 7893 * value - Value 7894 */ 7895 int 7896 bcmi_esw_portctrl_llfc_set(int unit, bcm_port_t port, bcm_port_control_t type, int value) 7897 { 7898 #ifdef PORTMOD_SUPPORT 7899 int rv = BCM_E_UNAVAIL; 7900 soc_reg_t port_config; 7901 int llfc_enable = 0; 7902 portmod_llfc_control_t control; 7903 #if defined(BCM_APACHE_SUPPORT) 7904 uint32 rval; 7905 #endif 7906 7907 switch(type) { 7908 case bcmPortControlLLFCReceive: 7909 case bcmPortControlSAFCReceive: 7910 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7911 if (SOC_IS_XGS3_SWITCH(unit)) { 7912 7913 if (!SOC_PORT_VALID(unit, port)) { 7914 return BCM_E_PORT; 7915 } 7916 if ((!IS_HG_PORT(unit, port)) && (!IS_CPRI_PORT(unit, port))) { 7917 return BCM_E_UNAVAIL; 7918 } 7919 PORT_LOCK(unit); 7920 rv = portmod_port_llfc_control_get(unit, port, &control); 7921 if(PORTMOD_SUCCESS(rv)) { 7922 control.rx_enable = value; 7923 rv = portmod_port_llfc_control_set(unit,port, &control); 7924 if(PORTMOD_SUCCESS(rv)) { 7925 if( value == 0 ) { 7926 rv = portmod_port_llfc_control_get(unit, port, &control); 7927 if(PORTMOD_SUCCESS(rv)) { 7928 llfc_enable = control.rx_enable ; 7929 } 7930 } else { 7931 llfc_enable = TRUE; 7932 } 7933 } 7934 } 7935 PORT_UNLOCK(unit); 7936 if (SOC_REG_FIELD_VALID(unit, XLPORT_CONFIGr, LLFC_ENf)) { 7937 port_config = XLPORT_CONFIGr; 7938 } else if (SOC_REG_FIELD_VALID(unit, XPORT_CONFIGr, LLFC_ENf)) { 7939 port_config = XPORT_CONFIGr; 7940 } else if (SOC_REG_FIELD_VALID(unit, PORT_CONFIGr, LLFC_ENf)) { 7941 port_config = PORT_CONFIGr; 7942 } else { 7943 port_config = INVALIDr; 7944 } 7945 7946 if (port_config != INVALIDr){ 7947 BCM_IF_ERROR_RETURN 7948 (soc_reg_field32_modify(unit, port_config, port, LLFC_ENf, 7949 llfc_enable ? 1 : 0)); 7950 } 7951 } 7952 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7953 break; 7954 case bcmPortControlLLFCTransmit: 7955 case bcmPortControlSAFCTransmit: 7956 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7957 if (SOC_IS_XGS3_SWITCH(unit)) { 7958 if (!SOC_PORT_VALID(unit, port)) { 7959 return BCM_E_PORT; 7960 } 7961 if (!IS_HG_PORT(unit, port)) { 7962 return BCM_E_UNAVAIL; 7963 } 7964 PORT_LOCK(unit); 7965 rv = portmod_port_llfc_control_get(unit, port, &control); 7966 if(PORTMOD_SUCCESS(rv)) { 7967 control.tx_enable = value; 7968 rv = portmod_port_llfc_control_set(unit,port, &control); 7969 if(PORTMOD_SUCCESS(rv)) { 7970 if( value == 0 ) { 7971 rv = portmod_port_llfc_control_get(unit, port, &control); 7972 if(PORTMOD_SUCCESS(rv)) { 7973 llfc_enable = control.tx_enable ; 7974 } 7975 } else { 7976 llfc_enable = TRUE; 7977 } 7978 } 7979 } 7980 PORT_UNLOCK(unit); 7981 if (SOC_REG_FIELD_VALID(unit, XLPORT_CONFIGr, LLFC_ENf)) { 7982 port_config = XLPORT_CONFIGr; 7983 } else if (SOC_REG_FIELD_VALID(unit, XPORT_CONFIGr, LLFC_ENf)) { 7984 port_config = XPORT_CONFIGr; 7985 } else if (SOC_REG_FIELD_VALID(unit, PORT_CONFIGr, LLFC_ENf)) { 7986 port_config = PORT_CONFIGr; 7987 } else { 7988 port_config = INVALIDr; 7989 } 7990 7991 if (port_config != INVALIDr){ 7992 BCM_IF_ERROR_RETURN 7993 (soc_reg_field32_modify(unit, port_config, port, LLFC_ENf, 7994 llfc_enable ? 1 : 0)); 7995 } 7996 #if defined(BCM_APACHE_SUPPORT) 7997 if ( SOC_IS_APACHE(unit)) { 7998 SOC_IF_ERROR_RETURN 7999 (soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr, 8000 port, 0, &rval)); 8001 8002 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 8003 PORT_PRI_XON_ENABLEf, 8004 llfc_enable ? 0xffff : 0); 8005 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 8006 PORT_PAUSE_ENABLEf, llfc_enable ? 0 : 1); 8007 8008 SOC_IF_ERROR_RETURN 8009 (soc_reg32_set(unit, THDI_INPUT_PORT_XON_ENABLESr, 8010 port, 0, rval)); 8011 } 8012 #endif 8013 8014 } 8015 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 8016 break; 8017 default: 8018 break; 8019 } 8020 return rv; 8021 #else /* PORTMOD_SUPPORT */ 8022 return BCM_E_UNAVAIL; 8023 #endif /* PORTMOD_SUPPORT */ 8024 } 8025 8026 /* 8027 * Function: 8028 * bcmi_esw_portctrl_link_get 8029 * Purpose: 8030 * Return current PHY up/down status 8031 * Parameters: 8032 * unit - StrataSwitch Unit #. 8033 * port - StrataSwitch port #. 8034 * hw - If TRUE, assume hardware linkscan is active and use it 8035 * to reduce PHY reads. 8036 * If FALSE, do not use information from hardware linkscan. 8037 * up - (OUT) TRUE for link up, FALSE for link down. 8038 * Returns: 8039 * BCM_E_NONE 8040 * BCM_E_XXX 8041 */ 8042 int 8043 bcmi_esw_portctrl_link_get(int unit, bcm_gport_t port, int hw, int *up) 8044 { 8045 #ifdef PORTMOD_SUPPORT 8046 int rv; 8047 int flags = 0; 8048 portctrl_pport_t pport; 8049 8050 /* Make sure port module is initialized. */ 8051 PORTCTRL_INIT_CHECK(unit); 8052 8053 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8054 8055 PORT_LOCK(unit); 8056 8057 if (hw) { 8058 pbmp_t hw_linkstat; 8059 8060 rv = soc_linkscan_hw_link_get(unit, &hw_linkstat); 8061 8062 *up = PBMP_MEMBER(hw_linkstat, port); 8063 8064 /* 8065 * We need to confirm link down because we may receive false link 8066 * change interrupts when hardware and software linkscan are mixed. 8067 * Processing a false link down event is known to cause packet 8068 * loss, which is obviously unacceptable. 8069 */ 8070 if (!(*up)) { 8071 rv = portmod_port_link_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, up); 8072 } 8073 } else { 8074 if (SOC_IS_RCPU_ONLY(unit)) { 8075 PORTMOD_PORT_ENABLE_MAC_SET(flags); 8076 rv = portmod_port_enable_get(unit, pport, flags, up); 8077 } else { 8078 rv = portmod_port_link_get(unit, pport, PORTMOD_INIT_F_EXTERNAL_MOST_ONLY, up); 8079 } 8080 } 8081 8082 PORT_UNLOCK(unit); 8083 8084 LOG_VERBOSE(BSL_LS_BCM_PORT, 8085 (BSL_META_UP(unit, port, 8086 "Get port link status: u=%d p=%d hw=%d up=%d rv=%d\n"), 8087 unit, port, hw, *up, rv)); 8088 8089 return rv; 8090 8091 #else /* PORTMOD_SUPPORT */ 8092 return BCM_E_UNAVAIL; 8093 #endif /* PORTMOD_SUPPORT */ 8094 } 8095 8096 /* 8097 * Function: 8098 * bcmi_esw_portctrl_lag_failover_disable 8099 * Purpose: 8100 * Disable lag failover 8101 * 8102 * Parameters: 8103 * unit - StrataSwitch unit number. 8104 * port - Port. 8105 */ 8106 int 8107 bcmi_esw_portctrl_lag_failover_disable(int unit, bcm_gport_t port) 8108 { 8109 #ifdef PORTMOD_SUPPORT 8110 int rv = BCM_E_NONE; 8111 portctrl_pport_t pport; 8112 8113 PORTCTRL_INIT_CHECK(unit); 8114 8115 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8116 8117 PORT_LOCK(unit); 8118 rv = portmod_port_lag_failover_disable(unit, pport); 8119 PORT_UNLOCK(unit); 8120 return rv; 8121 #else /* PORTMOD_SUPPORT */ 8122 return BCM_E_UNAVAIL; 8123 #endif /* PORTMOD_SUPPORT */ 8124 } 8125 8126 /* 8127 * Function: 8128 * bcmi_esw_portctrl_lag_failover_loopback_get 8129 * Purpose: 8130 * Get lag failover loopback mode for specified port. 8131 * 8132 * Parameters: 8133 * unit - StrataSwitch unit number. 8134 * port - Port. 8135 * value - Value 8136 */ 8137 int 8138 bcmi_esw_portctrl_lag_failover_loopback_get(int unit, 8139 bcm_gport_t port, int* value) 8140 { 8141 #ifdef PORTMOD_SUPPORT 8142 int rv = BCM_E_NONE; 8143 portctrl_pport_t pport; 8144 8145 PORTCTRL_INIT_CHECK(unit); 8146 8147 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8148 8149 PORT_LOCK(unit); 8150 rv = portmod_port_lag_failover_loopback_get(unit, pport, value); 8151 PORT_UNLOCK(unit); 8152 return rv; 8153 #else /* PORTMOD_SUPPORT */ 8154 return BCM_E_UNAVAIL; 8155 #endif /* PORTMOD_SUPPORT */ 8156 } 8157 8158 /* 8159 * Function: 8160 * bcmi_esw_portctrl_lag_failover_status_toggle 8161 * Purpose: 8162 * Toggle lag failover status 8163 * 8164 * Parameters: 8165 * unit - StrataSwitch unit number. 8166 * port - Port. 8167 */ 8168 int 8169 bcmi_esw_portctrl_lag_failover_status_toggle(int unit, bcm_gport_t port) 8170 { 8171 #ifdef PORTMOD_SUPPORT 8172 int rv = BCM_E_NONE; 8173 portctrl_pport_t pport; 8174 8175 PORTCTRL_INIT_CHECK(unit); 8176 8177 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8178 8179 PORT_LOCK(unit); 8180 rv = portmod_port_lag_failover_status_toggle(unit, pport); 8181 PORT_UNLOCK(unit); 8182 return rv; 8183 #else /* PORTMOD_SUPPORT */ 8184 return BCM_E_UNAVAIL; 8185 #endif /* PORTMOD_SUPPORT */ 8186 } 8187 8188 /* 8189 * Function: 8190 * bcmi_esw_portctrl_lag_remove_failover_lpbk_set 8191 * Purpose: 8192 * Set lag remove failover loopback 8193 * 8194 * Parameters: 8195 * unit - StrataSwitch unit number. 8196 * port - Port. 8197 */ 8198 int 8199 bcmi_esw_portctrl_lag_remove_failover_lpbk_set(int unit, 8200 bcm_gport_t port, int value) 8201 { 8202 #ifdef PORTMOD_SUPPORT 8203 int rv = BCM_E_NONE; 8204 portctrl_pport_t pport; 8205 8206 PORTCTRL_INIT_CHECK(unit); 8207 8208 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8209 8210 PORT_LOCK(unit); 8211 rv = portmod_port_lag_remove_failover_lpbk_set(unit, pport, value); 8212 PORT_UNLOCK(unit); 8213 return rv; 8214 #else /* PORTMOD_SUPPORT */ 8215 return BCM_E_UNAVAIL; 8216 #endif /* PORTMOD_SUPPORT */ 8217 } 8218 8219 /* 8220 * Function: 8221 * bcmi_esw_portctrl_trunk_hwfailover_set 8222 * Purpose: 8223 * Set trunk hwfailover 8224 * 8225 * Parameters: 8226 * unit - StrataSwitch unit number. 8227 * port - Port. 8228 * hw_count - hw count 8229 */ 8230 int 8231 bcmi_esw_portctrl_trunk_hwfailover_set(int unit, bcm_gport_t port, int hw_count) 8232 { 8233 #ifdef PORTMOD_SUPPORT 8234 int rv = BCM_E_NONE; 8235 portctrl_pport_t pport; 8236 8237 PORTCTRL_INIT_CHECK(unit); 8238 8239 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8240 8241 PORT_LOCK(unit); 8242 rv = portmod_port_trunk_hwfailover_config_set(unit, pport, hw_count); 8243 PORT_UNLOCK(unit); 8244 return rv; 8245 #else /* PORTMOD_SUPPORT */ 8246 return BCM_E_UNAVAIL; 8247 #endif /* PORTMOD_SUPPORT */ 8248 } 8249 8250 #ifdef BCM_TRIDENT2_SUPPORT 8251 /* 8252 * Function: 8253 * bcmi_esw_td2_portctrl_lanes_set 8254 * Purpose: 8255 * 8256 * Parameters: 8257 * unit - StrataSwitch unit number. 8258 * port_base - Port Base. 8259 * lanes - lanes 8260 * Returns: 8261 * BCM_E_NONE 8262 * BCM_E_INTERNAL - internal error. 8263 * Notes: 8264 */ 8265 int 8266 bcmi_esw_td2_portctrl_lanes_set(int unit, bcm_port_t port_base, int lanes) 8267 { 8268 #ifdef PORTMOD_SUPPORT 8269 soc_info_t *si = &SOC_INFO(unit); 8270 soc_td2_port_lanes_t lanes_ctrl; 8271 int port, i; 8272 int enable, okay; 8273 8274 sal_memset(&lanes_ctrl, 0, sizeof(lanes_ctrl)); 8275 lanes_ctrl.port_base = port_base; 8276 lanes_ctrl.lanes = lanes; 8277 SOC_IF_ERROR_RETURN 8278 (soc_trident2_port_lanes_validate(unit, &lanes_ctrl)); 8279 8280 if(lanes_ctrl.lanes == lanes_ctrl.cur_lanes) { 8281 return BCM_E_NONE; 8282 } 8283 8284 /* All existing ports are required to be disasbled */ 8285 SOC_IF_ERROR_RETURN(bcm_esw_port_enable_get(unit, port_base, &enable)); 8286 if (enable) { 8287 return BCM_E_BUSY; 8288 } 8289 if(lanes_ctrl.lanes > lanes_ctrl.cur_lanes) { /* port(s) to be removed */ 8290 for (i = 0; i < lanes_ctrl.phy_ports_len; i++) { 8291 port = si->port_p2l_mapping[lanes_ctrl.phy_ports[i]]; 8292 SOC_IF_ERROR_RETURN(bcm_esw_port_enable_get(unit, port, &enable)); 8293 if (enable) { 8294 return BCM_E_BUSY; 8295 } 8296 } 8297 } 8298 SOC_IF_ERROR_RETURN 8299 (soc_trident2_port_lanes_set(unit, &lanes_ctrl)); 8300 8301 /* Probe PHY on all port(s) after conversion */ 8302 BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port_base, &okay)); 8303 BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port_base, FALSE)); 8304 if(lanes_ctrl.lanes < lanes_ctrl.cur_lanes) { /* port(s) to be added */ 8305 for (i = 0; i < lanes_ctrl.phy_ports_len; i++) { 8306 port = si->port_p2l_mapping[lanes_ctrl.phy_ports[i]]; 8307 BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port, &okay)); 8308 BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port, FALSE)); 8309 } 8310 } 8311 8312 return BCM_E_NONE; 8313 #else /* PORTMOD_SUPPORT */ 8314 return BCM_E_UNAVAIL; 8315 #endif /* PORTMOD_SUPPORT */ 8316 8317 } 8318 #endif /* BCM_TRIDENT2_SUPPORT */ 8319 8320 8321 /* 8322 * Function: 8323 * bcmi_esw_portctrl_hwfailover_enable_set 8324 * Purpose: 8325 * Set front panel trunk hardware failover config. 8326 * Parameters: 8327 * unit - (IN) SOC unit number. 8328 * port - (IN) Port ID of the fail port. 8329 * enable - (IN) Set the HW failover config. 8330 * Returns: 8331 * BCM_E_xxx 8332 */ 8333 int 8334 bcmi_esw_portctrl_hwfailover_enable_set(int unit, bcm_gport_t port, int enable) 8335 { 8336 #ifdef PORTMOD_SUPPORT 8337 int rv; 8338 portctrl_pport_t pport; 8339 8340 /* Make sure port module is initialized. */ 8341 PORTCTRL_INIT_CHECK(unit); 8342 8343 BCM_IF_ERROR_RETURN 8344 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8345 8346 PORT_LOCK(unit); 8347 rv = portmod_port_trunk_hwfailover_config_set(unit, pport, enable); 8348 PORT_UNLOCK(unit); 8349 8350 if (PORTMOD_FAILURE(rv)) { 8351 LOG_VERBOSE(BSL_LS_BCM_TRUNK, 8352 (BSL_META_UP(unit, port, 8353 "Failed to set HW failover: u=%d p=%d rv=%d\n"), 8354 unit, port, rv)); 8355 } 8356 8357 return rv; 8358 8359 #else /* PORTMOD_SUPPORT */ 8360 return BCM_E_UNAVAIL; 8361 #endif /* PORTMOD_SUPPORT */ 8362 } 8363 8364 /* 8365 * Function: 8366 * bcmi_esw_portctrl_hwfailover_enable_get 8367 * Purpose: 8368 * Get front-panel trunk hardware failover config. 8369 * Parameters: 8370 * unit - (IN) SOC unit number. 8371 * port - (IN) Port ID of the fail port. 8372 * enable - (OUT) Get the HW failover config. 8373 * Returns: 8374 * BCM_E_xxx 8375 */ 8376 int 8377 bcmi_esw_portctrl_hwfailover_enable_get(int unit, bcm_gport_t port, int *enable) 8378 { 8379 #ifdef PORTMOD_SUPPORT 8380 int rv; 8381 portctrl_pport_t pport; 8382 8383 /* Make sure port module is initialized. */ 8384 PORTCTRL_INIT_CHECK(unit); 8385 8386 BCM_IF_ERROR_RETURN 8387 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8388 8389 PORT_LOCK(unit); 8390 rv = portmod_port_trunk_hwfailover_config_get(unit, pport, enable); 8391 PORT_UNLOCK(unit); 8392 8393 if (PORTMOD_FAILURE(rv)) { 8394 LOG_VERBOSE(BSL_LS_BCM_TRUNK, 8395 (BSL_META_UP(unit, port, 8396 "Failed to get HW failover config: u=%d p=%d rv=%d\n"), 8397 unit, port, rv)); 8398 } 8399 8400 return rv; 8401 8402 #else /* PORTMOD_SUPPORT */ 8403 return BCM_E_UNAVAIL; 8404 #endif /* PORTMOD_SUPPORT */ 8405 } 8406 8407 /* 8408 * Function: 8409 * bcmi_esw_portctrl_hwfailover_status_get 8410 * Purpose: 8411 * Get front-panel trunk hardware failover status. 8412 * Parameters: 8413 * unit - (IN) SOC unit number. 8414 * port - (IN) Port ID of the fail port. 8415 * status - (OUT) failover status. 8416 * Returns: 8417 * BCM_E_xxx 8418 */ 8419 int 8420 bcmi_esw_portctrl_hwfailover_status_get(int unit, bcm_gport_t port, int *status) 8421 { 8422 #ifdef PORTMOD_SUPPORT 8423 int rv; 8424 portctrl_pport_t pport; 8425 8426 /* Make sure port module is initialized. */ 8427 PORTCTRL_INIT_CHECK(unit); 8428 8429 BCM_IF_ERROR_RETURN 8430 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8431 8432 PORT_LOCK(unit); 8433 rv = portmod_port_trunk_hwfailover_status_get(unit, pport, status); 8434 PORT_UNLOCK(unit); 8435 8436 if (PORTMOD_FAILURE(rv)) { 8437 LOG_VERBOSE(BSL_LS_BCM_TRUNK, 8438 (BSL_META_UP(unit, port, 8439 "Failed to get HW failover status: u=%d p=%d rv=%d\n"), 8440 unit, port, rv)); 8441 } 8442 8443 return rv; 8444 8445 #else /* PORTMOD_SUPPORT */ 8446 return BCM_E_UNAVAIL; 8447 #endif /* PORTMOD_SUPPORT */ 8448 } 8449 8450 /* 8451 * Function: 8452 * bcmi_esw_portctrl_phy_control_get 8453 * Description: 8454 * Set PHY specific properties 8455 * Parameters: 8456 * unit device number 8457 * port port number 8458 * type configuration type 8459 * value value for the configuration 8460 * Return: 8461 * BCM_E_XXX 8462 */ 8463 int 8464 bcmi_esw_portctrl_phy_control_get(int unit, bcm_gport_t port, 8465 bcm_port_phy_control_t type, uint32 *value) 8466 { 8467 #ifdef PORTMOD_SUPPORT 8468 int rv; 8469 portctrl_pport_t pport; 8470 int phy_lane = -1; 8471 int phyn = -1, sys_side = 0; 8472 bcm_port_t local_port = -1; 8473 8474 /* Make sure port module is initialized. */ 8475 PORTCTRL_INIT_CHECK(unit); 8476 8477 BCM_IF_ERROR_RETURN 8478 (_bcm_esw_port_gport_phyn_validate(unit, port, 8479 &local_port, &phyn, 8480 &phy_lane, &sys_side)); 8481 8482 if (local_port != -1) { 8483 port = local_port; 8484 } 8485 8486 BCM_IF_ERROR_RETURN 8487 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8488 8489 PORT_LOCK(unit); 8490 8491 if (local_port == -1) { 8492 /* Configure outermost PHY (common case) */ 8493 rv = soc_portctrl_phy_control_get(unit, pport, 8494 -1, -1, 0, 8495 (soc_phy_control_t) type, value); 8496 } else { 8497 /* Configure PHY specified by GPORT */ 8498 rv = soc_portctrl_phy_control_get(unit, pport, 8499 phyn, phy_lane, sys_side, 8500 (soc_phy_control_t) type, value); 8501 } 8502 8503 PORT_UNLOCK(unit); 8504 8505 return rv; 8506 8507 #else /* PORTMOD_SUPPORT */ 8508 return BCM_E_UNAVAIL; 8509 #endif /* PORTMOD_SUPPORT */ 8510 } 8511 8512 /* 8513 * Function: 8514 * bcmi_esw_portctrl_phy_control_set 8515 * Description: 8516 * Set PHY specific properties 8517 * Parameters: 8518 * unit device number 8519 * port port number 8520 * type configuration type 8521 * value new value for the configuration 8522 * Return: 8523 * BCM_E_XXX 8524 */ 8525 int 8526 bcmi_esw_portctrl_phy_control_set(int unit, bcm_gport_t port, 8527 bcm_port_phy_control_t type, uint32 value) 8528 { 8529 #ifdef PORTMOD_SUPPORT 8530 int rv; 8531 portctrl_pport_t pport; 8532 int phy_lane = -1; 8533 int phyn = -1, sys_side = 0; 8534 bcm_port_t local_port = -1; 8535 _bcm_port_info_t *port_info; 8536 8537 /* Make sure port module is initialized. */ 8538 PORTCTRL_INIT_CHECK(unit); 8539 8540 BCM_IF_ERROR_RETURN 8541 (_bcm_esw_port_gport_phyn_validate(unit, port, 8542 &local_port, &phyn, 8543 &phy_lane, &sys_side)); 8544 8545 if (local_port != -1) { 8546 port = local_port; 8547 } 8548 8549 BCM_IF_ERROR_RETURN 8550 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 8551 8552 PORT_LOCK(unit); 8553 8554 if (local_port == -1) { 8555 /* Configure outermost PHY (common case) */ 8556 rv = soc_portctrl_phy_control_set(unit, pport, 8557 -1, -1, 0, 8558 (soc_phy_control_t) type, value); 8559 } else { 8560 /* Configure PHY specified by GPORT */ 8561 rv = soc_portctrl_phy_control_set(unit, pport, 8562 phyn, phy_lane, sys_side, 8563 (soc_phy_control_t) type, value); 8564 } 8565 8566 /* Provide Warmboot support for SW RX LOS status */ 8567 if (SOC_SUCCESS(rv) && 8568 (type == BCM_PORT_PHY_CONTROL_SOFTWARE_RX_LOS)) { 8569 _bcm_port_info_access(unit, port, &port_info); 8570 port_info->rx_los = value; 8571 } 8572 8573 PORT_UNLOCK(unit); 8574 8575 return rv; 8576 8577 #else /* PORTMOD_SUPPORT */ 8578 return BCM_E_UNAVAIL; 8579 #endif /* PORTMOD_SUPPORT */ 8580 } 8581 8582 8583 #ifdef PORTMOD_SUPPORT 8584 /* 8585 * Function: 8586 * _bcm_esw_portctrl_control_pfc_receive_set 8587 * Purpose: 8588 * Set the bcmPortControlPFCReceive port control. 8589 * Parameters: 8590 * unit - (IN) Unit number. 8591 * port - (IN) BCM port number (NONE gport format). 8592 * pport - (IN) Portmod port number. 8593 * value - (IN) value to be set. 8594 * Returns: 8595 * BCM_E_XXX 8596 * Notes: 8597 * Assumes caller will: 8598 * - Check for PORTCTRL_INIT() 8599 * - Provide LOCKs 8600 */ 8601 STATIC int 8602 _bcm_esw_portctrl_control_pfc_receive_set(int unit, bcm_port_t port, 8603 portctrl_pport_t pport, 8604 int value) 8605 { 8606 int pfc_enable; 8607 portmod_pfc_control_t pfc_control; 8608 8609 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 8610 return BCM_E_UNAVAIL; 8611 } 8612 8613 PORTMOD_IF_ERROR_RETURN 8614 (portmod_port_pfc_control_get(unit, pport, &pfc_control)); 8615 8616 pfc_control.rx_enable = value; 8617 PORTMOD_IF_ERROR_RETURN 8618 (portmod_port_pfc_control_set(unit, pport, &pfc_control)); 8619 8620 if (value == 0) { 8621 pfc_enable = pfc_control.tx_enable; 8622 } else { 8623 pfc_enable = TRUE; 8624 } 8625 8626 if (value == 0) { 8627 /* Disabling RX, flush MMU XOFF state */ 8628 pfc_control.force_xon = 1; 8629 PORTMOD_IF_ERROR_RETURN 8630 (portmod_port_pfc_control_set(unit, pport, &pfc_control)); 8631 pfc_control.force_xon = 0; 8632 PORTMOD_IF_ERROR_RETURN 8633 (portmod_port_pfc_control_set(unit, pport, &pfc_control)); 8634 } 8635 8636 /* Stats enable */ 8637 pfc_control.stats_en = pfc_enable ? 1 : 0; 8638 PORTMOD_IF_ERROR_RETURN 8639 (portmod_port_pfc_control_set(unit, pport, &pfc_control)); 8640 8641 if (SOC_REG_IS_VALID(unit, XPORT_TO_MMU_BKPr) && (pfc_enable == 0)) { 8642 BCM_IF_ERROR_RETURN(WRITE_XPORT_TO_MMU_BKPr(unit, port, 0)); 8643 } else if (SOC_REG_IS_VALID(unit, XPORT_TO_MMU_BKP_64r) && (pfc_enable == 0)) { 8644 uint64 zero64; 8645 COMPILER_64_ZERO(zero64); 8646 BCM_IF_ERROR_RETURN(WRITE_XPORT_TO_MMU_BKP_64r(unit, port, zero64)); 8647 } 8648 if (SOC_REG_IS_VALID(unit, MMU_INTFI_EGR_PORT_CFGr)) { 8649 uint32 rval = 0; 8650 SOC_IF_ERROR_RETURN 8651 (soc_reg32_get(unit, MMU_INTFI_EGR_PORT_CFGr, port, 0, &rval)); 8652 soc_reg_field_set(unit, MMU_INTFI_EGR_PORT_CFGr, 8653 &rval, DISABLE_Q_FCf, pfc_enable ? 0 : 1); 8654 SOC_IF_ERROR_RETURN 8655 (soc_reg32_set(unit, MMU_INTFI_EGR_PORT_CFGr, port, 0, rval)); 8656 } 8657 return BCM_E_NONE; 8658 } 8659 8660 8661 /* 8662 * Function: 8663 * _bcm_esw_portctrl_control_pfc_transmit_set 8664 * Purpose: 8665 * Set the bcmPortControlPFCTransmit port control. 8666 * Parameters: 8667 * unit - (IN) Unit number. 8668 * port - (IN) BCM port number (NONE gport format). 8669 * pport - (IN) Portmod port number. 8670 * value - (IN) value to be set. 8671 * Returns: 8672 * BCM_E_XXX 8673 * Notes: 8674 * Assumes caller will: 8675 * - Check for PORTCTRL_INIT() 8676 * - Provide LOCKs 8677 */ 8678 STATIC int 8679 _bcm_esw_portctrl_control_pfc_transmit_set(int unit, bcm_port_t port, 8680 portctrl_pport_t pport, 8681 int value) 8682 { 8683 int pfc_enable; 8684 portmod_pfc_control_t pfc_control; 8685 uint32 rval; 8686 8687 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 8688 return BCM_E_UNAVAIL; 8689 } 8690 8691 PORTMOD_IF_ERROR_RETURN 8692 (portmod_port_pfc_control_get(unit, pport, &pfc_control)); 8693 8694 pfc_control.tx_enable = value; 8695 PORTMOD_IF_ERROR_RETURN 8696 (portmod_port_pfc_control_set(unit, pport, &pfc_control)); 8697 8698 if (value == 0) { 8699 pfc_enable = pfc_control.rx_enable; 8700 } else { 8701 pfc_enable = TRUE; 8702 } 8703 8704 #ifdef BCM_TOMAHAWK3_SUPPORT 8705 if (SOC_IS_TOMAHAWK3(unit)) { 8706 SOC_IF_ERROR_RETURN 8707 (bcm_th3_mmu_pfc_tx_config_set(unit, port, 8708 pfc_enable, 0xff)); 8709 } 8710 #endif 8711 8712 /* Port config settings */ 8713 if (SOC_REG_IS_VALID(unit, THDI_INPUT_PORT_XON_ENABLESr)) { 8714 SOC_IF_ERROR_RETURN 8715 (soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr, 8716 port, 0, &rval)); 8717 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 8718 PORT_PRI_XON_ENABLEf, 8719 pfc_enable ? 0xffff : 0); 8720 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 8721 PORT_PAUSE_ENABLEf, pfc_enable ? 0 : 1); 8722 SOC_IF_ERROR_RETURN 8723 (soc_reg32_set(unit, THDI_INPUT_PORT_XON_ENABLESr, 8724 port, 0, rval)); 8725 } 8726 8727 /* Stats enable */ 8728 pfc_control.stats_en = pfc_enable ? 1 : 0; 8729 PORTMOD_IF_ERROR_RETURN 8730 (portmod_port_pfc_control_set(unit, pport, &pfc_control)); 8731 8732 return BCM_E_NONE; 8733 } 8734 8735 8736 /* 8737 * Function: 8738 * _bcm_esw_portctrl_control_eee_enable_set 8739 * Purpose: 8740 * Set the bcmPortControlEEEEnable port control. 8741 * Parameters: 8742 * unit - (IN) Unit number. 8743 * port - (IN) BCM port number (NONE gport format). 8744 * pport - (IN) Portmod port number. 8745 * value - (IN) value to be set. 8746 * Returns: 8747 * BCM_E_XXX 8748 * Notes: 8749 * Assumes caller will: 8750 * - Check for PORTCTRL_INIT() 8751 * - Provide LOCKs 8752 */ 8753 STATIC int 8754 _bcm_esw_portctrl_control_eee_enable_set(int unit, bcm_port_t port, 8755 portctrl_pport_t pport, 8756 int value) 8757 { 8758 portmod_eee_t eee; 8759 uint32 phy_val; 8760 bcm_port_t g_port; 8761 int rv, phyn; 8762 8763 8764 PORTMOD_IF_ERROR_RETURN(portmod_eee_t_init(unit, &eee)); 8765 8766 rv = portmod_port_eee_get(unit, pport, &eee); 8767 8768 /*if rv is SOC_E_UNAVAIL, Native EEE is not support for this MAC*/ 8769 if ((rv != SOC_E_UNAVAIL) && 8770 (soc_feature (unit, soc_feature_eee)) && 8771 (bcmi_esw_portctrl_phy_control_get(unit, port, 8772 BCM_PORT_PHY_CONTROL_EEE, 8773 &phy_val) != SOC_E_UNAVAIL)) { 8774 8775 /* If MAC/Switch is EEE aware (Native EEE mode is supported) 8776 * and PHY also supports Native EEE mode 8777 */ 8778 8779 /* a. Disable AutoGrEEEn mode by PHY if applicable */ 8780 rv = (bcmi_esw_portctrl_phy_control_get(unit, port, 8781 BCM_PORT_PHY_CONTROL_EEE_AUTO, 8782 &phy_val)); 8783 8784 if ((rv != SOC_E_UNAVAIL) && (phy_val != 0)) { 8785 (void)bcmi_esw_portctrl_phy_control_set(unit, port, 8786 BCM_PORT_PHY_CONTROL_EEE_AUTO, 8787 0); 8788 } 8789 8790 /* b. Enable/Disable Native EEE in PHY */ 8791 rv = bcmi_esw_portctrl_phy_control_set (unit, port, 8792 BCM_PORT_PHY_CONTROL_EEE, value ? 1 : 0); 8793 8794 if (SOC_SUCCESS(rv)) { 8795 /* EEE standard compliance Work Around: 8796 * Store the software copy of eee value in eee_cfg flag 8797 */ 8798 /*eee_cfg[unit][port] = value;*/ 8799 BCM_IF_ERROR_RETURN 8800 (bcmi_esw_port_eee_cfg_set(unit, port, value)); 8801 /* If (value==1), EEE will be enabled in MAC after 1 sec. 8802 * during linkscan update*/ 8803 if (value == 0) { 8804 eee.enable = 0; 8805 /* Disable EEE in MAC immediately*/ 8806 rv = portmod_port_eee_set(unit, port, &eee); 8807 } 8808 8809 /* Notify Int-PHY to bypass LPI for native EEE mode. 8810 * 8811 * Note : 8812 * 1. Not all internal SerDes support the setting to 8813 * enable/disable bypass LPI signal. 8814 * 2. Int-PHY to bypass LPI will sync with Ext-PHY's EEE 8815 * enabling status for Native EEE mode. 8816 */ 8817 /*phyn == 0 ( outermost ) 8818 phyn == 1 ( internal ) 8819 phyn == >1 ( ext phy ) 8820 */ 8821 phyn = 1; 8822 BCM_PHY_GPORT_PHYN_PORT_SET(g_port, phyn, port); 8823 (void)bcmi_esw_portctrl_phy_control_set (unit, g_port, 8824 BCM_PORT_PHY_CONTROL_EEE, PORTMOD_EEE_ENABLE_LPI_BYPASS_SET(value)); 8825 } 8826 8827 } else { 8828 /* If native EEE mode is not supported, 8829 * set PHY in AutoGrEEEn mode. 8830 */ 8831 8832 /* a. Disable Native EEE mode in PHY if applicable */ 8833 rv = (bcmi_esw_portctrl_phy_control_get(unit, port, 8834 BCM_PORT_PHY_CONTROL_EEE, 8835 &phy_val)); 8836 8837 if ((rv != SOC_E_UNAVAIL) && (phy_val != 0)) { 8838 (void)bcmi_esw_portctrl_phy_control_set (unit, port, 8839 BCM_PORT_PHY_CONTROL_EEE, 8840 0); 8841 } 8842 8843 /* b. Enable/Disable AutoGrEEEn in PHY. 8844 * If PHY does not support AutoGrEEEn mode, 8845 * rv will be assigned SOC_E_UNAVAIL. 8846 */ 8847 rv = bcmi_esw_portctrl_phy_control_set (unit, port, 8848 BCM_PORT_PHY_CONTROL_EEE_AUTO, 8849 value ? 1 : 0); 8850 if (SOC_SUCCESS(rv)) { 8851 BCM_IF_ERROR_RETURN 8852 (bcmi_esw_port_eee_cfg_set(unit, port, value)); 8853 } 8854 } 8855 8856 return rv; 8857 } 8858 8859 /* 8860 * Function: 8861 * _bcm_esw_portctrl_eee_statistics_clear 8862 * Purpose: 8863 * Set the bcmPortControlEEEStatisticsClear port control. 8864 * Parameters: 8865 * unit - (IN) Unit number. 8866 * port - (IN) BCM port number (NONE gport format). 8867 * pport - (IN) Portmod port number. 8868 * value - (IN) value to be set. 8869 * Returns: 8870 * BCM_E_XXX 8871 * Notes: 8872 * Assumes caller will: 8873 * - Check for PORTCTRL_INIT() 8874 * - Provide LOCKs 8875 */ 8876 STATIC int 8877 _bcm_esw_portctrl_eee_statistics_clear(int unit, bcm_port_t port, 8878 portctrl_pport_t pport, 8879 int value) 8880 { 8881 8882 #if 0 8883 uint32 val = 0; 8884 uint64 val64; 8885 uint32 phy_val; 8886 int idx; 8887 soc_reg_t regs[] = { 8888 RX_EEE_LPI_DURATION_COUNTERr, 8889 RX_EEE_LPI_EVENT_COUNTERr, 8890 TX_EEE_LPI_DURATION_COUNTERr, 8891 TX_EEE_LPI_EVENT_COUNTERr 8892 }; 8893 8894 if (!soc_feature(unit, soc_feature_eee)) { 8895 return BCM_E_UNAVAIL; 8896 } 8897 8898 COMPILER_64_ZERO(val64); 8899 if ((MAC_CONTROL_GET(PORT(unit, port).p_mac, unit, port, 8900 SOC_MAC_CONTROL_EEE_ENABLE, &mac_val) 8901 != SOC_E_UNAVAIL) && 8902 (soc_phyctrl_control_get(unit, port, 8903 BCM_PORT_PHY_CONTROL_EEE, &phy_val) 8904 != SOC_E_UNAVAIL)) { 8905 8906 only for TD2... 8907 for (idx = 0; idx < sizeof(regs) / sizeof(regs[0]); idx++) { 8908 SOC_IF_ERROR_RETURN 8909 (soc_counter_set(unit, port, regs[idx], 0, val64)); 8910 } 8911 return ?? 8912 8913 /* MAC/Switch is EEE aware (Native EEE mode is supported) */ 8914 if (soc_feature(unit, soc_feature_unified_port)) { 8915 if (SOC_REG_IS_VALID(unit, PORT_XGXS_COUNTER_MODEr)) { 8916 _BCM_PORT_IF_ERROR_RETURN_WITH_UNLOCK 8917 (READ_PORT_XGXS_COUNTER_MODEr(unit, port, &val)); 8918 soc_reg_field_set(unit, PORT_XGXS_COUNTER_MODEr, &val, 8919 CNT_MODEf, 0); 8920 _BCM_PORT_IF_ERROR_RETURN_WITH_UNLOCK 8921 (WRITE_PORT_XGXS_COUNTER_MODEr(unit, port, val)); 8922 } 8923 } 8924 8925 /* Read counters to clear them*/ 8926 SOC_IF_ERROR_RETURN 8927 (READ_RX_EEE_LPI_DURATION_COUNTERr(unit, port, &val64)); 8928 SOC_IF_ERROR_RETURN 8929 (READ_RX_EEE_LPI_EVENT_COUNTERr(unit, port, &val64)); 8930 SOC_IF_ERROR_RETURN 8931 (READ_TX_EEE_LPI_DURATION_COUNTERr(unit, port, &val64)); 8932 SOC_IF_ERROR_RETURN 8933 (READ_TX_EEE_LPI_EVENT_COUNTERr(unit, port, &val64)); 8934 8935 /* Set counter rollover bit to 1*/ 8936 if (soc_feature(unit, soc_feature_unified_port)) { 8937 if (SOC_REG_IS_VALID(unit, 8938 PORT_XGXS_COUNTER_MODEr)) { 8939 SOC_IF_ERROR_RETURN 8940 (READ_PORT_XGXS_COUNTER_MODEr(unit, port, &val)); 8941 soc_reg_field_set(unit, PORT_XGXS_COUNTER_MODEr, &val, 8942 CNT_MODEf, 1); 8943 SOC_IF_ERROR_RETURN 8944 (WRITE_PORT_XGXS_COUNTER_MODEr(unit, port, val)); 8945 } 8946 } 8947 } else { 8948 /* native EEE mode is not supported, */ 8949 rv = soc_phyctrl_control_set 8950 (unit, port, 8951 BCM_PORT_PHY_CONTROL_EEE_STATISTICS_CLEAR, value); 8952 } 8953 #endif 8954 8955 return BCM_E_NONE; 8956 } 8957 #endif /* PORTMOD_SUPPORT */ 8958 8959 /* 8960 * Function: 8961 * bcmi_esw_portctrl_priority_group_config_set 8962 * Purpose: 8963 * Set the port priority group configuration. 8964 * Parameters: 8965 * unit - (IN) device id. 8966 * port - (IN) generic port. 8967 * priority_group - (IN) priority group id. 8968 * prigrp_config - (IN) structure describes port PG configuration. 8969 * Returns: 8970 * BCM_E_XXX 8971 */ 8972 int 8973 bcmi_esw_portctrl_priority_group_config_set(int unit, bcm_gport_t port, 8974 int priority_group, 8975 bcm_port_priority_group_config_t *prigrp_config) 8976 { 8977 #ifdef PORTMOD_SUPPORT 8978 int rv; 8979 int pfc_enable; 8980 portmod_pfc_control_t pfc_control; 8981 uint32 rval, pri_bmp; 8982 portctrl_pport_t pport; 8983 8984 /* Make sure port module is initialized. */ 8985 PORTCTRL_INIT_CHECK(unit); 8986 8987 if (!soc_feature(unit, soc_feature_priority_flow_control)) { 8988 return BCM_E_UNAVAIL; 8989 } 8990 if ((priority_group < PORTCTRL_PRIOROTY_GROUP_ID_MIN) || 8991 (priority_group > PORTCTRL_PRIOROTY_GROUP_ID_MAX)) { 8992 return BCM_E_PARAM; 8993 } 8994 if (prigrp_config == NULL) { 8995 return BCM_E_PARAM; 8996 } 8997 if (prigrp_config->shared_pool_xoff_enable || 8998 prigrp_config->shared_pool_discard_enable || 8999 prigrp_config->priority_enable_vector_mask) { 9000 return BCM_E_UNAVAIL; 9001 } 9002 9003 BCM_IF_ERROR_RETURN 9004 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 9005 9006 PORT_LOCK(unit); 9007 9008 rv = portmod_port_pfc_control_get(unit, pport, &pfc_control); 9009 if (PORTMOD_FAILURE(rv)) { 9010 PORT_UNLOCK(unit); 9011 return rv; 9012 } 9013 9014 rv = portmod_port_pfc_control_set(unit, pport, &pfc_control); 9015 if (PORTMOD_FAILURE(rv)) { 9016 PORT_UNLOCK(unit); 9017 return rv; 9018 } 9019 9020 if (prigrp_config->pfc_transmit_enable == 0) { 9021 pfc_enable = pfc_control.rx_enable; 9022 } else { 9023 pfc_enable = TRUE; 9024 } 9025 9026 /* Port config settings */ 9027 if (SOC_REG_IS_VALID(unit, THDI_INPUT_PORT_XON_ENABLESr)) { 9028 rv = soc_reg32_get(unit, THDI_INPUT_PORT_XON_ENABLESr, 9029 pport, 0, &rval); 9030 if (PORTMOD_FAILURE(rv)) { 9031 PORT_UNLOCK(unit); 9032 return rv; 9033 } 9034 pri_bmp = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval, 9035 PORT_PRI_XON_ENABLEf); 9036 if (prigrp_config->pfc_transmit_enable) { 9037 pri_bmp |= (1 << priority_group); 9038 } else { 9039 pri_bmp &= ~(1 << priority_group); 9040 } 9041 /* To cover higher 8 PFC classes that have no corresponding PG. */ 9042 if ((pri_bmp & 0xff) == 0) { 9043 pri_bmp = 0; 9044 } 9045 9046 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 9047 PORT_PRI_XON_ENABLEf, 9048 pfc_enable ? pri_bmp : 0); 9049 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 9050 PORT_PAUSE_ENABLEf, pfc_enable ? 0 : 1); 9051 rv = soc_reg32_set(unit, THDI_INPUT_PORT_XON_ENABLESr, 9052 pport, 0, rval); 9053 if (PORTMOD_FAILURE(rv)) { 9054 PORT_UNLOCK(unit); 9055 return rv; 9056 } 9057 } 9058 9059 /* Stats enable */ 9060 pfc_control.stats_en = pfc_enable ? 1 : 0; 9061 rv = portmod_port_pfc_control_set(unit, pport, &pfc_control); 9062 PORT_UNLOCK(unit); 9063 9064 return rv; 9065 #else /* PORTMOD_SUPPORT */ 9066 return BCM_E_UNAVAIL; 9067 #endif /* PORTMOD_SUPPORT */ 9068 9069 } 9070 9071 /* 9072 * Function: 9073 * bcmi_esw_portctrl_control_validate 9074 * Purpose: 9075 * Check that given port control feature in valid in Port Control. 9076 * Parameters: 9077 * unit - (IN) Unit number. 9078 * type - (IN) Port control feature bcmPortControlxxx. 9079 * valid - (OUT) Indicates if control feature is valid. 9080 * Returns: 9081 * BCM_E_XXX 9082 */ 9083 int 9084 bcmi_esw_portctrl_control_validate(int unit, bcm_port_control_t type, 9085 int *valid) 9086 { 9087 #ifdef PORTMOD_SUPPORT 9088 9089 PORTCTRL_INIT_CHECK(unit); 9090 9091 *valid = 0; 9092 switch (type) { 9093 case bcmPortControlEEEEnable: 9094 case bcmPortControlEEEReceiveDuration: 9095 case bcmPortControlEEEReceiveEventCount: 9096 case bcmPortControlEEEReceiveQuietTime: 9097 case bcmPortControlEEEReceiveSleepTime: 9098 case bcmPortControlEEEReceiveWakeTime: 9099 case bcmPortControlEEEStatisticsClear: 9100 case bcmPortControlEEETransmitDuration: 9101 case bcmPortControlEEETransmitEventCount: 9102 case bcmPortControlEEETransmitIdleTime: 9103 case bcmPortControlEEETransmitQuietTime: 9104 case bcmPortControlEEETransmitRefreshTime: 9105 case bcmPortControlEEETransmitSleepTime: 9106 case bcmPortControlEEETransmitWakeTime: 9107 case bcmPortControlFrameSpacingStretch: 9108 case bcmPortControlLinkdownTransmit: 9109 case bcmPortControlLinkFaultLocal: 9110 case bcmPortControlLinkFaultLocalEnable: 9111 case bcmPortControlLinkFaultRemote: 9112 case bcmPortControlLinkFaultRemoteEnable: 9113 case bcmPortControlPassControlFrames: 9114 case bcmPortControlPFCClasses: 9115 case bcmPortControlPFCDestMacNonOui: 9116 case bcmPortControlPFCDestMacOui: 9117 case bcmPortControlPFCEthertype: 9118 case bcmPortControlPFCOpcode: 9119 case bcmPortControlPFCPassFrames: 9120 case bcmPortControlPFCReceive: 9121 case bcmPortControlPFCRefreshTime: 9122 case bcmPortControlPFCTransmit: 9123 case bcmPortControlPFCXOffTime: 9124 case bcmPortControlPrbsPolynomial: 9125 case bcmPortControlPrbsRxEnable: 9126 case bcmPortControlPrbsRxStatus: 9127 case bcmPortControlPrbsTxEnable: 9128 case bcmPortControlPrbsTxInvertData: 9129 case bcmPortControlRxEnable: 9130 case bcmPortControlSerdesDriverTune: 9131 case bcmPortControlSerdesDriverEqualizationTuneStatusFarEnd: 9132 case bcmPortControlSerdesTuneMarginMax: 9133 case bcmPortControlSerdesTuneMarginMode: 9134 case bcmPortControlSerdesTuneMarginValue: 9135 case bcmPortControlTimestampTransmit: 9136 case bcmPortControlVrf: 9137 case bcmPortControlTimestampEnable: 9138 case bcmPortControlTXPISDMOverride: 9139 case bcmPortControlTXPISDMStatus: 9140 case bcmPortControlOOBFCTxReportIngEnable: 9141 case bcmPortControlOOBFCTxReportEgrEnable: 9142 *valid = 1; 9143 break; 9144 default: 9145 *valid = 0; 9146 break; 9147 } 9148 9149 return BCM_E_NONE; 9150 #else /* PORTMOD_SUPPORT */ 9151 return BCM_E_UNAVAIL; 9152 #endif /* PORTMOD_SUPPORT */ 9153 } 9154 9155 9156 /* 9157 * Function: 9158 * bcmi_esw_portctrl_control_set 9159 * Purpose: 9160 * Set specified port control feature. 9161 * Parameters: 9162 * unit - (IN) Unit number. 9163 * port - (IN) Port number. 9164 * type - (IN) Port control feature to set. 9165 * value - (IN) Value of port control feature. 9166 * Returns: 9167 * BCM_E_XXX 9168 * Notes: 9169 * Any new control needs to be included in 9170 * bcmi_esw_portctrl_control_validate(). 9171 */ 9172 int 9173 bcmi_esw_portctrl_control_set(int unit, bcm_gport_t port, 9174 bcm_port_control_t type, int value) 9175 { 9176 #ifdef PORTMOD_SUPPORT 9177 int rv = BCM_E_UNAVAIL; 9178 portctrl_pport_t pport; 9179 9180 PORTCTRL_INIT_CHECK(unit); 9181 9182 BCM_IF_ERROR_RETURN 9183 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 9184 9185 switch (type) { 9186 case bcmPortControlPassControlFrames: 9187 if (IS_E_PORT(unit, port)) { 9188 rv = _bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE, 9189 PASS_CONTROL_FRAMESf, 9190 (value) ? 1 : 0); 9191 } 9192 9193 if (IS_XE_PORT(unit, port) || IS_CE_PORT(unit, port) || 9194 IS_CDE_PORT(unit, port) || IS_C_PORT(unit, port) || 9195 (IS_GE_PORT(unit, port) 9196 && soc_feature(unit, soc_feature_unified_port))) { 9197 /* Enable Control Frames in BigMAC */ 9198 if(soc_feature(unit, soc_feature_pgw_mac_control_frame)) { 9199 uint32 rval32 = 0; 9200 9201 PORT_LOCK(unit); 9202 rv = READ_PGW_MAC_RSV_MASKr(unit, port, &rval32); 9203 if (BCM_SUCCESS(rv)) { 9204 /* PGW_MAC_RSV_MASK: Bit 11 Control Frame recieved 9205 * Enable Control Frame : Set 0. Packet go through 9206 * Disable Control Frame : Set 1. Packet is purged. 9207 */ 9208 if(value) { 9209 rval32 &= ~(1 << 11); 9210 } else { 9211 rval32 |= (1 << 11); 9212 } 9213 rv = WRITE_PGW_MAC_RSV_MASKr(unit, port, rval32); 9214 } 9215 PORT_UNLOCK(unit); 9216 } else { 9217 portmod_rx_control_t rx_control; 9218 9219 PORTMOD_IF_ERROR_RETURN 9220 (portmod_rx_control_t_init(unit, &rx_control)); 9221 9222 rx_control.flags = PORTMOD_MAC_PASS_CONTROL_FRAME; 9223 rx_control.pass_control_frames = value; 9224 PORT_LOCK(unit); 9225 rv = portmod_port_rx_control_set(unit, pport, &rx_control); 9226 PORT_UNLOCK(unit); 9227 } 9228 } 9229 break; 9230 9231 case bcmPortControlFrameSpacingStretch: 9232 PORT_LOCK(unit); 9233 rv = portmod_port_frame_spacing_stretch_set(unit, pport, value); 9234 PORT_UNLOCK(unit); 9235 break; 9236 9237 case bcmPortControlPFCEthertype: 9238 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9239 portmod_pfc_config_t pfc_config; 9240 9241 if (value < 0 || value > 0xffff) { 9242 return BCM_E_PARAM; 9243 } 9244 9245 PORT_LOCK(unit); 9246 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9247 if (PORTMOD_SUCCESS(rv)) { 9248 pfc_config.type = value; 9249 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config); 9250 } 9251 PORT_UNLOCK(unit); 9252 } 9253 break; 9254 9255 case bcmPortControlPFCOpcode: 9256 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9257 portmod_pfc_config_t pfc_config; 9258 9259 if (value < 0 || value > 0xffff) { 9260 return BCM_E_PARAM; 9261 } 9262 9263 PORT_LOCK(unit); 9264 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9265 if (PORTMOD_SUCCESS(rv)) { 9266 pfc_config.opcode = value; 9267 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config); 9268 } 9269 PORT_UNLOCK(unit); 9270 } 9271 break; 9272 9273 case bcmPortControlPFCReceive: 9274 PORT_LOCK(unit); 9275 rv = _bcm_esw_portctrl_control_pfc_receive_set(unit, port, 9276 pport, value); 9277 PORT_UNLOCK(unit); 9278 break; 9279 9280 case bcmPortControlPFCTransmit: 9281 PORT_LOCK(unit); 9282 rv = _bcm_esw_portctrl_control_pfc_transmit_set(unit, port, 9283 pport, value); 9284 PORT_UNLOCK(unit); 9285 break; 9286 9287 case bcmPortControlPFCClasses: 9288 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9289 portmod_pfc_config_t pfc_config; 9290 9291 if (value < 0 || value > 0xffffff) { 9292 return BCM_E_PARAM; 9293 } 9294 9295 PORT_LOCK(unit); 9296 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9297 if (PORTMOD_SUCCESS(rv)) { 9298 pfc_config.classes = value; 9299 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config); 9300 } 9301 PORT_UNLOCK(unit); 9302 } 9303 break; 9304 9305 case bcmPortControlPFCPassFrames: 9306 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9307 if(soc_feature(unit, soc_feature_pgw_mac_pfc_frame)) { 9308 uint32 rval32 = 0; 9309 PORT_LOCK(unit); 9310 rv = READ_PGW_MAC_RSV_MASKr(unit, port, &rval32); 9311 if (BCM_SUCCESS(rv)) { 9312 /* PGW_MAC_RSV_MASK: Bit 18 PFC frame detected 9313 * Enable PFC Frame : Set 0. Go through 9314 * Disable PFC Frame : Set 1. Purged. 9315 */ 9316 if(value) { 9317 rval32 &= ~(1 << 18); 9318 } else { 9319 rval32 |= (1 << 18); 9320 } 9321 rv = WRITE_PGW_MAC_RSV_MASKr(unit, port, rval32); 9322 } 9323 PORT_UNLOCK(unit); 9324 } else { 9325 portmod_pfc_config_t pfc_config; 9326 9327 PORT_LOCK(unit); 9328 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9329 if (PORTMOD_SUCCESS(rv)) { 9330 pfc_config.rxpass = value; 9331 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config); 9332 } 9333 PORT_UNLOCK(unit); 9334 } 9335 } 9336 break; 9337 9338 case bcmPortControlPFCDestMacOui: 9339 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9340 portmod_pfc_config_t pfc_config; 9341 9342 if (value < 0 || value > 0xffffff) { 9343 return BCM_E_PARAM; 9344 } 9345 9346 PORT_LOCK(unit); 9347 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9348 if (PORTMOD_SUCCESS(rv)) { 9349 pfc_config.da_oui = value; 9350 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config); 9351 } 9352 PORT_UNLOCK(unit); 9353 } 9354 break; 9355 9356 case bcmPortControlPFCDestMacNonOui: 9357 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9358 portmod_pfc_config_t pfc_config; 9359 9360 if (value < 0 || value > 0xffffff) { 9361 return BCM_E_PARAM; 9362 } 9363 9364 PORT_LOCK(unit); 9365 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9366 if (PORTMOD_SUCCESS(rv)) { 9367 pfc_config.da_nonoui = value; 9368 rv = portmod_port_pfc_config_set(unit, pport, &pfc_config); 9369 } 9370 PORT_UNLOCK(unit); 9371 } 9372 break; 9373 9374 case bcmPortControlPFCRefreshTime: 9375 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9376 portmod_pfc_control_t pfc_control; 9377 9378 if (value < 0 || value > 0xffff) { 9379 return BCM_E_PARAM; 9380 } 9381 9382 PORT_LOCK(unit); 9383 rv = portmod_port_pfc_control_get(unit, pport, &pfc_control); 9384 if (PORTMOD_SUCCESS(rv)) { 9385 pfc_control.refresh_timer = value; 9386 rv = portmod_port_pfc_control_set(unit, pport, &pfc_control); 9387 } 9388 PORT_UNLOCK(unit); 9389 } 9390 break; 9391 9392 case bcmPortControlPFCXOffTime: 9393 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9394 portmod_pfc_control_t pfc_control; 9395 9396 if (value < 0 || value > 0xffff) { 9397 return BCM_E_PARAM; 9398 } 9399 9400 PORT_LOCK(unit); 9401 rv = portmod_port_pfc_control_get(unit, pport, &pfc_control); 9402 if (PORTMOD_SUCCESS(rv)) { 9403 pfc_control.xoff_timer = value; 9404 rv = portmod_port_pfc_control_set(unit, pport, &pfc_control); 9405 } 9406 PORT_UNLOCK(unit); 9407 } 9408 break; 9409 9410 case bcmPortControlPrbsPolynomial: 9411 PORT_LOCK(unit); 9412 rv = bcmi_esw_portctrl_phy_control_set(unit, port, 9413 BCM_PORT_PHY_CONTROL_PRBS_POLYNOMIAL, value); 9414 PORT_UNLOCK(unit); 9415 break; 9416 9417 case bcmPortControlPrbsTxEnable: 9418 PORT_LOCK(unit); 9419 rv = bcmi_esw_portctrl_phy_control_set(unit, port, 9420 BCM_PORT_PHY_CONTROL_PRBS_TX_ENABLE, value); 9421 PORT_UNLOCK(unit); 9422 break; 9423 9424 case bcmPortControlPrbsRxEnable: 9425 PORT_LOCK(unit); 9426 rv = bcmi_esw_portctrl_phy_control_set(unit, port, 9427 BCM_ESW_PORTCTRL_PHYCTRL_PRBS_RX_ENABLE, value); 9428 PORT_UNLOCK(unit); 9429 break; 9430 9431 case bcmPortControlPrbsTxInvertData: 9432 PORT_LOCK(unit); 9433 rv = bcmi_esw_portctrl_phy_control_set(unit, port, 9434 BCM_PORT_PHY_CONTROL_PRBS_TX_INVERT_DATA, value); 9435 PORT_UNLOCK(unit); 9436 break; 9437 9438 case bcmPortControlLinkFaultLocalEnable: 9439 { 9440 portmod_local_fault_control_t control; 9441 9442 PORT_LOCK(unit); 9443 rv = portmod_port_local_fault_control_get(unit, pport, &control); 9444 if (PORTMOD_SUCCESS(rv)) { 9445 control.enable = value; 9446 rv = portmod_port_local_fault_control_set(unit, 9447 pport, &control); 9448 } 9449 PORT_UNLOCK(unit); 9450 } 9451 break; 9452 9453 case bcmPortControlLinkFaultRemoteEnable: 9454 { 9455 portmod_remote_fault_control_t control; 9456 9457 PORT_LOCK(unit); 9458 rv = portmod_port_remote_fault_control_get(unit, pport, &control); 9459 if (PORTMOD_SUCCESS(rv)) { 9460 control.enable = value; 9461 rv = portmod_port_remote_fault_control_set(unit, 9462 pport, &control); 9463 } 9464 PORT_UNLOCK(unit); 9465 } 9466 break; 9467 9468 case bcmPortControlSerdesDriverTune: 9469 PORT_LOCK(unit); 9470 9471 /* rv = soc_phyctrl_control_set(unit, port, 9472 SOC_PHY_CONTROL_SERDES_DRIVER_TUNE, value); 9473 */ 9474 PORT_UNLOCK(unit); 9475 break; 9476 9477 case bcmPortControlLinkdownTransmit: 9478 PORT_LOCK(unit); 9479 rv = bcmi_esw_portctrl_phy_control_set(unit, port, 9480 BCM_PORT_PHY_CONTROL_LINKDOWN_TRANSMIT, value); 9481 PORT_UNLOCK(unit); 9482 /* Most of PHYs have nothing to configure and simply return UNAVAIL*/ 9483 if ((rv == SOC_E_NONE) || (rv == SOC_E_UNAVAIL)) { 9484 portmod_local_fault_control_t control; 9485 9486 rv = _bcm_esw_link_down_tx_set(unit, port, value); 9487 9488 PORT_LOCK(unit); 9489 rv = portmod_port_local_fault_control_get(unit, pport, &control); 9490 if (PORTMOD_SUCCESS(rv)) { 9491 control.enable = value ? 0 : 1; 9492 rv = portmod_port_local_fault_control_set(unit, 9493 pport, &control); 9494 } 9495 PORT_UNLOCK(unit); 9496 } 9497 break; 9498 9499 case bcmPortControlSerdesTuneMarginMode: 9500 PORT_LOCK(unit); 9501 9502 /* rv = soc_phyctrl_control_set(unit, port, 9503 SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_MODE, value); 9504 */ 9505 PORT_UNLOCK(unit); 9506 break; 9507 9508 case bcmPortControlSerdesTuneMarginValue: 9509 PORT_LOCK(unit); 9510 9511 /* rv = soc_phyctrl_control_set(unit, port, 9512 SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_VALUE, value); 9513 */ 9514 PORT_UNLOCK(unit); 9515 break; 9516 9517 case bcmPortControlEEEEnable: 9518 PORT_LOCK(unit); 9519 rv = _bcm_esw_portctrl_control_eee_enable_set(unit, port, 9520 pport, value); 9521 PORT_UNLOCK(unit); 9522 9523 break; 9524 9525 case bcmPortControlEEEStatisticsClear: 9526 PORT_LOCK(unit); 9527 9528 rv = _bcm_esw_portctrl_eee_statistics_clear(unit, port, 9529 pport, value); 9530 PORT_UNLOCK (unit); 9531 break; 9532 9533 9534 /********************** EEE Mode Overview ************************ 9535 * |DET| | WT | 9536 * Signalling |idles| |------------------------------| | idles | 9537 * from Tx MAC | or | | Low Power Idle (LPI) |idles| or | 9538 * to local PHY |data | |------------------------------| | data | 9539 * * * 9540 * * * 9541 * * -------LPI state------------* 9542 * Local PHY | | | | | | | | | | 9543 * signaling | Active|Ts| Tq |Tr| Tq |Tr| Tq |Tw |Active | 9544 * on MDI | | | | | | | | | | 9545 * *------------------------------* 9546 * * * 9547 * * * 9548 * Signaling | idles |-------------------------------|id| PHY is | 9549 * from LP PHY | or | Low Power Idle (LPI) |le| ready | 9550 * to Rx MAC | data |-------------------------------|s | for data | 9551 * 9552 * where DET = Delay Entry Timer WT = Tx MAC Wake Timer 9553 */ 9554 case bcmPortControlEEETransmitIdleTime: 9555 /* DET = Time (in microsecs) for which condition to move to LPI state 9556 * is satisfied, at the end of which MAC TX transitions to LPI state */ 9557 if (soc_feature (unit, soc_feature_eee)) { 9558 portmod_eee_t eee; 9559 9560 PORT_LOCK(unit); 9561 rv = portmod_port_eee_get(unit, pport, &eee); 9562 if (PORTMOD_SUCCESS(rv)) { 9563 eee.tx_idle_time = value; 9564 rv = portmod_port_eee_set(unit, pport, &eee); 9565 } 9566 PORT_UNLOCK(unit); 9567 } 9568 break; 9569 9570 case bcmPortControlEEETransmitRefreshTime: 9571 PORT_LOCK(unit); 9572 9573 /* rv = soc_phyctrl_control_set(unit, port, 9574 BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME, value); 9575 */ 9576 PORT_UNLOCK (unit); 9577 break; 9578 9579 case bcmPortControlEEETransmitSleepTime: 9580 PORT_LOCK (unit); 9581 9582 /* rv = soc_phyctrl_control_set(unit, port, 9583 BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME, value); 9584 */ 9585 PORT_UNLOCK (unit); 9586 break; 9587 9588 case bcmPortControlEEETransmitQuietTime: 9589 PORT_LOCK(unit); 9590 9591 /* rv = soc_phyctrl_control_set(unit, port, 9592 BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME, value); 9593 */ 9594 PORT_UNLOCK (unit); 9595 break; 9596 9597 case bcmPortControlEEETransmitWakeTime: 9598 /* Time(in microsecs) to wait before transmitter can leave LPI State*/ 9599 if (soc_feature (unit, soc_feature_eee)) { 9600 portmod_eee_t eee; 9601 9602 PORT_LOCK(unit); 9603 rv = portmod_port_eee_get(unit, pport, &eee); 9604 if (PORTMOD_SUCCESS(rv)) { 9605 eee.tx_wake_time = value; 9606 rv = portmod_port_eee_set(unit, pport, &eee); 9607 } 9608 PORT_UNLOCK(unit); 9609 } 9610 break; 9611 9612 case bcmPortControlEEEReceiveSleepTime: 9613 PORT_LOCK (unit); 9614 9615 /* rv = soc_phyctrl_control_set(unit, port, 9616 BCM_PORT_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME, value); 9617 */ 9618 PORT_UNLOCK (unit); 9619 break; 9620 9621 case bcmPortControlEEEReceiveQuietTime: 9622 PORT_LOCK(unit); 9623 9624 /* rv = soc_phyctrl_control_set(unit, port, 9625 BCM_PORT_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME, value); 9626 */ 9627 PORT_UNLOCK(unit); 9628 break; 9629 9630 case bcmPortControlEEEReceiveWakeTime: 9631 PORT_LOCK(unit); 9632 9633 9634 /* rv = soc_phyctrl_control_set (unit, port, 9635 BCM_PORT_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME, value); 9636 */ 9637 PORT_UNLOCK(unit); 9638 break; 9639 9640 case bcmPortControlRxEnable: 9641 rv = bcmi_esw_portctrl_mac_rx_control(unit, port, 0, &value); 9642 break; 9643 case bcmPortControlVrf: 9644 rv = _bcm_esw_port_vrf_set(unit, port, value); 9645 break; 9646 case bcmPortControlTimestampEnable: 9647 PORT_LOCK(unit); 9648 rv = portmod_port_mac_timestamp_enable_set(unit, pport, value); 9649 PORT_UNLOCK(unit); 9650 break; 9651 case bcmPortControlTXPISDMOverride: 9652 { 9653 portmod_txpi_override_t override; 9654 9655 if (value < -100 || value > 100) { 9656 return BCM_E_PARAM; 9657 } 9658 override.enable = value ? 1 : 0; 9659 override.value = value; 9660 9661 PORT_LOCK(unit); 9662 rv = portmod_port_txpi_override_set(unit, pport, &override); 9663 PORT_UNLOCK(unit); 9664 } 9665 break; 9666 case bcmPortControlOOBFCTxReportIngEnable: 9667 if (soc_feature(unit, soc_feature_oob_fc)) { 9668 #ifdef BCM_TOMAHAWK3_SUPPORT 9669 if (SOC_IS_TOMAHAWK3(unit)) { 9670 rv = bcm_th3_oob_fc_tx_port_control_set(unit, port, value, 0); 9671 } else 9672 #endif 9673 { 9674 rv = BCM_E_UNAVAIL; 9675 } 9676 } else { 9677 rv = BCM_E_UNAVAIL; 9678 } 9679 break; 9680 case bcmPortControlOOBFCTxReportEgrEnable: 9681 if (soc_feature(unit, soc_feature_oob_fc)) { 9682 #ifdef BCM_TOMAHAWK3_SUPPORT 9683 if (SOC_IS_TOMAHAWK3(unit)) { 9684 rv = bcm_th3_oob_fc_tx_port_control_set(unit, port, value, 1); 9685 } else 9686 #endif 9687 { 9688 rv = BCM_E_UNAVAIL; 9689 } 9690 } else { 9691 rv = BCM_E_UNAVAIL; 9692 } 9693 break; 9694 default: 9695 /* Control is not supported */ 9696 break; 9697 } 9698 return rv; 9699 9700 #else /* PORTMOD_SUPPORT */ 9701 return BCM_E_UNAVAIL; 9702 #endif /* PORTMOD_SUPPORT */ 9703 } 9704 9705 9706 /* 9707 * Function: 9708 * bcmi_esw_portctrl_control_get 9709 * Purpose: 9710 * Get the status of the specified port control feature. 9711 * Parameters: 9712 * unit - (IN) Unit number. 9713 * port - (IN) Port number. 9714 * type - (IN) Port control. 9715 * value - (OUT) Value of port control feature. 9716 * Returns: 9717 * BCM_E_XXX 9718 * Notes: 9719 * Any new control needs to be included in 9720 * bcmi_esw_portctrl_control_validate(). 9721 */ 9722 int 9723 bcmi_esw_portctrl_control_get(int unit, bcm_gport_t port, 9724 bcm_port_control_t type, int *value) 9725 { 9726 #ifdef PORTMOD_SUPPORT 9727 int rv = BCM_E_UNAVAIL; 9728 portctrl_pport_t pport; 9729 9730 PORTCTRL_INIT_CHECK(unit); 9731 9732 BCM_IF_ERROR_RETURN 9733 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 9734 9735 switch (type) { 9736 case bcmPortControlPassControlFrames: 9737 if (IS_XE_PORT(unit, port) || IS_CE_PORT(unit, port) || 9738 IS_CDE_PORT(unit, port) || IS_C_PORT(unit, port) || 9739 (IS_GE_PORT(unit, port) 9740 && soc_feature(unit, soc_feature_unified_port))) { 9741 if(soc_feature(unit, soc_feature_pgw_mac_control_frame)) { 9742 uint32 rval32 = 0; 9743 rv = READ_PGW_MAC_RSV_MASKr(unit, port, &rval32); 9744 if (BCM_SUCCESS(rv)) { 9745 /* PGW_MAC_RSV_MASK: Bit 11 Control Frame recieved 9746 * the bit value needs to be reversed 9747 */ 9748 *value = ((rval32 & 0x800) >> 11) ? 0 : 1 ; 9749 } 9750 } else { 9751 portmod_rx_control_t rx_control; 9752 PORT_LOCK(unit); 9753 rv = portmod_port_rx_control_get(unit, pport, &rx_control); 9754 PORT_UNLOCK(unit); 9755 if (PORTMOD_SUCCESS(rv)) { 9756 *value = rx_control.pass_control_frames; 9757 } 9758 } 9759 } 9760 break; 9761 9762 case bcmPortControlFrameSpacingStretch: 9763 PORT_LOCK(unit); 9764 rv = portmod_port_frame_spacing_stretch_get(unit, pport, value); 9765 PORT_UNLOCK(unit); 9766 break; 9767 9768 case bcmPortControlPFCEthertype: 9769 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9770 portmod_pfc_config_t pfc_config; 9771 9772 PORT_LOCK(unit); 9773 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9774 PORT_UNLOCK(unit); 9775 if (PORTMOD_SUCCESS(rv)) { 9776 *value = pfc_config.type; 9777 } 9778 } 9779 break; 9780 9781 case bcmPortControlPFCOpcode: 9782 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9783 portmod_pfc_config_t pfc_config; 9784 9785 PORT_LOCK(unit); 9786 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9787 PORT_UNLOCK(unit); 9788 if (PORTMOD_SUCCESS(rv)) { 9789 *value = pfc_config.opcode; 9790 } 9791 } 9792 break; 9793 9794 case bcmPortControlPFCReceive: 9795 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9796 portmod_pfc_control_t pfc_control; 9797 9798 PORT_LOCK(unit); 9799 rv = portmod_port_pfc_control_get(unit, pport, &pfc_control); 9800 PORT_UNLOCK(unit); 9801 if (PORTMOD_SUCCESS(rv)) { 9802 *value = pfc_control.rx_enable; 9803 } 9804 } 9805 break; 9806 9807 case bcmPortControlPFCTransmit: 9808 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9809 portmod_pfc_control_t pfc_control; 9810 9811 PORT_LOCK(unit); 9812 rv = portmod_port_pfc_control_get(unit, pport, &pfc_control); 9813 PORT_UNLOCK(unit); 9814 if (PORTMOD_SUCCESS(rv)) { 9815 *value = pfc_control.tx_enable; 9816 } 9817 } 9818 break; 9819 9820 case bcmPortControlPFCClasses: 9821 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9822 portmod_pfc_config_t pfc_config; 9823 9824 PORT_LOCK(unit); 9825 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9826 PORT_UNLOCK(unit); 9827 if (PORTMOD_SUCCESS(rv)) { 9828 *value = pfc_config.classes; 9829 } 9830 } 9831 break; 9832 9833 case bcmPortControlPFCPassFrames: 9834 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9835 if(soc_feature(unit, soc_feature_pgw_mac_pfc_frame)) { 9836 uint32 rval32 = 0; 9837 rv = READ_PGW_MAC_RSV_MASKr(unit, port, &rval32); 9838 if (BCM_SUCCESS(rv)) { 9839 /* PGW_MAC_RSV_MASK: Bit 18 PFC frame detected 9840 * the bit value needs to be reversed 9841 */ 9842 *value = ((rval32 & 0x40000) >> 18) ? 0 : 1 ; 9843 } 9844 } else { 9845 portmod_pfc_config_t pfc_config; 9846 9847 PORT_LOCK(unit); 9848 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9849 PORT_UNLOCK(unit); 9850 if (PORTMOD_SUCCESS(rv)) { 9851 *value = pfc_config.rxpass; 9852 } 9853 } 9854 } 9855 break; 9856 9857 case bcmPortControlPFCDestMacOui: 9858 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9859 portmod_pfc_config_t pfc_config; 9860 9861 PORT_LOCK(unit); 9862 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9863 PORT_UNLOCK(unit); 9864 if (PORTMOD_SUCCESS(rv)) { 9865 *value = pfc_config.da_oui; 9866 } 9867 } 9868 break; 9869 9870 case bcmPortControlPFCDestMacNonOui: 9871 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9872 portmod_pfc_config_t pfc_config; 9873 9874 PORT_LOCK(unit); 9875 rv = portmod_port_pfc_config_get(unit, pport, &pfc_config); 9876 PORT_UNLOCK(unit); 9877 if (PORTMOD_SUCCESS(rv)) { 9878 *value = pfc_config.da_nonoui; 9879 } 9880 } 9881 break; 9882 9883 case bcmPortControlPFCRefreshTime: 9884 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9885 portmod_pfc_control_t pfc_control; 9886 9887 PORT_LOCK(unit); 9888 rv = portmod_port_pfc_control_get(unit, pport, &pfc_control); 9889 PORT_UNLOCK(unit); 9890 if (PORTMOD_SUCCESS(rv)) { 9891 *value = pfc_control.refresh_timer; 9892 } 9893 } 9894 break; 9895 9896 case bcmPortControlPFCXOffTime: 9897 if (soc_feature(unit, soc_feature_priority_flow_control)) { 9898 portmod_pfc_control_t pfc_control; 9899 9900 PORT_LOCK(unit); 9901 rv = portmod_port_pfc_control_get(unit, pport, &pfc_control); 9902 PORT_UNLOCK(unit); 9903 if (PORTMOD_SUCCESS(rv)) { 9904 *value = pfc_control.xoff_timer; 9905 } 9906 } 9907 break; 9908 9909 case bcmPortControlPrbsPolynomial: 9910 rv = bcmi_esw_portctrl_phy_control_get(unit, port, 9911 BCM_PORT_PHY_CONTROL_PRBS_POLYNOMIAL, (uint32 *)value); 9912 break; 9913 case bcmPortControlPrbsTxEnable: 9914 rv = bcmi_esw_portctrl_phy_control_get(unit, port, 9915 BCM_PORT_PHY_CONTROL_PRBS_TX_ENABLE, (uint32 *)value); 9916 break; 9917 9918 case bcmPortControlPrbsRxEnable: 9919 rv = bcmi_esw_portctrl_phy_control_get(unit, port, 9920 BCM_ESW_PORTCTRL_PHYCTRL_PRBS_RX_ENABLE, (uint32 *)value); 9921 break; 9922 9923 case bcmPortControlPrbsTxInvertData: 9924 rv = bcmi_esw_portctrl_phy_control_get(unit, port, 9925 BCM_PORT_PHY_CONTROL_PRBS_TX_INVERT_DATA, (uint32 *)value); 9926 break; 9927 9928 case bcmPortControlPrbsRxStatus: 9929 rv = bcmi_esw_portctrl_phy_control_get(unit, port, 9930 BCM_PORT_PHY_CONTROL_PRBS_RX_STATUS, (uint32 *)value); 9931 break; 9932 9933 case bcmPortControlLinkFaultLocalEnable: 9934 { 9935 portmod_local_fault_control_t control; 9936 9937 PORT_LOCK(unit); 9938 rv = portmod_port_local_fault_control_get(unit, pport, &control); 9939 PORT_UNLOCK(unit); 9940 if (PORTMOD_SUCCESS(rv)) { 9941 *value = control.enable; 9942 } 9943 } 9944 break; 9945 case bcmPortControlLinkFaultRemoteEnable: 9946 { 9947 portmod_remote_fault_control_t control; 9948 9949 PORT_LOCK(unit); 9950 rv = portmod_port_remote_fault_control_get(unit, pport, &control); 9951 PORT_UNLOCK(unit); 9952 if (PORTMOD_SUCCESS(rv)) { 9953 *value = control.enable; 9954 } 9955 } 9956 break; 9957 9958 case bcmPortControlLinkFaultLocal: 9959 PORT_LOCK(unit); 9960 rv = portmod_port_local_fault_status_get(unit, pport, value); 9961 PORT_UNLOCK(unit); 9962 break; 9963 9964 case bcmPortControlLinkFaultRemote: 9965 PORT_LOCK(unit); 9966 rv = portmod_port_remote_fault_status_get(unit, pport, value); 9967 PORT_UNLOCK(unit); 9968 break; 9969 9970 case bcmPortControlTimestampTransmit: 9971 if (soc_feature(unit, soc_feature_timesync_support)) { 9972 portmod_fifo_status_t info; 9973 9974 PORT_LOCK(unit); 9975 rv = portmod_port_diag_fifo_status_get(unit, pport, &info); 9976 PORT_UNLOCK(unit); 9977 if (PORTMOD_SUCCESS(rv)) { 9978 *value = info.timestamps_in_fifo; 9979 } 9980 } 9981 9982 break; 9983 9984 case bcmPortControlSerdesDriverEqualizationTuneStatusFarEnd: 9985 PORT_LOCK(unit); 9986 9987 /* rv = soc_phyctrl_control_get(unit, port, 9988 SOC_PHY_CONTROL_SERDES_DRIVER_EQUALIZATION_TUNE_STATUS_FAR_END, 9989 (uint32 *)value); 9990 */ 9991 PORT_UNLOCK(unit); 9992 break; 9993 9994 case bcmPortControlLinkdownTransmit: 9995 PORT_LOCK(unit); 9996 rv = bcmi_esw_portctrl_phy_control_get(unit, port, 9997 BCM_PORT_PHY_CONTROL_LINKDOWN_TRANSMIT, (uint32 *)value); 9998 PORT_UNLOCK(unit); 9999 /* Most of PHYs have nothing to configure and simply return UNAVAIL*/ 10000 if ((rv == SOC_E_NONE) || (rv == SOC_E_UNAVAIL)) { 10001 rv = _bcm_esw_link_down_tx_get(unit, port, value); 10002 } 10003 break; 10004 10005 case bcmPortControlSerdesTuneMarginMode: 10006 PORT_LOCK(unit); 10007 10008 /* rv = soc_phyctrl_control_get(unit, port, 10009 SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_MODE, 10010 (uint32 *)value); 10011 */ 10012 PORT_UNLOCK(unit); 10013 break; 10014 10015 case bcmPortControlSerdesTuneMarginValue: 10016 PORT_LOCK(unit); 10017 10018 /* rv = soc_phyctrl_control_get(unit, port, 10019 SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_VALUE, 10020 (uint32 *)value); 10021 */ 10022 PORT_UNLOCK(unit); 10023 break; 10024 10025 case bcmPortControlSerdesTuneMarginMax: 10026 PORT_LOCK(unit); 10027 10028 /* rv = soc_phyctrl_control_get(unit, port, 10029 SOC_PHY_CONTROL_SERDES_TUNE_MARGIN_MAX, 10030 (uint32 *)value); 10031 */ 10032 PORT_UNLOCK(unit); 10033 break; 10034 10035 case bcmPortControlEEEEnable: 10036 PORT_LOCK(unit); 10037 if (soc_feature(unit, soc_feature_eee)) { 10038 uint32 eeenative, eeeauto; 10039 int rv1 = BCM_E_UNAVAIL, rv2 = BCM_E_UNAVAIL; 10040 10041 rv = BCM_E_NONE; 10042 rv1 = (bcmi_esw_portctrl_phy_control_get(unit, port, 10043 BCM_PORT_PHY_CONTROL_EEE, 10044 &eeenative)); 10045 if (rv1 != BCM_E_UNAVAIL) { 10046 *value = eeenative; 10047 } 10048 rv2 = (bcmi_esw_portctrl_phy_control_get(unit, port, 10049 BCM_PORT_PHY_CONTROL_EEE_AUTO, 10050 &eeeauto)); 10051 if (rv2 != BCM_E_UNAVAIL) { 10052 *value = eeeauto; 10053 } 10054 10055 /* If neither Native EEE nor AutoGrEEEn mode is supported */ 10056 if ((rv1 == BCM_E_UNAVAIL) && (rv2 == BCM_E_UNAVAIL)) { 10057 rv = BCM_E_UNAVAIL; 10058 } 10059 10060 /* If both Native EEE and AutoGrEEEn mode are supported */ 10061 if ((rv1 != SOC_E_UNAVAIL) && (rv2 != SOC_E_UNAVAIL)) { 10062 *value = eeenative ? (eeeauto ? 0 : 1) : (eeeauto ? 1 : 0); 10063 } 10064 } else { 10065 rv = BCM_E_UNAVAIL; 10066 } 10067 PORT_UNLOCK (unit); 10068 break; 10069 10070 /********************** EEE Mode Overview ************************ 10071 * |DET| | WT | 10072 * Signalling |idles| |------------------------------| | idles | 10073 * from Tx MAC | or | | Low Power Idle (LPI) |idles| or | 10074 * to local PHY |data | |------------------------------| | data | 10075 * * * 10076 * * * 10077 * * -------LPI state------------* 10078 * Local PHY | | | | | | | | | | 10079 * signaling | Active|Ts| Tq |Tr| Tq |Tr| Tq |Tw |Active | 10080 * on MDI | | | | | | | | | | 10081 * *------------------------------* 10082 * * * 10083 * * * 10084 * Signaling | idles |-------------------------------|id| PHY is | 10085 * from LP PHY | or | Low Power Idle (LPI) |le| ready | 10086 * to Rx MAC | data |-------------------------------|s | for data | 10087 * 10088 * where DET = Delay Entry Timer WT = MAC Wake Timer 10089 */ 10090 case bcmPortControlEEETransmitIdleTime: 10091 /* DET = Time (in microsecs) for which condition to move to LPI state 10092 * is satisfied, at the end of which MAC TX transitions to LPI state */ 10093 if (soc_feature (unit, soc_feature_eee)) { 10094 portmod_eee_t eee; 10095 PORT_LOCK(unit); 10096 rv = portmod_port_eee_get(unit, pport, &eee); 10097 PORT_UNLOCK(unit); 10098 if (PORTMOD_SUCCESS(rv)) { 10099 *value = eee.tx_idle_time; 10100 } 10101 } 10102 10103 break; 10104 10105 case bcmPortControlEEETransmitEventCount: 10106 /* Number of time MAC TX enters LPI state for 10107 * a given measurement interval*/ 10108 if (soc_feature(unit, soc_feature_eee)) { 10109 uint64 rval64; 10110 10111 rv = READ_TX_EEE_LPI_EVENT_COUNTERr(unit, port, &rval64); 10112 if (SOC_SUCCESS(rv)) { 10113 *value = COMPILER_64_LO(rval64); 10114 } 10115 } 10116 break; 10117 10118 case bcmPortControlEEETransmitDuration: 10119 /* Time in (microsecs) for which MAC TX enters LPI state 10120 * during a measurement interval*/ 10121 if (soc_feature(unit, soc_feature_eee)) { 10122 uint64 rval64; 10123 10124 rv = READ_TX_EEE_LPI_DURATION_COUNTERr(unit, port, &rval64); 10125 if (SOC_SUCCESS(rv)) { 10126 *value = COMPILER_64_LO(rval64); 10127 } 10128 } 10129 10130 break; 10131 10132 case bcmPortControlEEEReceiveEventCount: 10133 /* Number of time MAC RX enters LPI state for 10134 * a given measurement interval */ 10135 if (soc_feature(unit, soc_feature_eee)) { 10136 uint64 rval64; 10137 10138 rv = READ_RX_EEE_LPI_EVENT_COUNTERr(unit, port, &rval64); 10139 if (SOC_SUCCESS(rv)) { 10140 *value = COMPILER_64_LO(rval64); 10141 } 10142 } 10143 break; 10144 10145 case bcmPortControlEEEReceiveDuration: 10146 /* Time in (microsecs) for which MAC RX enters LPI state 10147 * during a measurement interval*/ 10148 if (soc_feature(unit, soc_feature_eee)) { 10149 uint64 rval64; 10150 10151 rv = READ_RX_EEE_LPI_DURATION_COUNTERr(unit, port, &rval64); 10152 if (SOC_SUCCESS(rv)) { 10153 *value = COMPILER_64_LO(rval64); 10154 } 10155 } 10156 break; 10157 10158 case bcmPortControlEEETransmitRefreshTime: 10159 PORT_LOCK(unit); 10160 10161 /* rv = soc_phyctrl_control_get(unit, port, 10162 BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME, 10163 (uint32 *)value); 10164 */ 10165 PORT_UNLOCK (unit); 10166 break; 10167 10168 case bcmPortControlEEETransmitSleepTime: 10169 PORT_LOCK(unit); 10170 10171 /* rv = soc_phyctrl_control_get(unit, port, 10172 BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME, (uint32 *)value); 10173 */ 10174 PORT_UNLOCK (unit); 10175 break; 10176 10177 case bcmPortControlEEETransmitQuietTime: 10178 PORT_LOCK(unit); 10179 10180 /* rv = soc_phyctrl_control_get(unit, port, 10181 BCM_PORT_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME, (uint32 *)value); 10182 */ 10183 PORT_UNLOCK (unit); 10184 break; 10185 10186 case bcmPortControlEEETransmitWakeTime: 10187 /* Time(in microsecs) to wait before transmitter can leave LPI State*/ 10188 if (soc_feature(unit, soc_feature_eee)) { 10189 portmod_eee_t eee; 10190 10191 PORT_LOCK(unit); 10192 rv = portmod_port_eee_get(unit, pport, &eee); 10193 PORT_UNLOCK(unit); 10194 if (PORTMOD_SUCCESS(rv)) { 10195 *value = eee.tx_wake_time; 10196 } 10197 } 10198 break; 10199 10200 case bcmPortControlEEEReceiveSleepTime: 10201 PORT_LOCK(unit); 10202 10203 /* rv = soc_phyctrl_control_get(unit, port, 10204 BCM_PORT_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME, (uint32 *)value); 10205 */ 10206 PORT_UNLOCK(unit); 10207 break; 10208 10209 case bcmPortControlEEEReceiveQuietTime: 10210 PORT_LOCK(unit); 10211 10212 /* rv = soc_phyctrl_control_get(unit, port, 10213 BCM_PORT_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME, (uint32 *)value); 10214 */ 10215 PORT_UNLOCK(unit); 10216 break; 10217 10218 case bcmPortControlEEEReceiveWakeTime: 10219 PORT_LOCK(unit); 10220 10221 /* rv = soc_phyctrl_control_get(unit, port, 10222 BCM_PORT_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME, (uint32 *)value); 10223 */ 10224 PORT_UNLOCK(unit); 10225 break; 10226 10227 case bcmPortControlRxEnable: 10228 rv = bcmi_esw_portctrl_mac_rx_control(unit, port, 1, value); 10229 break; 10230 case bcmPortControlVrf: 10231 rv = _bcm_esw_port_vrf_get(unit, port, value); 10232 break; 10233 case bcmPortControlTimestampEnable: 10234 PORT_LOCK(unit); 10235 rv = portmod_port_mac_timestamp_enable_get(unit, pport, value); 10236 PORT_UNLOCK(unit); 10237 break; 10238 case bcmPortControlTXPISDMOverride: 10239 { 10240 portmod_txpi_override_t override; 10241 10242 PORT_LOCK(unit); 10243 rv = portmod_port_txpi_override_get(unit, pport, &override); 10244 *value = override.enable ? override.value : 0; 10245 PORT_UNLOCK(unit); 10246 } 10247 break; 10248 case bcmPortControlTXPISDMStatus: 10249 PORT_LOCK(unit); 10250 rv = portmod_port_txpi_sdm_data_get(unit, pport, value); 10251 PORT_UNLOCK(unit); 10252 break; 10253 case bcmPortControlOOBFCTxReportIngEnable: 10254 if (soc_feature(unit, soc_feature_oob_fc)) { 10255 #ifdef BCM_TOMAHAWK3_SUPPORT 10256 if (SOC_IS_TOMAHAWK3(unit)) { 10257 rv = bcm_th3_oob_fc_tx_port_control_get(unit, port, value, 0); 10258 } else 10259 #endif 10260 { 10261 rv = BCM_E_UNAVAIL; 10262 } 10263 } else { 10264 rv = BCM_E_UNAVAIL; 10265 } 10266 break; 10267 case bcmPortControlOOBFCTxReportEgrEnable: 10268 if (soc_feature(unit, soc_feature_oob_fc)) { 10269 #ifdef BCM_TOMAHAWK3_SUPPORT 10270 if (SOC_IS_TOMAHAWK3(unit)) { 10271 rv = bcm_th3_oob_fc_tx_port_control_get(unit, port, value, 1); 10272 } else 10273 #endif 10274 { 10275 rv = BCM_E_UNAVAIL; 10276 } 10277 } else { 10278 rv = BCM_E_UNAVAIL; 10279 } 10280 break; 10281 default: 10282 /* Control is not supported */ 10283 break; 10284 } 10285 10286 return rv; 10287 10288 #else /* PORTMOD_SUPPORT */ 10289 return BCM_E_UNAVAIL; 10290 #endif /* PORTMOD_SUPPORT */ 10291 } 10292 10293 /* 10294 * Function: 10295 * bcmi_esw_portctrl_mode_get 10296 * Description: 10297 * Get the current mode used for MAC 10298 * Parameters: 10299 * unit(IN) - Device number 10300 * port(IN) - Port number 10301 * mode(OUT) - The configured MAC mode 10302 * Return Value: 10303 * BCM_E_XXX 10304 */ 10305 int 10306 bcmi_esw_portctrl_mode_get(int unit, bcm_gport_t port, int *mode) 10307 { 10308 #ifdef PORTMOD_SUPPORT 10309 int rv = BCM_E_NONE; 10310 portctrl_pport_t pport; 10311 portmod_port_mode_info_t info; 10312 10313 /* Make sure port module is initialized. */ 10314 PORTCTRL_INIT_CHECK(unit); 10315 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10316 10317 portmod_port_mode_info_t_init(unit, &info); 10318 10319 PORT_LOCK(unit); 10320 10321 rv = portmod_port_mode_get(unit, pport, &info); 10322 10323 PORT_UNLOCK(unit); 10324 10325 if (PORTMOD_SUCCESS(rv)) { 10326 *mode = info.cur_mode; 10327 } 10328 10329 return rv; 10330 10331 #else /* PORTMOD_SUPPORT */ 10332 return BCM_E_UNAVAIL; 10333 #endif /* PORTMOD_SUPPORT */ 10334 } 10335 10336 /* 10337 * Function: 10338 * bcmi_esw_portctrl_e2e_tx_enable_get 10339 * Purpose: 10340 * Get E2E Enable 10341 * Parameters: 10342 * unit - (IN) SOC unit number. 10343 * port - (IN) Port number. 10344 * enable - (OUT) Whether to enable or disable 10345 * Returns: 10346 * BCM_E_xxx 10347 */ 10348 int 10349 bcmi_esw_portctrl_e2e_tx_enable_get(int unit, bcm_gport_t port, int *enable) 10350 { 10351 #ifdef PORTMOD_SUPPORT 10352 int rv; 10353 portctrl_pport_t pport; 10354 10355 /* Make sure port module is initialized. */ 10356 PORTCTRL_INIT_CHECK(unit); 10357 10358 BCM_IF_ERROR_RETURN 10359 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10360 10361 PORT_LOCK(unit); 10362 rv = portmod_port_e2e_enable_get(unit, pport, enable); 10363 PORT_UNLOCK(unit); 10364 10365 return rv; 10366 10367 #else /* PORTMOD_SUPPORT */ 10368 return BCM_E_UNAVAIL; 10369 #endif /* PORTMOD_SUPPORT */ 10370 } 10371 10372 /* 10373 * Function: 10374 * bcmi_esw_portctrl_e2e_tx_enable_set 10375 * Purpose: 10376 * Set E2E Tx Enable 10377 * Parameters: 10378 * unit - (IN) SOC unit number. 10379 * port - (IN) Port number. 10380 * enable - (IN) Whether to enable or disable 10381 * Returns: 10382 * BCM_E_xxx 10383 */ 10384 int 10385 bcmi_esw_portctrl_e2e_tx_enable_set(int unit, bcm_gport_t port, int enable) 10386 { 10387 #ifdef PORTMOD_SUPPORT 10388 int rv; 10389 portctrl_pport_t pport; 10390 10391 /* Make sure port module is initialized. */ 10392 PORTCTRL_INIT_CHECK(unit); 10393 10394 BCM_IF_ERROR_RETURN 10395 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10396 10397 PORT_LOCK(unit); 10398 rv = portmod_port_e2e_enable_set(unit, pport, enable); 10399 PORT_UNLOCK(unit); 10400 10401 return rv; 10402 10403 #else /* PORTMOD_SUPPORT */ 10404 return BCM_E_UNAVAIL; 10405 #endif /* PORTMOD_SUPPORT */ 10406 } 10407 10408 /* 10409 * Function: 10410 * bcmi_esw_portctrl_e2ecc_hdr_get 10411 * Purpose: 10412 * Get E2ECC header data 10413 * Parameters: 10414 * unit - (IN) SOC unit number. 10415 * port - (IN) Port number. 10416 * e2ecc_hdr - (OUT) E2ECC header. 10417 * Returns: 10418 * BCM_E_xxx 10419 */ 10420 int 10421 bcmi_esw_portctrl_e2ecc_hdr_get(int unit, bcm_gport_t port, 10422 soc_higig_e2ecc_hdr_t *e2ecc_hdr) 10423 { 10424 #ifdef PORTMOD_SUPPORT 10425 int rv; 10426 portctrl_pport_t pport; 10427 portmod_port_higig_e2ecc_hdr_t portmod_hdr; 10428 10429 /* Make sure port module is initialized. */ 10430 PORTCTRL_INIT_CHECK(unit); 10431 10432 if (!e2ecc_hdr) { 10433 return BCM_E_PARAM; 10434 } 10435 10436 portmod_port_higig_e2ecc_hdr_t_init(unit, &portmod_hdr); 10437 10438 BCM_IF_ERROR_RETURN 10439 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10440 10441 PORT_LOCK(unit); 10442 rv = portmod_port_e2ecc_hdr_get(unit, pport, &portmod_hdr); 10443 PORT_UNLOCK(unit); 10444 10445 if (PORTMOD_SUCCESS(rv)) { 10446 sal_memcpy(e2ecc_hdr, &portmod_hdr, sizeof(soc_higig_e2ecc_hdr_t)); 10447 } 10448 10449 return rv; 10450 10451 #else /* PORTMOD_SUPPORT */ 10452 return BCM_E_UNAVAIL; 10453 #endif /* PORTMOD_SUPPORT */ 10454 } 10455 10456 /* 10457 * Function: 10458 * bcmi_esw_portctrl_e2ecc_hdr_set 10459 * Purpose: 10460 * Set E2ECC header data 10461 * Parameters: 10462 * unit - (IN) SOC unit number. 10463 * port - (IN) Port number. 10464 * e2ecc_hdr - (IN) E2ECC header. 10465 * Returns: 10466 * BCM_E_xxx 10467 */ 10468 int 10469 bcmi_esw_portctrl_e2ecc_hdr_set(int unit, bcm_gport_t port, 10470 soc_higig_e2ecc_hdr_t *e2ecc_hdr) 10471 { 10472 #ifdef PORTMOD_SUPPORT 10473 int rv; 10474 portctrl_pport_t pport; 10475 portmod_port_higig_e2ecc_hdr_t portmod_hdr; 10476 10477 /* Make sure port module is initialized. */ 10478 PORTCTRL_INIT_CHECK(unit); 10479 10480 if (!e2ecc_hdr) { 10481 return BCM_E_PARAM; 10482 } 10483 10484 portmod_port_higig_e2ecc_hdr_t_init(unit, &portmod_hdr); 10485 10486 BCM_IF_ERROR_RETURN 10487 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10488 10489 sal_memcpy(&portmod_hdr, e2ecc_hdr, sizeof(portmod_port_higig_e2ecc_hdr_t)); 10490 10491 PORT_LOCK(unit); 10492 rv = portmod_port_e2ecc_hdr_set(unit, pport, &portmod_hdr); 10493 PORT_UNLOCK(unit); 10494 10495 return rv; 10496 10497 #else /* PORTMOD_SUPPORT */ 10498 return BCM_E_UNAVAIL; 10499 #endif /* PORTMOD_SUPPORT */ 10500 } 10501 10502 /* 10503 * Function: 10504 * bcmi_esw_portctrl_vlan_tpid_set 10505 * Purpose: 10506 * Set TPID in vlan_tag. 10507 * Parameters: 10508 * unit - (IN) SOC unit number. 10509 * port - (IN) Port number. 10510 * tpid - (IN) tpid value. 10511 * Returns: 10512 * BCM_E_xxx 10513 */ 10514 int 10515 bcmi_esw_portctrl_vlan_tpid_set(int unit, bcm_gport_t port, int tpid) 10516 { 10517 #ifdef PORTMOD_SUPPORT 10518 int rv; 10519 portctrl_pport_t pport; 10520 portmod_vlan_tag_t vlan_tag; 10521 10522 /* Make sure port module is initialized. */ 10523 PORTCTRL_INIT_CHECK(unit); 10524 10525 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10526 10527 BCM_IF_ERROR_RETURN(portmod_port_vlan_tag_get(unit, port, &vlan_tag)); 10528 10529 vlan_tag.outer_vlan_tag = tpid; 10530 10531 PORT_LOCK(unit); 10532 rv = portmod_port_vlan_tag_set(unit, port, &vlan_tag); 10533 PORT_UNLOCK(unit); 10534 10535 return (rv); 10536 #else /* PORTMOD_SUPPORT */ 10537 return BCM_E_UNAVAIL; 10538 #endif /* PORTMOD_SUPPORT */ 10539 } 10540 10541 /* 10542 * Function: 10543 * bcmi_esw_portctrl_vlan_inner_tpid_set 10544 * Purpose: 10545 * Set TPID in vlan_tag. 10546 * Parameters: 10547 * unit - (IN) SOC unit number. 10548 * port - (IN) Port number. 10549 * tpid - (IN) tpid value. 10550 * Returns: 10551 * BCM_E_xxx 10552 */ 10553 int 10554 bcmi_esw_portctrl_vlan_inner_tpid_set(int unit, bcm_gport_t port, int tpid) 10555 { 10556 #ifdef PORTMOD_SUPPORT 10557 int rv; 10558 portctrl_pport_t pport; 10559 portmod_vlan_tag_t vlan_tag; 10560 10561 /* Make sure port module is initialized. */ 10562 PORTCTRL_INIT_CHECK(unit); 10563 10564 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10565 10566 BCM_IF_ERROR_RETURN(portmod_port_vlan_tag_get(unit, port, &vlan_tag)); 10567 10568 vlan_tag.inner_vlan_tag = tpid; 10569 10570 10571 PORT_LOCK(unit); 10572 rv = portmod_port_vlan_tag_set(unit, port, &vlan_tag); 10573 PORT_UNLOCK(unit); 10574 10575 return (rv); 10576 #else /* PORTMOD_SUPPORT */ 10577 return BCM_E_UNAVAIL; 10578 #endif /* PORTMOD_SUPPORT */ 10579 } 10580 10581 /* 10582 * Function: 10583 * bcmi_esw_portctrl_cntmaxsize_get 10584 * Purpose: 10585 * Get the max packet size that is used in statistic counter update 10586 * Parameters: 10587 * unit - (IN) SOC unit number. 10588 * port - (IN) Port number. 10589 * val - (OUT) max packet size. 10590 * Returns: 10591 * BCM_E_xxx 10592 */ 10593 int 10594 bcmi_esw_portctrl_cntmaxsize_get(int unit, bcm_gport_t port, int *val) 10595 { 10596 #ifdef PORTMOD_SUPPORT 10597 int rv; 10598 portctrl_pport_t pport; 10599 10600 /* Make sure port module is initialized. */ 10601 PORTCTRL_INIT_CHECK(unit); 10602 10603 BCM_IF_ERROR_RETURN 10604 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10605 10606 PORT_LOCK(unit); 10607 rv = portmod_port_cntmaxsize_get(unit, pport, val); 10608 PORT_UNLOCK(unit); 10609 10610 return rv; 10611 #else /* PORTMOD_SUPPORT */ 10612 return BCM_E_UNAVAIL; 10613 #endif /* PORTMOD_SUPPORT */ 10614 } 10615 /* 10616 * Function: 10617 * bcmi_esw_portctrl_cntmaxsize_set 10618 * Purpose: 10619 * Set the max packet size that is used in statistic counter update 10620 * Parameters: 10621 * unit - (IN) SOC unit number. 10622 * port - (IN) Port number. 10623 * val - (IN) max packet size. 10624 * Returns: 10625 * BCM_E_xxx 10626 */ 10627 int 10628 bcmi_esw_portctrl_cntmaxsize_set(int unit, bcm_gport_t port, int val) 10629 { 10630 #ifdef PORTMOD_SUPPORT 10631 int rv; 10632 portctrl_pport_t pport; 10633 10634 /* Make sure port module is initialized. */ 10635 PORTCTRL_INIT_CHECK(unit); 10636 10637 BCM_IF_ERROR_RETURN 10638 (PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10639 10640 PORT_LOCK(unit); 10641 rv = portmod_port_cntmaxsize_set(unit, pport, val); 10642 PORT_UNLOCK(unit); 10643 10644 return rv; 10645 10646 #else /* PORTMOD_SUPPORT */ 10647 return BCM_E_UNAVAIL; 10648 #endif /* PORTMOD_SUPPORT */ 10649 } 10650 10651 /* 10652 * Function: 10653 * bcmi_esw_portctrl_cable_diag 10654 * Description: 10655 * Run Cable Diagnostics on port 10656 * Parameters: 10657 * unit - Device number 10658 * port - Port number 10659 * status - (OUT) cable diag status structure 10660 * Return Value: 10661 * BCM_E_XXX 10662 * Notes: 10663 * Cable diagnostics are only supported by some phy types 10664 * (currently 5248 10/100 phy and 546x 10/100/1000 phys) 10665 */ 10666 int 10667 bcmi_esw_portctrl_cable_diag(int unit, bcm_port_t port, 10668 bcm_port_cable_diag_t *status) 10669 { 10670 #ifdef PORTMOD_SUPPORT 10671 int rv = BCM_E_NONE; 10672 portctrl_pport_t pport; 10673 int ext_phy_present; 10674 10675 /* Make sure port module is initialized. */ 10676 PORTCTRL_INIT_CHECK(unit); 10677 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10678 10679 /* PORTMOD currently only supports medium config get for ports with legacy ext PHY */ 10680 SOC_IF_ERROR_RETURN(portmod_port_is_legacy_ext_phy_present(unit, pport, &ext_phy_present)); 10681 if (!ext_phy_present) { 10682 return BCM_E_UNAVAIL; 10683 } 10684 10685 PORT_LOCK(unit); 10686 rv = soc_phyctrl_cable_diag(unit, port, status); 10687 PORT_UNLOCK(unit); 10688 10689 return rv; 10690 10691 #else /* PORTMOD_SUPPORT */ 10692 return BCM_E_UNAVAIL; 10693 #endif /* PORTMOD_SUPPORT */ 10694 } 10695 10696 /* 10697 * Function: 10698 * bcmi_esw_portctrl_preemption_status_tx_get 10699 * Purpose: 10700 * get preemption tx status 10701 * Parameters: 10702 * unit - (IN) unit number. 10703 * port - (IN) port number 10704 * value - (OUT) value 10705 * Returns: 10706 * BCM_E_XXX 10707 * Notes: 10708 */ 10709 int 10710 bcmi_esw_portctrl_preemption_status_tx_get(int unit, bcm_port_t port, 10711 uint32* value) 10712 { 10713 10714 #ifdef PORTMOD_SUPPORT 10715 return (portmod_preemption_tx_status_get(unit, port , 10716 value)); 10717 #endif 10718 return BCM_E_UNAVAIL; 10719 } 10720 /* 10721 * Function: 10722 * bcmi_esw_portctrl_preemption_status_verify_get 10723 * Purpose: 10724 * get preemption verify status 10725 * Parameters: 10726 * unit - (IN) unit number. 10727 * port - (IN) port number 10728 * value - (OUT) value 10729 * Returns: 10730 * BCM_E_XXX 10731 * Notes: 10732 */ 10733 int 10734 bcmi_esw_portctrl_preemption_status_verify_get(int unit, bcm_port_t port, 10735 uint32* value) 10736 { 10737 10738 #ifdef PORTMOD_SUPPORT 10739 return (portmod_preemption_verify_status_get(unit, port , portmodPreemptionVerifyStatus, 10740 value)); 10741 #endif 10742 return BCM_E_UNAVAIL; 10743 } 10744 /* 10745 * Function: 10746 * bcmi_esw_portctrl_preemption_mac_config_set 10747 * Purpose: 10748 * set preemption mac config 10749 * Parameters: 10750 * unit - (IN) unit number. 10751 * port - (IN) port number 10752 * type - (IN) Preemption control type 10753 * arg - (IN) value 10754 * Returns: 10755 * BCM_E_XXX 10756 * Notes: 10757 */ 10758 int 10759 bcmi_esw_portctrl_preemption_mac_config_set(int unit, bcm_port_t port, 10760 bcm_port_preempt_control_t type, 10761 uint32 arg) 10762 { 10763 #ifdef PORTMOD_SUPPORT 10764 portctrl_pport_t pport; 10765 10766 /* Make sure port module is initialized. */ 10767 PORTCTRL_INIT_CHECK(unit); 10768 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10769 10770 switch (type) { 10771 case bcmPortPreemptControlPreemptionSupport: 10772 return (portmod_preemption_control_set(unit, port , 10773 portmodPreemptionControlPreemptionSupport, arg)); 10774 case bcmPortPreemptControlEnableTx: 10775 return (portmod_preemption_control_set(unit, port , 10776 portmodPreemptionControlEnableTx, arg)); 10777 case bcmPortPreemptControlVerifyEnable: 10778 return (portmod_preemption_control_set(unit, port , 10779 portmodPreemptionControlVerifyEnable, arg)); 10780 case bcmPortPreemptControlVerifyTime: 10781 return (portmod_preemption_control_set(unit, port , 10782 portmodPreemptionControlVerifyTime, arg)); 10783 case bcmPortPreemptControlVerifyAttempts: 10784 return (portmod_preemption_control_set(unit, port , 10785 portmodPreemptionControlVerifyAttempts, arg)); 10786 case bcmPortPreemptControlNonFinalFragSizeRx: 10787 return (portmod_preemption_control_set(unit, port , 10788 portmodPreemptionControlNonFinalFragSizeRx, arg)); 10789 case bcmPortPreemptControlFinalFragSizeRx: 10790 return (portmod_preemption_control_set(unit, port , 10791 portmodPreemptionControlFinalFragSizeRx, arg)); 10792 default: 10793 return BCM_E_UNAVAIL; 10794 } 10795 #endif 10796 return BCM_E_UNAVAIL; 10797 } 10798 /* 10799 * Function: 10800 * bcmi_esw_portctrl_preemption_mac_config_get 10801 * Purpose: 10802 * get preemption mac config 10803 * Parameters: 10804 * unit - (IN) unit number. 10805 * port - (IN) port number 10806 * type - (IN) Preemption control type 10807 * arg - (OUT) value 10808 * Returns: 10809 * BCM_E_XXX 10810 * Notes: 10811 */ 10812 int 10813 bcmi_esw_portctrl_preemption_mac_config_get(int unit, bcm_port_t port, 10814 bcm_port_preempt_control_t type, 10815 uint32* arg) 10816 { 10817 10818 #ifdef PORTMOD_SUPPORT 10819 portctrl_pport_t pport; 10820 10821 /* Make sure port module is initialized. */ 10822 PORTCTRL_INIT_CHECK(unit); 10823 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10824 10825 switch (type) { 10826 case bcmPortPreemptControlPreemptionSupport: 10827 return (portmod_preemption_control_get(unit, port , 10828 portmodPreemptionControlPreemptionSupport, arg)); 10829 case bcmPortPreemptControlEnableTx: 10830 return (portmod_preemption_control_get(unit, port , 10831 portmodPreemptionControlEnableTx, arg)); 10832 case bcmPortPreemptControlVerifyEnable: 10833 return (portmod_preemption_control_get(unit, port , 10834 portmodPreemptionControlVerifyEnable, arg)); 10835 case bcmPortPreemptControlVerifyTime: 10836 return (portmod_preemption_control_get(unit, port , 10837 portmodPreemptionControlVerifyTime, arg)); 10838 case bcmPortPreemptControlVerifyAttempts: 10839 return (portmod_preemption_control_get(unit, port , 10840 portmodPreemptionControlVerifyAttempts, arg)); 10841 case bcmPortPreemptControlNonFinalFragSizeRx: 10842 return (portmod_preemption_control_get(unit, port , 10843 portmodPreemptionControlNonFinalFragSizeRx, arg)); 10844 case bcmPortPreemptControlFinalFragSizeRx: 10845 return (portmod_preemption_control_get(unit, port , 10846 portmodPreemptionControlFinalFragSizeRx, arg)); 10847 default: 10848 return BCM_E_UNAVAIL; 10849 } 10850 #endif 10851 return BCM_E_UNAVAIL; 10852 } 10853 10854 #if defined(INCLUDE_PHY_542XX) 10855 /* 10856 * Function: 10857 * bcmi_esw_portctrl_serdes_link_update 10858 * Description: 10859 * Update the force link status of Serdes 10860 * Parameters: 10861 * unit - Device number 10862 * port - Port number 10863 * link - Link Status of the port 10864 * Return Value: 10865 * BCM_E_XXX 10866 * Notes: 10867 */ 10868 int 10869 bcmi_esw_portctrl_serdes_link_update(int unit, bcm_port_t port, int link) 10870 { 10871 #ifdef PORTMOD_SUPPORT 10872 portmod_port_update_control_t portmod_port_update_control; 10873 int rv = BCM_E_NONE; 10874 portctrl_pport_t pport; 10875 10876 /* Make sure port module is initialized. */ 10877 PORTCTRL_INIT_CHECK(unit); 10878 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10879 10880 SOC_IF_ERROR_RETURN(portmod_port_update_control_t_init(unit, 10881 &portmod_port_update_control)); 10882 portmod_port_update_control.link_status = link; 10883 PORTMOD_PORT_UPDATE_F_UPDATE_SERDES_LINK_SET(&portmod_port_update_control); 10884 PORT_LOCK(unit); 10885 rv = portmod_port_update(unit, port, &portmod_port_update_control); 10886 PORT_UNLOCK(unit); 10887 return rv; 10888 #else /* PORTMOD_SUPPORT */ 10889 return BCM_E_UNAVAIL; 10890 #endif /* PORTMOD_SUPPORT */ 10891 } 10892 #endif 10893 10894 /* 10895 * Function: 10896 * bcmi_esw_portctrl_timestamp_adjust_set 10897 * Purpose: 10898 * set OSTS,TSTS timestamp adjust based on speed 10899 * Parameters: 10900 * unit - (IN) Unit number. 10901 * port - (IN) Port. 10902 * ts_adjust - (IN) configuration for tsts,osts timestamp adjustment. 10903 * Returns: 10904 * BCM_E_xxx 10905 * Notes: 10906 */ 10907 int 10908 bcmi_esw_portctrl_timestamp_adjust_set(int unit, bcm_gport_t port, 10909 bcm_port_timestamp_adjust_t *ts_adjust) 10910 { 10911 #ifdef PORTMOD_SUPPORT 10912 int rv; 10913 portctrl_pport_t pport; 10914 10915 PORTCTRL_INIT_CHECK(unit); 10916 10917 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10918 10919 PORT_LOCK(unit); 10920 rv = portmod_port_timestamp_adjust_set(unit, pport, ts_adjust); 10921 PORT_UNLOCK(unit); 10922 10923 return rv; 10924 #else /* PORTMOD_SUPPORT */ 10925 return BCM_E_UNAVAIL; 10926 #endif /* PORTMOD_SUPPORT */ 10927 } 10928 10929 /* 10930 * Function: 10931 * bcmi_esw_portctrl_timestamp_adjust_get 10932 * Purpose: 10933 * get OSTS,TSTS timestamp adjust based on current speed 10934 * Parameters: 10935 * unit - (IN) Unit number. 10936 * port - (IN) Port. 10937 * ts_adjust - (OUT) configuration of tsts,osts timestamp adjustment. 10938 * Returns: 10939 * BCM_E_xxx 10940 * Notes: 10941 */ 10942 int 10943 bcmi_esw_portctrl_timestamp_adjust_get(int unit, bcm_gport_t port, 10944 bcm_port_timestamp_adjust_t *ts_adjust) 10945 { 10946 #ifdef PORTMOD_SUPPORT 10947 int rv; 10948 portctrl_pport_t pport; 10949 10950 PORTCTRL_INIT_CHECK(unit); 10951 10952 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 10953 10954 PORT_LOCK(unit); 10955 rv = portmod_port_timestamp_adjust_get(unit, pport, ts_adjust); 10956 PORT_UNLOCK(unit); 10957 10958 return rv; 10959 #else /* PORTMOD_SUPPORT */ 10960 return BCM_E_UNAVAIL; 10961 #endif /* PORTMOD_SUPPORT */ 10962 } 10963 10964 /* Function: 10965 * bcmi_esw_portctrl_phy_tx_set 10966 * Purpose: 10967 * Set port phy tx properties 10968 * Parameters: 10969 * unit - StrataSwitch Unit #. 10970 * port - StrataSwtich port #. 10971 * tx - tx properties 10972 * Returns: 10973 * BCM_E_NONE 10974 * BCM_E_XXX 10975 */ 10976 int 10977 bcmi_esw_portctrl_phy_tx_set(int unit, 10978 bcm_port_t port, 10979 bcm_port_phy_tx_t *tx) 10980 { 10981 #ifdef PORTMOD_SUPPORT 10982 int rv; 10983 portctrl_pport_t pport; 10984 int phy_lane = -1; 10985 int phyn = -1, sys_side = 0; 10986 bcm_port_t local_port = -1; 10987 10988 /* Make sure port module is initialized. */ 10989 PORTCTRL_INIT_CHECK(unit); 10990 10991 BCM_IF_ERROR_RETURN( 10992 _bcm_esw_port_gport_phyn_validate(unit, port, 10993 &local_port, &phyn, 10994 &phy_lane, &sys_side)); 10995 10996 if (local_port != -1) { 10997 port = local_port; 10998 } 10999 11000 /* Only support for PM8x50 ports */ 11001 if (!IS_CD_PORT(unit, port)) { 11002 return BCM_E_UNAVAIL; 11003 } 11004 11005 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 11006 11007 PORT_LOCK(unit); 11008 port = local_port; 11009 11010 rv = soc_esw_portctrl_phy_tx_set(unit, pport, phyn, phy_lane, sys_side, (soc_port_phy_tx_t *)tx); 11011 PORT_UNLOCK(unit); 11012 11013 return rv; 11014 #else /* PORTMOD_SUPPORT */ 11015 return BCM_E_UNAVAIL; 11016 #endif /* PORTMOD_SUPPORT */ 11017 } 11018 11019 /* Function: 11020 * bcmi_esw_portctrl_phy_tx_get 11021 * Purpose: 11022 * Set port phy tx properties 11023 * Parameters: 11024 * unit - StrataSwitch Unit #. 11025 * port - StrataSwtich port #. 11026 * tx - tx properties 11027 * Returns: 11028 * BCM_E_NONE 11029 * BCM_E_XXX 11030 */ 11031 int 11032 bcmi_esw_portctrl_phy_tx_get(int unit, 11033 bcm_port_t port, 11034 bcm_port_phy_tx_t *tx) 11035 { 11036 #ifdef PORTMOD_SUPPORT 11037 int rv; 11038 portctrl_pport_t pport; 11039 int phy_lane = -1; 11040 int phyn = -1, sys_side = 0; 11041 bcm_port_t local_port = -1; 11042 11043 /* Make sure port module is initialized. */ 11044 PORTCTRL_INIT_CHECK(unit); 11045 11046 BCM_IF_ERROR_RETURN( 11047 _bcm_esw_port_gport_phyn_validate(unit, port, 11048 &local_port, &phyn, 11049 &phy_lane, &sys_side)); 11050 11051 if (local_port != -1) { 11052 port = local_port; 11053 } 11054 11055 /* Only support for PM8x50 ports */ 11056 if (!IS_CD_PORT(unit, port)) { 11057 return BCM_E_UNAVAIL; 11058 } 11059 11060 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 11061 11062 PORT_LOCK(unit); 11063 rv = soc_esw_portctrl_phy_tx_get(unit, pport, phyn, phy_lane, sys_side, (soc_port_phy_tx_t *)tx); 11064 11065 PORT_UNLOCK(unit); 11066 11067 return rv; 11068 #else /* PORTMOD_SUPPORT */ 11069 return BCM_E_UNAVAIL; 11070 #endif /* PORTMOD_SUPPORT */ 11071 } 11072 11073 /* Function: 11074 * bcmi_esw_portctrl_speed_config_get 11075 * Purpose: 11076 * Fetch the speed config from portmod 11077 * Parameters: 11078 * unit - (IN) StrataSwitch Unit #. 11079 * port - (IN) gport 11080 * speed_config - (OUT) pointer to speed_config datatype 11081 * Returns: 11082 * BCM_E_NONE 11083 * BCM_E_XXX 11084 */ 11085 int 11086 bcmi_esw_portctrl_speed_config_get(int unit, 11087 bcm_gport_t gport, 11088 void *speed_config) 11089 { 11090 #if defined(PORTMOD_SUPPORT) && defined(PORTMOD_PM8X50_SUPPORT) 11091 int pport; 11092 int phy_port; 11093 int lport; 11094 int rv = BCM_E_UNAVAIL; 11095 portmod_dispatch_type_t pm_type; 11096 11097 if (NULL == speed_config) { 11098 return BCM_E_PARAM; 11099 } 11100 11101 /* validate the gport to fetch the logical port */ 11102 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, gport, &lport)); 11103 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, lport, &lport, &pport)); 11104 11105 /* get the port macro type */ 11106 phy_port = SOC_INFO(unit).port_l2p_mapping[lport]; 11107 #if defined(BCM_TOMAHAWK3_SUPPORT) 11108 /* The PM4x10 requires a gap between the two management ports in TH3, 11109 * so portmod sees the management ports as physical ports 257 and 259 while 11110 * the SDK sees them as physical ports 257 and 258 11111 */ 11112 if (SOC_IS_TOMAHAWK3(unit) && phy_port == 258) { 11113 phy_port = 259; 11114 } 11115 #endif 11116 BCM_IF_ERROR_RETURN(portmod_phy_pm_type_get(unit, phy_port, &pm_type)); 11117 11118 /* if pm8x50, then fetch the speed config */ 11119 if (pm_type == portmodDispatchTypePm8x50) { 11120 PORT_LOCK(unit); 11121 rv = portmod_port_speed_config_get(unit, pport, 11122 ((portmod_speed_config_t *)speed_config)); 11123 PORT_UNLOCK(unit); 11124 } 11125 11126 return rv; 11127 #else 11128 return BCM_E_UNAVAIL; 11129 #endif 11130 } 11131 11132 /* Function: 11133 * bcmi_esw_portctrl_rlm_config_set 11134 * Purpose: 11135 * Set port rlm properties 11136 * Parameters: 11137 * unit - StrataSwitch Unit #. 11138 * port - StrataSwtich port #. 11139 * tx - tx properties 11140 * enable - enable/disable 11141 * Returns: 11142 * BCM_E_NONE 11143 * BCM_E_XXX 11144 */ 11145 int 11146 bcmi_esw_portctrl_rlm_config_set(int unit, 11147 bcm_port_t port, 11148 bcm_port_rlm_config_t *rlm_config, 11149 int enable) 11150 { 11151 #ifdef PORTMOD_SUPPORT 11152 int rv = BCM_E_NONE; 11153 portctrl_pport_t pport; 11154 int phy_lane = -1; 11155 int phyn = -1, sys_side = 0; 11156 bcm_port_t local_port = -1; 11157 portmod_port_rlm_config_t portmod_rlm_config; 11158 11159 /* Make sure port module is initialized. */ 11160 PORTCTRL_INIT_CHECK(unit); 11161 11162 BCM_IF_ERROR_RETURN( 11163 _bcm_esw_port_gport_phyn_validate(unit, port, 11164 &local_port, &phyn, 11165 &phy_lane, &sys_side)); 11166 11167 if (local_port != -1) { 11168 port = local_port; 11169 } 11170 11171 /* Only support for PM8x50 ports */ 11172 if (!IS_CD_PORT(unit, port)) { 11173 return BCM_E_UNAVAIL; 11174 } 11175 11176 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 11177 11178 PORT_LOCK(unit); 11179 11180 portmod_rlm_config.active_lane_bit_map = rlm_config->active_lane_bit_map; 11181 portmod_rlm_config.is_initiator = rlm_config->is_initiator; 11182 11183 rv = portmod_port_rlm_config_set(unit, port, enable, &portmod_rlm_config); 11184 PORT_UNLOCK(unit); 11185 11186 return rv; 11187 #else /* PORTMOD_SUPPORT */ 11188 return BCM_E_UNAVAIL; 11189 #endif /* PORTMOD_SUPPORT */ 11190 } 11191 11192 /* Function: 11193 * bcmi_esw_portctrl_rlm_config_get 11194 * Purpose: 11195 * Get port rlm properties 11196 * Parameters: 11197 * unit - StrataSwitch Unit #. 11198 * port - StrataSwtich port #. 11199 * rlm_config - rlm properties 11200 * enable - enable/disable 11201 * Returns: 11202 * BCM_E_NONE 11203 * BCM_E_XXX 11204 */ 11205 int 11206 bcmi_esw_portctrl_rlm_config_get(int unit, 11207 bcm_port_t port, 11208 bcm_port_rlm_config_t *rlm_config, 11209 int *enable) 11210 { 11211 #ifdef PORTMOD_SUPPORT 11212 int rv = BCM_E_NONE; 11213 portctrl_pport_t pport; 11214 int phy_lane = -1; 11215 int phyn = -1, sys_side = 0; 11216 bcm_port_t local_port = -1; 11217 portmod_port_rlm_config_t portmod_rlm_config; 11218 11219 /* Make sure port module is initialized. */ 11220 PORTCTRL_INIT_CHECK(unit); 11221 11222 BCM_IF_ERROR_RETURN( 11223 _bcm_esw_port_gport_phyn_validate(unit, port, 11224 &local_port, &phyn, 11225 &phy_lane, &sys_side)); 11226 11227 if (local_port != -1) { 11228 port = local_port; 11229 } 11230 11231 /* Only support for PM8x50 ports */ 11232 if (!IS_CD_PORT(unit, port)) { 11233 return BCM_E_UNAVAIL; 11234 } 11235 11236 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 11237 11238 PORT_LOCK(unit); 11239 rv = portmod_port_rlm_config_get(unit, port, enable, &portmod_rlm_config); 11240 rlm_config->active_lane_bit_map = portmod_rlm_config.active_lane_bit_map; 11241 rlm_config->is_initiator = portmod_rlm_config.is_initiator; 11242 11243 PORT_UNLOCK(unit); 11244 11245 return rv; 11246 #else /* PORTMOD_SUPPORT */ 11247 return BCM_E_UNAVAIL; 11248 #endif /* PORTMOD_SUPPORT */ 11249 } 11250 11251 /* Function: 11252 * bcmi_esw_portctrl_rlm_status_get 11253 * Purpose: 11254 * Get port rlm status 11255 * Parameters: 11256 * unit - StrataSwitch Unit #. 11257 * port - StrataSwtich port #. 11258 * rlm_status - rlm status 11259 * Returns: 11260 * BCM_E_NONE 11261 * BCM_E_XXX 11262 */ 11263 int 11264 bcmi_esw_portctrl_rlm_status_get(int unit, 11265 bcm_port_t port, 11266 bcm_port_rlm_status_t *rlm_status) 11267 { 11268 #ifdef PORTMOD_SUPPORT 11269 int rv = BCM_E_NONE; 11270 portctrl_pport_t pport; 11271 int phy_lane = -1; 11272 int phyn = -1, sys_side = 0; 11273 bcm_port_t local_port = -1; 11274 portmod_port_rlm_status_t portmod_rlm_status; 11275 11276 /* Make sure port module is initialized. */ 11277 PORTCTRL_INIT_CHECK(unit); 11278 11279 BCM_IF_ERROR_RETURN( 11280 _bcm_esw_port_gport_phyn_validate(unit, port, 11281 &local_port, &phyn, 11282 &phy_lane, &sys_side)); 11283 11284 if (local_port != -1) { 11285 port = local_port; 11286 } 11287 11288 /* Only support for PM8x50 ports */ 11289 if (!IS_CD_PORT(unit, port)) { 11290 return BCM_E_UNAVAIL; 11291 } 11292 11293 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 11294 11295 PORT_LOCK(unit); 11296 /* get the portmod RLM status */ 11297 rv = portmod_port_rlm_status_get(unit, port, &portmod_rlm_status); 11298 if (portmod_rlm_status.rlm_busy) { 11299 *rlm_status = bcmPortRlmBusy; 11300 } else if (portmod_rlm_status.rlm_disabled) { 11301 *rlm_status = bcmPortRlmDisabled; 11302 } else if (portmod_rlm_status.rlm_done) { 11303 *rlm_status = bcmPortRlmDone; 11304 } else if (portmod_rlm_status.rlm_failed) { 11305 *rlm_status = bcmPortRlmFailed; 11306 } else { 11307 return BCM_E_UNAVAIL; 11308 } 11309 11310 PORT_UNLOCK(unit); 11311 11312 return rv; 11313 #else /* PORTMOD_SUPPORT */ 11314 return BCM_E_UNAVAIL; 11315 #endif /* PORTMOD_SUPPORT */ 11316 } 11317 11318 /* Function: 11319 * bcmi_esw_portctrl_autoneg_status_get 11320 * Purpose: 11321 * Get port autoneg status 11322 * Parameters: 11323 * unit - StrataSwitch Unit #. 11324 * port - StrataSwtich port #. 11325 * enabled - if AN is enabled 11326 * locked - if AN is locked 11327 * Returns: 11328 * BCM_E_NONE 11329 * BCM_E_XXX 11330 */ 11331 int 11332 bcmi_esw_portctrl_autoneg_status_get(int unit, 11333 bcm_gport_t port, 11334 int *enabled, 11335 int *locked) 11336 11337 { 11338 int rv = BCM_E_NONE; 11339 #ifdef PORTMOD_SUPPORT 11340 portctrl_pport_t pport; 11341 phymod_autoneg_status_t an_status; 11342 11343 PORTCTRL_INIT_CHECK(unit); 11344 11345 BCM_IF_ERROR_RETURN(PORTCTRL_PORT_RESOLVE(unit, port, &port, &pport)); 11346 11347 PORT_LOCK(unit); 11348 11349 rv = portmod_port_autoneg_status_get(unit, pport, &an_status); 11350 11351 PORT_UNLOCK(unit); 11352 11353 *enabled = an_status.enabled; 11354 *locked = an_status.locked; 11355 #endif 11356 return rv; 11357 }