port.c (115212B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: port.c 8 * Purpose: Port driver. 9 */ 10 11 #include <soc/defs.h> 12 13 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 14 #include <shared/bsl.h> 15 #include <soc/drv.h> 16 #include <soc/types.h> 17 #include <soc/td2_td2p.h> 18 #include <bcm_int/esw_dispatch.h> 19 #include <bcm_int/esw/port.h> 20 #include <bcm_int/esw/stack.h> 21 #include <bcm_int/esw/mirror.h> 22 #include <bcm_int/esw/portctrl.h> 23 #include <bcm_int/esw/firebolt.h> 24 #include <bcm_int/esw/triumph.h> 25 #include <bcm_int/esw/triumph2.h> 26 #include <bcm_int/esw/triumph3.h> 27 #include <bcm_int/esw/trx.h> 28 #include <bcm_int/esw/xgs5.h> 29 #include <bcm_int/esw/xgs3.h> 30 #include <bcm_int/esw/trident2.h> 31 #include <bcm_int/esw/trident2plus.h> 32 #include <bcm_int/esw/trx.h> 33 #include <bcm/error.h> 34 #include <bcm/port.h> 35 36 37 /* 38 * FlexPort Operations Changes 39 * 40 * Flags to be used to determine the type of operations required 41 * when the FlexPort API multi_set() is called. 42 * 43 * OP_NONE - No changes. 44 * OP_PMAP - Change in port mapping. It requires FlexPort sequence. 45 * OP_LANES - Change in lanes. It requires FlexPort sequence. 46 * OP_SPEED - Change in speed. This is covered in a FlexPort sequence. 47 * A change in speed may require a FlexPort sequence. 48 * If it is not required, then calling the 'speed' set 49 * function is sufficient. 50 * OP_ENCAP - Change in encap mode. It is NOT covered in a FlexPort 51 * sequence, so an explicit call must be made to change 52 * the encap mode. 53 * OP_ALL - All the above. It requires FlexPort sequence. 54 */ 55 #define BCM_TD2P_PORT_RESOURCE_OP_NONE 0 56 #define BCM_TD2P_PORT_RESOURCE_OP_PMAP (1 << 0) 57 #define BCM_TD2P_PORT_RESOURCE_OP_LANES (1 << 1) 58 #define BCM_TD2P_PORT_RESOURCE_OP_SPEED (1 << 2) 59 #define BCM_TD2P_PORT_RESOURCE_OP_ENCAP (1 << 3) 60 #define BCM_TD2P_PORT_RESOURCE_OP_ALL \ 61 (BCM_TD2P_PORT_RESOURCE_OP_PMAP | \ 62 BCM_TD2P_PORT_RESOURCE_OP_LANES | \ 63 BCM_TD2P_PORT_RESOURCE_OP_SPEED | \ 64 BCM_TD2P_PORT_RESOURCE_OP_ENCAP) 65 66 soc_profile_mem_t *egr_pri_cng_profile[BCM_MAX_NUM_UNITS] = {NULL}; 67 68 /* 69 * DSCP 70 */ 71 #define DSCP_CODE_POINT_CNT 64 72 73 74 /* 75 * Internal BCM Port Resource Configuration 76 */ 77 typedef struct bcm_td2p_port_resource_s { 78 uint32 flags; /* SOC_PORT_RESOURCE_XXX */ 79 bcm_gport_t port; /* Local logical port number to connect to 80 the given physical port */ 81 int physical_port; /* Local physical port, -1 if the logical to 82 physical mapping is to be deleted */ 83 int speed; /* Initial speed after FlexPort operation */ 84 int lanes; /* Number of PHY lanes for this physical port */ 85 bcm_port_encap_t encap; /* Encapsulation mode for port */ 86 } bcm_td2p_port_resource_t; 87 88 89 /* 90 * Forward static function declaration 91 */ 92 STATIC int 93 _bcm_td2p_port_resource_multi_set(int unit, 94 int nport, bcm_port_resource_t *resource); 95 STATIC int 96 _bcm_td2p_port_resource_speed_set(int unit, bcm_port_t port, int speed); 97 98 /* 99 * Function Vector 100 */ 101 static bcm_esw_port_drv_t bcm_td2p_port_drv = { 102 /* fn_drv_init */ bcmi_td2p_port_fn_drv_init, 103 /* resource_set */ bcmi_xgs5_port_resource_set, 104 /* resource_get */ bcmi_xgs5_port_resource_get, 105 /* resource_multi_set */ _bcm_td2p_port_resource_multi_set, 106 /* resource_speed_set */ _bcm_td2p_port_resource_speed_set, 107 /* resource_traverse */ bcmi_xgs5_port_resource_traverse, 108 /* port_redirect_set */ NULL, 109 /* port_redirect_get */ NULL, 110 /* port_enable_set */ NULL, 111 /* encap_speed_check */ bcmi_xgs5_port_encap_speed_check, 112 /* force_lb_set */ NULL, 113 /* force_lb_check */ NULL, 114 /* resource_status_update */ bcmi_xgs5_port_resource_status_update 115 }; 116 117 118 /* 119 * Function: 120 * bcmi_td2p_port_fn_drv_init 121 * Purpose: 122 * Initialize the Port function driver. 123 * Parameters: 124 * unit - (IN) Unit number. 125 * Returns: 126 * BCM_E_xxx 127 * Notes: 128 */ 129 int 130 bcmi_td2p_port_fn_drv_init(int unit) 131 { 132 /* Initialize Common XGS5 Port module */ 133 BCM_IF_ERROR_RETURN 134 (bcmi_xgs5_port_fn_drv_init(unit, &bcm_td2p_port_drv, NULL, NULL)); 135 136 return BCM_E_NONE; 137 } 138 139 140 /* 141 * Function: 142 * _bcm_td2p_port_trunk_src_trunk_map_table_entry_init 143 * Purpose: 144 * This function is used by Flexport feature. It programs 145 * SOURCE_TRUNK_MAP_TABLE entries for a port to the values programmed 146 * during chip initialization. 147 * Parameters: 148 * unit - (IN) SOC unit number. 149 * port - (IN) Source Port num. 150 * index - (OUT) Source mod port table index. Can be NULL if the caller is 151 * not interested in the table's index corresponding to the 152 * port. May be used for debugging. 153 * Returns: 154 * BCM_E_xxx 155 */ 156 STATIC int 157 _bcm_td2p_port_trunk_src_trunk_map_table_entry_init(int unit, bcm_port_t port, 158 int *index) 159 { 160 int my_modid; 161 int src_trk_idx = 0; 162 int rv; 163 source_trunk_map_table_entry_t trunk_map_entry; 164 165 /* Get module id for unit. */ 166 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 167 168 /* Get index to source trunk map table */ 169 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 170 port, 171 &src_trk_idx)); 172 173 /* Read source trunk map table */ 174 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 175 rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ALL, 176 src_trk_idx, &trunk_map_entry); 177 178 if (SOC_FAILURE(rv)) { 179 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 180 return rv; 181 } 182 183 /* Initialize relevant fields */ 184 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &trunk_map_entry, 185 PORT_TYPEf, 0); 186 187 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &trunk_map_entry, 188 TGIDf, 0); 189 190 /* Write entry to hw. */ 191 rv = soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ALL, 192 src_trk_idx, &trunk_map_entry); 193 194 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 195 196 if ((index != NULL) && SOC_SUCCESS(rv)) { 197 *index = src_trk_idx; 198 } 199 200 return rv; 201 } 202 203 /* 204 * Function: 205 * _bcm_td2p_port_trunk_port_attach 206 * Purpose: 207 * This function initializes trunk tables for newly added port. It is 208 * used for Flexport feature. 209 * Parameters: 210 * unit - (IN) Unit number. 211 * port - (IN) Logical port, BCM format. 212 * Returns: 213 * BCM_E_NONE Success. 214 * BCM_E_XXX 215 */ 216 217 STATIC int 218 _bcm_td2p_port_trunk_port_attach(int unit, bcm_port_t port) 219 { 220 221 bcm_pbmp_t pbmp; 222 higig_trunk_control_entry_t entry; 223 int rv = BCM_E_NONE; 224 int index = -1; 225 226 BCM_IF_ERROR_RETURN(_bcm_td2p_port_trunk_src_trunk_map_table_entry_init( 227 unit, port, &index)); 228 229 LOG_INFO(BSL_LS_BCM_PORT, 230 (BSL_META_U(unit, 231 "table_entry_init: unit=%d port=%d index=%d\n"), 232 unit, port, index)); 233 234 soc_mem_lock(unit, HIGIG_TRUNK_CONTROLm); 235 236 rv = soc_mem_read(unit, HIGIG_TRUNK_CONTROLm, MEM_BLOCK_ANY, 0, &entry); 237 238 if (SOC_FAILURE(rv)) { 239 soc_mem_unlock(unit, HIGIG_TRUNK_CONTROLm); 240 return (rv); 241 } 242 243 BCM_PBMP_CLEAR(pbmp); 244 245 /* Read port bmap from hardware, and add new port to the bitmap */ 246 soc_mem_pbmp_field_get(unit, HIGIG_TRUNK_CONTROLm, &entry, 247 ACTIVE_PORT_BITMAPf, &pbmp); 248 249 BCM_PBMP_PORT_ADD(pbmp, port); 250 251 soc_mem_pbmp_field_set(unit, HIGIG_TRUNK_CONTROLm, &entry, 252 ACTIVE_PORT_BITMAPf, &pbmp); 253 254 rv = soc_mem_write(unit, HIGIG_TRUNK_CONTROLm, MEM_BLOCK_ALL, 0, 255 &entry); 256 257 soc_mem_unlock(unit, HIGIG_TRUNK_CONTROLm); 258 259 return rv; 260 } 261 262 /* 263 * Function: 264 * _bcm_td2p_port_trunk_port_detach 265 * Purpose: 266 * This function updates the trunk tables for a deleted port. It is 267 * used for Flexport feature. 268 * Parameters: 269 * unit - (IN) Unit number. 270 * port - (IN) Logical port, BCM format. 271 * Returns: 272 * BCM_E_NONE Success. 273 * BCM_E_XXX 274 * Notes: 275 * The internal databases will be updated when a port is removed from trunk 276 * group, or when the trunk itself is destroyed 277 */ 278 279 STATIC int 280 _bcm_td2p_port_trunk_port_detach(int unit, bcm_port_t port) 281 { 282 bcm_pbmp_t pbmp; 283 higig_trunk_control_entry_t entry; 284 int rv = BCM_E_NONE; 285 286 soc_mem_lock(unit, HIGIG_TRUNK_CONTROLm); 287 288 rv = soc_mem_read(unit, HIGIG_TRUNK_CONTROLm, MEM_BLOCK_ANY, 0, &entry); 289 290 if (SOC_FAILURE(rv)) { 291 soc_mem_unlock(unit, HIGIG_TRUNK_CONTROLm); 292 return (rv); 293 } 294 295 BCM_PBMP_CLEAR(pbmp); 296 297 /* Read port bmap from hardware, and remove port from the bitmap */ 298 soc_mem_pbmp_field_get(unit, HIGIG_TRUNK_CONTROLm, &entry, 299 ACTIVE_PORT_BITMAPf, &pbmp); 300 301 BCM_PBMP_PORT_REMOVE(pbmp, port); 302 303 soc_mem_pbmp_field_set(unit, HIGIG_TRUNK_CONTROLm, &entry, 304 ACTIVE_PORT_BITMAPf, &pbmp); 305 306 rv = soc_mem_write(unit, HIGIG_TRUNK_CONTROLm, MEM_BLOCK_ALL, 0, 307 &entry); 308 309 soc_mem_unlock(unit, HIGIG_TRUNK_CONTROLm); 310 311 return rv; 312 } 313 314 /* 315 * Function: 316 * _bcm_td2p_port_ipmc_port_state_change 317 * Purpose: 318 * This function updates ipmc related fields in hardware tables/registers, 319 * for a specified port. It is used for Flexport feature. 320 * Parameters: 321 * unit - (IN) Unit number. 322 * port - (IN) Logical port, BCM format. 323 * enable - (IN) Port specific enable/disable of IPMC config and related 324 * features. Set TRUE to enable them, FALSE to disable them 325 * Returns: 326 * BCM_E_NONE Success. 327 * BCM_E_XXX 328 * Notes: 329 */ 330 STATIC int 331 _bcm_td2p_port_ipmc_port_state_change(int unit, bcm_port_t port, int enable) 332 { 333 int do_vlan = soc_property_get(unit, spn_IPMC_DO_VLAN, 1); 334 335 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, port, 336 _bcmPortIpmcV4Enable, enable)); 337 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, port, 338 _bcmPortIpmcV6Enable, enable)); 339 BCM_IF_ERROR_RETURN(_bcm_esw_port_config_set(unit, port, 340 _bcmPortIpmcVlanKey, (enable && do_vlan) ? 1 : 0)); 341 342 /* Update LPORT Profile Table */ 343 BCM_IF_ERROR_RETURN(_bcm_lport_profile_field32_modify(unit, 344 LPORT_PROFILE_LPORT_TAB, V4IPMC_ENABLEf, enable)); 345 BCM_IF_ERROR_RETURN(_bcm_lport_profile_field32_modify(unit, 346 LPORT_PROFILE_LPORT_TAB, V6IPMC_ENABLEf, enable)); 347 BCM_IF_ERROR_RETURN(_bcm_lport_profile_field32_modify(unit, 348 LPORT_PROFILE_LPORT_TAB, IPMC_DO_VLANf, 349 (enable && do_vlan) ? 1 : 0)); 350 351 return BCM_E_NONE; 352 } 353 354 /* 355 * Function: 356 * _bcm_td2p_port_ipmc_port_attach 357 * Purpose: 358 * This function programs hardware tables and registers for enabling IPMC 359 * functionality and related features. It is used for Flexport feature. 360 * Parameters: 361 * unit - (IN) Unit number. 362 * port - (IN) Logical port, BCM format. 363 * Returns: 364 * BCM_E_NONE Success. 365 * BCM_E_XXX 366 */ 367 STATIC int 368 _bcm_td2p_port_ipmc_port_attach(int unit, bcm_port_t port) 369 { 370 if (soc_feature(unit, soc_feature_ip_mcast)) { 371 BCM_IF_ERROR_RETURN(_bcm_td2p_port_ipmc_port_state_change(unit, 372 port, TRUE)); 373 374 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3) 375 if (soc_feature(unit, soc_feature_ip_mcast_repl)) { 376 BCM_IF_ERROR_RETURN(bcm_tr3_ipmc_port_attach_repl_init(unit, port)); 377 } 378 379 if (IS_E_PORT(unit, port)) { 380 BCM_IF_ERROR_RETURN(bcm_esw_ipmc_egress_port_set(unit, port, 381 _soc_mac_all_zeroes, 0, 0, 0)); 382 } 383 #endif 384 } 385 386 return BCM_E_NONE; 387 } 388 389 /* 390 * Function: 391 * _bcm_td2p_port_ipmc_port_detach 392 * Purpose: 393 * This function clears hardware tables and registers in IPMC 394 * functionality and related features. It is used for Flexport feature. 395 * Parameters: 396 * unit - (IN) Unit number. 397 * port - (IN) Logical port, BCM format. 398 * Returns: 399 * BCM_E_NONE Success. 400 * BCM_E_XXX 401 */ 402 STATIC int 403 _bcm_td2p_port_ipmc_port_detach(int unit, bcm_port_t port) 404 { 405 if (soc_feature(unit, soc_feature_ip_mcast)) { 406 BCM_IF_ERROR_RETURN(_bcm_td2p_port_ipmc_port_state_change(unit, 407 port, FALSE)); 408 409 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3) 410 if (soc_feature(unit, soc_feature_ip_mcast_repl)) { 411 /* See bcm_tr_ipmc_detach, bcm_tr3_ipmc_repl_detach for more 412 * information 413 */ 414 BCM_IF_ERROR_RETURN(bcm_tr3_ipmc_port_detach_repl_deinit(unit, port)); 415 } 416 #endif 417 } 418 419 return BCM_E_NONE; 420 } 421 422 423 /* 424 * Function: 425 * _bcm_td2p_port_rate_port_attach 426 * Purpose: 427 * Initialize port related information in the Rate module. 428 * Parameters: 429 * unit - (IN) Unit number. 430 * port - (IN) Logical port, BCM format. 431 * Returns: 432 * BCM_E_XXX 433 */ 434 STATIC int 435 _bcm_td2p_port_rate_port_attach(int unit, bcm_port_t port) 436 { 437 soc_field_t fields[] = {PACKET_QUANTUMf, BYTE_MODEf}; 438 uint32 values[] = {0x100, 1}; 439 440 SOC_IF_ERROR_RETURN 441 (WRITE_STORM_CONTROL_METER_CONFIGr(unit, port, 0)); 442 443 SOC_IF_ERROR_RETURN 444 (soc_reg_fields32_modify(unit, 445 STORM_CONTROL_METER_CONFIGr, 446 port, COUNTOF(fields), 447 fields, values)); 448 449 return BCM_E_NONE; 450 } 451 452 453 /* 454 * Function: 455 * _bcm_td2p_port_rate_port_detach 456 * Purpose: 457 * Clear port related information in the Rate module. 458 * Parameters: 459 * unit - (IN) Unit number. 460 * port - (IN) Logical port, BCM format. 461 * Returns: 462 * BCM_E_XXX 463 */ 464 STATIC int 465 _bcm_td2p_port_rate_port_detach(int unit, bcm_port_t port) 466 { 467 SOC_IF_ERROR_RETURN 468 (WRITE_STORM_CONTROL_METER_CONFIGr(unit, port, 0)); 469 470 return BCM_E_NONE; 471 } 472 473 474 /* 475 * Function: 476 * _bcm_td2p_port_stack_port_attach 477 * Purpose: 478 * Initialize port related information in the Stack module. 479 * Set my_modid and other modid related initialization. 480 * Parameters: 481 * unit - (IN) Unit number. 482 * port - (IN) Logical port, BCM format. 483 * Returns: 484 * BCM_E_XXX 485 * Notes: 486 * - Assumes port is valid. 487 */ 488 int 489 _bcm_td2p_port_stack_port_attach(int unit, bcm_port_t port) 490 { 491 modport_map_subport_entry_t subport_entry; 492 modport_map_subport_mirror_entry_t subport_m_entry; 493 494 /* Configure logical subport numbers */ 495 sal_memset(&subport_entry, 0, sizeof(subport_entry)); 496 soc_MODPORT_MAP_SUBPORTm_field32_set(unit, &subport_entry, ENABLEf, 1); 497 soc_MODPORT_MAP_SUBPORTm_field32_set(unit, &subport_entry, DESTf, port); 498 SOC_IF_ERROR_RETURN 499 (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ALL, 500 port, &subport_entry)); 501 502 /* Configure logical subport mirror numbers */ 503 sal_memset(&subport_m_entry, 0, sizeof(subport_m_entry)); 504 soc_MODPORT_MAP_SUBPORT_M0m_field32_set(unit, &subport_m_entry, 505 ENABLEf, 1); 506 soc_MODPORT_MAP_SUBPORT_M0m_field32_set(unit, &subport_m_entry, 507 DESTf, port); 508 SOC_IF_ERROR_RETURN 509 (WRITE_MODPORT_MAP_SUBPORT_MIRRORm(unit, MEM_BLOCK_ALL, 510 port, &subport_m_entry)); 511 512 /* Initialize modport map profiles ptr on port.*/ 513 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 514 BCM_IF_ERROR_RETURN 515 (bcm_td_stk_modport_map_port_attach(unit, port)); 516 } 517 518 return BCM_E_NONE; 519 } 520 521 522 /* 523 * Function: 524 * _bcm_td2p_port_stack_port_detach 525 * Purpose: 526 * Clear port related information in the Stack module. 527 * Parameters: 528 * unit - (IN) Unit number. 529 * port - (IN) Logical port, BCM format. 530 * Returns: 531 * BCM_E_XXX 532 * Notes: 533 * - Assumes port is valid. 534 */ 535 int 536 _bcm_td2p_port_stack_port_detach(int unit, bcm_port_t port) 537 { 538 modport_map_subport_entry_t subport_entry; 539 modport_map_subport_mirror_entry_t subport_m_entry; 540 541 /* Clear logical subport numbers */ 542 sal_memset(&subport_entry, 0, sizeof(subport_entry)); 543 SOC_IF_ERROR_RETURN 544 (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ALL, 545 port, &subport_entry)); 546 547 /* Clear logical subport mirror numbers */ 548 sal_memset(&subport_m_entry, 0, sizeof(subport_m_entry)); 549 SOC_IF_ERROR_RETURN 550 (WRITE_MODPORT_MAP_SUBPORT_MIRRORm(unit, MEM_BLOCK_ALL, 551 port, &subport_m_entry)); 552 553 /* detach port from modport map profiles */ 554 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 555 BCM_IF_ERROR_RETURN 556 (bcm_td_stk_modport_map_port_detach(unit, port)); 557 } 558 559 return BCM_E_NONE; 560 } 561 562 563 /* 564 * Function: 565 * _bcm_td2p_port_dscp_table_default_add 566 * Purpose: 567 * Add DSCP default profile entry to given port. 568 * Parameters: 569 * unit - (IN) Unit number. 570 * port - (IN) Logical port, BCM format. 571 * Returns: 572 * BCM_E_XXX 573 * Notes: 574 * - Assumes port is valid. 575 */ 576 STATIC int 577 _bcm_td2p_port_dscp_table_default_add(int unit, bcm_port_t port) 578 { 579 BCM_IF_ERROR_RETURN 580 (_bcm_esw_port_tab_set(unit, port, 581 _BCM_CPU_TABS_ETHER, 582 TRUST_DSCP_PTRf, 583 0)); 584 return BCM_E_NONE; 585 } 586 587 /* 588 * Function: 589 * _bcm_td2p_port_outer_tpid_ref_count_update 590 * Purpose: 591 * Update TPID reference count. 592 * Parameters: 593 * unit - (IN) Unit number. 594 * port - (IN) Logical port, BCM format. 595 * add - (IN) Indicates whether port is added or deleted from BCM. 596 * Returns: 597 * BCM_E_XXX 598 * Notes: 599 */ 600 STATIC int 601 _bcm_td2p_port_outer_tpid_ref_count_update(int unit, bcm_port_t port, int add) 602 { 603 egr_vlan_control_1_entry_t entry; 604 int index; 605 int enabled; 606 607 if (soc_feature(unit, soc_feature_egr_all_profile)) { 608 BCM_IF_ERROR_RETURN( 609 bcm_esw_port_egr_lport_field_get(unit, port, 610 EGR_VLAN_CONTROL_1m, OUTER_TPID_INDEXf, (void *)&index)); 611 } else { 612 SOC_IF_ERROR_RETURN 613 (READ_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry)); 614 index = soc_EGR_VLAN_CONTROL_1m_field32_get(unit, &entry, 615 OUTER_TPID_INDEXf); 616 } 617 if (add) { 618 BCM_IF_ERROR_RETURN 619 (_bcm_fb2_outer_tpid_tab_ref_count_add(unit, index, 1)); 620 } else { 621 /* Ignore error when deleting */ 622 (void) _bcm_fb2_outer_tpid_entry_delete(unit, index); 623 } 624 625 enabled = 0; 626 BCM_IF_ERROR_RETURN 627 (_bcm_esw_port_config_get(unit, port, 628 _bcmPortOuterTpidEnables, &enabled)); 629 index = 0; 630 while (enabled) { 631 if (enabled & 1) { 632 if (add) { 633 BCM_IF_ERROR_RETURN 634 (_bcm_fb2_outer_tpid_tab_ref_count_add(unit, index, 1)); 635 } else { 636 /* Ignore error when deleting */ 637 (void) _bcm_fb2_outer_tpid_entry_delete(unit, index); 638 } 639 } 640 enabled = enabled >> 1; 641 index++; 642 } 643 644 return BCM_E_NONE; 645 } 646 647 648 /* 649 * Function: 650 * _bcm_td2p_port_priority_map_init 651 * Purpose: 652 * Initialize priority map for given port. 653 * Parameters: 654 * unit - (IN) Unit number. 655 * port - (IN) Logical port, BCM format. 656 * Returns: 657 * BCM_E_XXX 658 * Notes: 659 */ 660 STATIC int 661 _bcm_td2p_port_priority_map_init(int unit, bcm_port_t port) 662 { 663 int rv = BCM_E_NONE; 664 665 if (soc_feature(unit, soc_feature_egr_qos_combo_profile)) { 666 rv = _bcm_esw_egr_port_tab_set(unit, port, EGR_QOS_PROFILE_INDEXf, 0); 667 if (BCM_FAILURE(rv)) { 668 return rv; 669 } 670 } else if (SOC_IS_TRIDENT3X(unit)) { 671 rv = _bcm_esw_egr_port_tab_set(unit, port, EGR_QOS_PROFILE_INDEXf, 0); 672 if (BCM_FAILURE(rv)) { 673 return rv; 674 } 675 } 676 677 return rv; 678 } 679 680 /* 681 * Function: 682 * _bcm_td2p_port_software_free 683 * Purpose: 684 * Deallocates memory for a given port from the BCM PORT module 685 * data structure. 686 * Parameters: 687 * unit - (IN) Unit number. 688 * port - (IN) Logical port, BCM format. 689 * Returns: 690 * BCM_E_XXX 691 * Notes: 692 * - Assumes main BCM PORT module initialization has been executed. 693 * - Assumes port is valid. 694 */ 695 STATIC int 696 _bcm_td2p_port_software_free(int unit, bcm_port_t port) 697 { 698 _bcm_port_info_t *pinfo; 699 700 /* Get PORT info structure pointer */ 701 BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo)); 702 if (pinfo == NULL) { 703 return BCM_E_INTERNAL; 704 } 705 706 /* Proto-based VLAN_DATA state */ 707 if (pinfo->p_vd_pbvl != NULL) { 708 sal_free(pinfo->p_vd_pbvl); 709 pinfo->p_vd_pbvl = NULL; 710 } 711 712 /* End-to-end congestion control configuration */ 713 if (pinfo->e2ecc_config != NULL) { 714 sal_free(pinfo->e2ecc_config); 715 pinfo->e2ecc_config = NULL; 716 } 717 718 /* Reset all fields */ 719 sal_memset(pinfo, 0, sizeof(_bcm_port_info_t)); 720 721 return BCM_E_NONE; 722 } 723 724 725 /* 726 * Function: 727 * _bcm_td2p_port_software_alloc 728 * Purpose: 729 * Allocates software memory in the BCM PORT module for given port. 730 * Parameters: 731 * unit - (IN) Unit number. 732 * port - (IN) Logical port, BCM format. 733 * Returns: 734 * BCM_E_XXX 735 * Notes: 736 * - Assumes main BCM PORT module initialization has been executed. 737 * - Assumes port is valid. 738 */ 739 STATIC int 740 _bcm_td2p_port_software_alloc(int unit, bcm_port_t port) 741 { 742 _bcm_port_info_t *pinfo; 743 int idxmax = soc_mem_index_count(unit, VLAN_PROTOCOLm); 744 int inds_bytes = (idxmax + (_BCM_PORT_VD_PBVL_ESIZE - 1)) / \ 745 _BCM_PORT_VD_PBVL_ESIZE; /* Round to the next entry */ 746 747 /* Free memory in case this is already allocated */ 748 BCM_IF_ERROR_RETURN(_bcm_td2p_port_software_free(unit, port)); 749 750 /* Get PORT info structure pointer */ 751 BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo)); 752 if (pinfo == NULL) { 753 LOG_ERROR(BSL_LS_BCM_PORT, 754 (BSL_META_U(unit, 755 "Unable to get PORT info data for " 756 "unit=%d port=%d\n"), 757 unit, port)); 758 return BCM_E_INTERNAL; 759 } 760 761 /* Reset all fields */ 762 sal_memset(pinfo, 0, sizeof(_bcm_port_info_t)); 763 764 /* Proto-based VLAN_DATA state */ 765 pinfo->p_vd_pbvl = sal_alloc(inds_bytes, "vdv_info"); 766 if (pinfo->p_vd_pbvl == NULL) { 767 LOG_ERROR(BSL_LS_BCM_PORT, 768 (BSL_META_U(unit, 769 "Unable to allocate memory for PORT vlan " 770 "unit=%d port=%d\n"), 771 unit, port)); 772 return BCM_E_MEMORY; 773 } 774 sal_memset(pinfo->p_vd_pbvl, 0, inds_bytes); 775 776 return BCM_E_NONE; 777 } 778 779 /* 780 * Function: 781 * _bcm_td2p_port_bridge_port_init 782 * Purpose: 783 * This function initializes PORT_BRIDGE_BMAP memory (for a normal port), 784 * and/or PORT_BRIDGE_MIRROR_BMAP (for a Higig port). The initialization is 785 * required for ensuring that port bit in one of the above memories 786 * (depending on port type), and PORT_TAB.PORT_BRIDGE bit have the same 787 * value. See notes. 788 * Parameters: 789 * unit - (IN) Unit number. 790 * port - (IN) Logical port, BCM format. 791 * value - 1 Set bit in PORT_BRIDGE_BMAP and/or PORT_BRIDGE_MIRROR_BMAP 792 * memory. 793 * 0 Reset bit in PORT_BRIDGE_BMAP and/or PORT_BRIDGE_MIRROR_BMAP 794 * memory. 795 * See Notes. 796 * Returns: 797 * BCM_E_XXX 798 * Notes: 799 * - PORT_TAB.PORT_BRIDGE is reset in function 800 * mbcm_driver[unit]->mbcm_port_cfg_init() 801 * - If this function is called outside of port attach and detach 802 * functions then the caller must make sure that PORT_TAB.PORT_BRIDGE is 803 * programmed to the same value as in these memories, for a given port 804 * Refer to memory description of these two memories for more information 805 * - Assumes port is valid. 806 * - Assumes this is NOT called during Warmboot. 807 */ 808 STATIC int 809 _bcm_td2p_port_bridge_port_init(int unit, bcm_port_t port, int value) 810 { 811 int rv = BCM_E_NONE; 812 bcm_pbmp_t pbmp; 813 814 if (IS_E_PORT(unit, port) 815 || IS_CPU_PORT(unit, port) 816 || IS_HG_PORT(unit, port)) { 817 port_bridge_bmap_entry_t entry; 818 819 SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_BRIDGE_BMAPm, 820 MEM_BLOCK_ANY, 0, &entry)); 821 soc_mem_pbmp_field_get(unit, PORT_BRIDGE_BMAPm, &entry, 822 BITMAPf, &pbmp); 823 824 if (value) { 825 SOC_PBMP_PORT_ADD(pbmp, port); 826 } else { 827 SOC_PBMP_PORT_REMOVE(pbmp, port); 828 } 829 830 soc_mem_pbmp_field_set(unit, PORT_BRIDGE_BMAPm, &entry, 831 BITMAPf, &pbmp); 832 833 SOC_IF_ERROR_RETURN(soc_mem_write(unit, PORT_BRIDGE_BMAPm, 834 MEM_BLOCK_ANY, 0, &entry)); 835 } 836 837 if (IS_HG_PORT(unit, port)) { 838 port_bridge_mirror_bmap_entry_t entry; 839 840 SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_BRIDGE_MIRROR_BMAPm, 841 MEM_BLOCK_ANY, 0, &entry)); 842 soc_mem_pbmp_field_get(unit, PORT_BRIDGE_MIRROR_BMAPm, &entry, 843 BITMAPf, &pbmp); 844 if (value) { 845 SOC_PBMP_PORT_ADD(pbmp, port); 846 } else { 847 SOC_PBMP_PORT_REMOVE(pbmp, port); 848 } 849 soc_mem_pbmp_field_set(unit, PORT_BRIDGE_MIRROR_BMAPm, &entry, 850 BITMAPf, &pbmp); 851 SOC_IF_ERROR_RETURN(soc_mem_write(unit, PORT_BRIDGE_MIRROR_BMAPm, 852 MEM_BLOCK_ANY, 0, &entry)); 853 } 854 855 return rv; 856 } 857 858 /* 859 * Function: 860 * _bcm_td2_port_basic_init 861 * Purpose: 862 * Initialize the BCM PORT module portion (basic) for a given port 863 * (bcm_esw_port_init). 864 * Parameters: 865 * unit - (IN) Unit number. 866 * port - (IN) Logical port, BCM format. 867 * Returns: 868 * BCM_E_XXX 869 * Notes: 870 * - Assumes main BCM PORT module initialization has been executed. 871 * - Assumes port is valid. 872 * - Caller must call other corresponding module routines 873 * that need to initialize any port related information. 874 * - Assumes this is NOT called during Warmboot. 875 */ 876 STATIC int 877 _bcm_td2_port_basic_init(int unit, bcm_port_t port) 878 { 879 int rv; 880 _bcm_port_info_t *pinfo; 881 bcm_vlan_action_set_t action; 882 bcm_pbmp_t port_pbmp; 883 bcm_vlan_data_t vd; 884 int length_check; 885 uint32 addr; 886 int block; 887 uint8 acc_type; 888 uint32 rval; 889 uint32 profile_index; 890 int blk; 891 int blk_num = -1; 892 int bindex = 0; 893 int tx_pbm = 0; 894 uint32 rx_los; 895 int enable; 896 int value; 897 898 LOG_VERBOSE(BSL_LS_BCM_PORT, 899 (BSL_META_U(unit, 900 "BCM Port Basic Init unit=%d port=%d(%s)\n"), 901 unit, port, SOC_PORT_NAME(unit, port))); 902 903 /* Get PORT info structure pointer */ 904 BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo)); 905 if (pinfo == NULL) { 906 LOG_ERROR(BSL_LS_BCM_PORT, 907 (BSL_META_U(unit, 908 "Unable to get PORT info data for " 909 "unit=%d port=%d\n"), 910 unit, port)); 911 return BCM_E_INTERNAL; 912 } 913 914 915 /********** 916 * VLAN TPID reference count 917 * Priority Map 918 * Double-Tag mode 919 */ 920 BCM_IF_ERROR_RETURN 921 (_bcm_td2p_port_outer_tpid_ref_count_update(unit, port, 1)); 922 BCM_IF_ERROR_RETURN 923 (_bcm_td2p_port_priority_map_init(unit, port)); 924 925 pinfo->dtag_mode = BCM_PORT_DTAG_MODE_NONE; 926 927 /********** 928 * VLAN Action 929 * soc_feature_vlan_action 930 */ 931 bcm_vlan_action_set_t_init(&action); 932 pinfo->vp_count = 0; 933 if (!IS_LB_PORT(unit, port)) { 934 BCM_IF_ERROR_RETURN 935 (_bcm_port_vlan_prot_index_alloc(unit, &(pinfo->vlan_prot_ptr))); 936 } 937 938 /* Update Egress VLAN profile table count */ 939 _bcm_trx_egr_vlan_action_profile_entry_increment 940 (unit, BCM_TRX_EGR_VLAN_ACTION_PROFILE_DEFAULT); 941 942 if (IS_HG_PORT(unit, port)) { 943 BCM_IF_ERROR_RETURN 944 (_bcm_trx_vlan_port_egress_default_action_get(unit, 945 port, &action)); 946 /* Backward compatible defaults */ 947 action.ot_outer = bcmVlanActionDelete; 948 action.dt_outer = bcmVlanActionDelete; 949 BCM_IF_ERROR_RETURN 950 (_bcm_trx_vlan_port_egress_default_action_set(unit, 951 port, &action)); 952 } 953 954 /********** 955 * Write port configuration tables to contain the Initial System 956 * Configuration (see init.c). 957 * 958 * Note: Logically, it would make more sense to call mbcm_port_cfg_init() 959 * and bcm_port_settings_init() first. However, we are maintaining 960 * the same order sequence as in bcm_esw_port_init() to avoid 961 * introducing dependencies issues on code above. 962 */ 963 SOC_PBMP_CLEAR(port_pbmp); 964 BCM_PBMP_ASSIGN(port_pbmp, PBMP_ALL(unit)); 965 SOC_PBMP_REMOVE(port_pbmp, PBMP_TDM(unit)); 966 967 vd.vlan_tag = BCM_VLAN_DEFAULT; 968 BCM_PBMP_ASSIGN(vd.port_bitmap, port_pbmp); 969 BCM_PBMP_ASSIGN(vd.ut_port_bitmap, port_pbmp); 970 BCM_PBMP_REMOVE(vd.ut_port_bitmap, PBMP_CMIC(unit)); 971 972 BCM_IF_ERROR_RETURN 973 (mbcm_driver[unit]->mbcm_port_cfg_init(unit, port, &vd)); 974 975 BCM_IF_ERROR_RETURN(_bcm_td2p_port_bridge_port_init(unit, port, 0)); 976 977 BCM_IF_ERROR_RETURN(bcm_port_settings_init(unit, port)); 978 979 /********** 980 * DSCP Profile 981 */ 982 BCM_IF_ERROR_RETURN 983 (_bcm_td2p_port_dscp_table_default_add(unit, port)); 984 985 /********** 986 * COS_MAP Profile 987 */ 988 if (SOC_IS_TRIDENT2PLUS(unit)) { 989 BCM_IF_ERROR_RETURN 990 (bcm_td2p_port_cosq_config_set(unit, port, TRUE)); 991 } 992 993 if (soc_feature(unit, soc_feature_pgw_mac_rsv_mask_remap)) { 994 /********** 995 * Frame Length Check 996 */ 997 length_check = soc_property_get(unit, spn_MAC_LENGTH_CHECK_ENABLE, 0); 998 addr = soc_reg_addr_get(unit, PGW_MAC_RSV_MASKr, port, 0, FALSE, &block, 999 &acc_type); 1000 addr &= 0xffffff00; 1001 addr |= (SOC_INFO(unit).port_l2p_mapping[port] - 1) & 0xf; 1002 SOC_IF_ERROR_RETURN 1003 (_soc_reg32_get(unit, block, acc_type, addr, &rval)); 1004 if (length_check) { 1005 rval |= 0x20; /* Set bit 5 to enable frame length check */ 1006 } else { 1007 rval &= ~0x20; /* Clear bit 5 to disable frame length check */ 1008 } 1009 rval |= 1 << 18; /* Set PFC frame detected indicator */ 1010 SOC_IF_ERROR_RETURN 1011 (_soc_reg32_set(unit, block, acc_type, addr, rval)); 1012 } 1013 1014 #ifdef BCM_RCPU_SUPPORT 1015 if ((uint32)port == soc_property_get(unit, spn_RCPU_PORT, -1)) { 1016 BCM_IF_ERROR_RETURN 1017 (bcm_esw_port_frame_max_set(unit, port, BCM_PORT_JUMBO_MAXSZ)); 1018 } 1019 #endif /* BCM_RCPU_SUPPORT */ 1020 1021 /********** 1022 * Outer TPID 1023 * soc_feature_vlan_ctrl 1024 */ 1025 BCM_IF_ERROR_RETURN 1026 (bcm_esw_port_tpid_set(unit, port, 1027 _bcm_fb2_outer_tpid_default_get(unit))); 1028 1029 /********** 1030 * Profile Indexes 1031 */ 1032 /* Initialize egress block profile pointer to invalid value */ 1033 BCM_IF_ERROR_RETURN 1034 (bcmi_esw_port_egr_prof_ptr_set(unit, port, -1)); 1035 1036 /* Program the VLAN_PROTOCOL_DATA / FP_PORT_FIELD_SEL_INDEX 1037 / PROTOCOL_PKT_INDEX pointers */ 1038 if (!IS_LB_PORT(unit, port) && !IS_TDM_PORT(unit, port)) { 1039 if (soc_mem_index_max(unit, VLAN_PROTOCOLm) > 0) { 1040 value = pinfo->vlan_prot_ptr / 1041 soc_mem_index_count(unit, VLAN_PROTOCOLm); 1042 1043 BCM_IF_ERROR_RETURN 1044 (_bcm_esw_port_tab_set(unit, port, 1045 _BCM_CPU_TABS_ETHER, 1046 VLAN_PROTOCOL_DATA_INDEXf, 1047 value)); 1048 } 1049 1050 BCM_IF_ERROR_RETURN 1051 (_bcm_esw_port_tab_set(unit, port, 1052 _BCM_CPU_TABS_ETHER, 1053 FP_PORT_FIELD_SEL_INDEXf, 1054 port)); 1055 BCM_IF_ERROR_RETURN 1056 (_bcm_prot_pkt_ctrl_add(unit, 0, 0, &profile_index)); 1057 BCM_IF_ERROR_RETURN 1058 (_bcm_esw_port_tab_set(unit, port, 1059 _BCM_CPU_TABS_ETHER, 1060 PROTOCOL_PKT_INDEXf, 1061 profile_index)); 1062 } 1063 1064 /******** 1065 * E2ECC 1066 * 1067 * Ports are enabled to send E2ECC messages by default. 1068 * Disable E2ECC message TX here until congestion config 1069 * set enables the port. 1070 */ 1071 blk = SOC_PORT_BLOCK(unit, SOC_INFO(unit).port_l2p_mapping[port]); 1072 bindex = SOC_PORT_BINDEX(unit, SOC_INFO(unit).port_l2p_mapping[port]); 1073 blk_num = SOC_BLOCK_INFO(unit, blk).number; 1074 1075 SOC_IF_ERROR_RETURN(READ_E2ECC_TX_ENABLE_BMPr(unit, blk_num, &rval)); 1076 tx_pbm = soc_reg_field_get(unit, E2ECC_TX_ENABLE_BMPr, rval, 1077 TX_ENABLE_BMPf); 1078 tx_pbm &= ~(1 << bindex); 1079 soc_reg_field_set(unit, E2ECC_TX_ENABLE_BMPr, &rval, 1080 TX_ENABLE_BMPf, tx_pbm); 1081 SOC_IF_ERROR_RETURN(WRITE_E2ECC_TX_ENABLE_BMPr(unit, blk_num, rval)); 1082 1083 /********** 1084 * EEE Config 1085 * soc_feature_eee 1086 */ 1087 if (!IS_LB_PORT(unit, port) && !IS_CPU_PORT (unit, port) && 1088 !IS_TDM_PORT(unit, port)) { 1089 /* EEE standard compliance Work Around: 1090 * Initialize the software state of native eee in MAC 1091 */ 1092 BCM_IF_ERROR_RETURN 1093 (bcmi_esw_port_eee_cfg_set(unit, port, 0)); 1094 /* Check if MAC supports Native EEE and set the value of 1095 * eee_cfg by reading the EEE status from MAC*/ 1096 rv = bcmi_esw_portctrl_eee_enable_get(unit, port, &value); 1097 if (rv != BCM_E_UNAVAIL) { 1098 BCM_IF_ERROR_RETURN 1099 (bcmi_esw_port_eee_cfg_set(unit, port, value)); 1100 } 1101 } 1102 1103 /********** 1104 * HIGIG 1105 */ 1106 if (IS_HG_PORT(unit, port)) { 1107 BCM_IF_ERROR_RETURN 1108 (bcmi_esw_portctrl_higig_mode_set(unit, port, TRUE)); 1109 #ifdef BCM_HIGIG2_SUPPORT 1110 /* soc_feature_higig2 */ 1111 BCM_IF_ERROR_RETURN 1112 (bcmi_esw_portctrl_higig2_mode_set(unit, port, TRUE)); 1113 SOC_HG2_ENABLED_PORT_ADD(unit, port); 1114 #endif /* BCM_HIGIG2_SUPPORT */ 1115 } else { /* IEEE */ 1116 BCM_IF_ERROR_RETURN 1117 (bcmi_esw_portctrl_higig_mode_set(unit, port, FALSE)); 1118 #ifdef BCM_HIGIG2_SUPPORT 1119 /* soc_feature_higig2 */ 1120 BCM_IF_ERROR_RETURN 1121 (bcmi_esw_portctrl_higig2_mode_set(unit, port, FALSE)); 1122 SOC_HG2_ENABLED_PORT_REMOVE(unit, port); 1123 #endif /* BCM_HIGIG2_SUPPORT */ 1124 } 1125 1126 /*********** 1127 * SW RX LOS configuration from PHY driver 1128 */ 1129 if (IS_E_PORT(unit, port)) { 1130 rv = bcm_esw_port_phy_control_get(unit, port, 1131 BCM_PORT_PHY_CONTROL_SOFTWARE_RX_LOS, 1132 &rx_los); 1133 if (BCM_SUCCESS(rv)) { 1134 pinfo->rx_los = rx_los; 1135 } 1136 } 1137 1138 /*********** 1139 * SW port enable status from HW 1140 */ 1141 rv = bcm_esw_port_enable_get(unit, port, &enable); 1142 if (BCM_SUCCESS(rv)) { 1143 pinfo->enable = enable; 1144 } 1145 1146 return BCM_E_NONE; 1147 } 1148 1149 /* 1150 * Function: 1151 * _bcm_td2_port_basic_attach 1152 * Purpose: 1153 * Initialize the BCM PORT module portion (basic) for a given port 1154 * (bcm_esw_port_init) and allocates any memory needed by the BCM PORT 1155 * module. 1156 * Parameters: 1157 * unit - (IN) Unit number. 1158 * port - (IN) Logical port, BCM format. 1159 * Returns: 1160 * BCM_E_XXX 1161 * Notes: 1162 * - Assumes main BCM PORT module initialization has been executed. 1163 * - Assumes port is valid. 1164 * - Caller must call other corresponding module routines 1165 * that need to initialize any port related information. 1166 * - Assumes this is NOT called during Warmboot. 1167 */ 1168 STATIC int 1169 _bcm_td2_port_basic_attach(int unit, bcm_port_t port) 1170 { 1171 int rv, rv1; 1172 1173 LOG_VERBOSE(BSL_LS_BCM_PORT, 1174 (BSL_META_U(unit, 1175 "BCM Attach Basic unit=%d port=%d(%s)\n"), 1176 unit, port, SOC_PORT_NAME(unit, port))); 1177 1178 /* Allocate SW memory needed by PORT module */ 1179 BCM_IF_ERROR_RETURN(_bcm_td2p_port_software_alloc(unit, port)); 1180 1181 /* Initialize PORT module */ 1182 rv = _bcm_td2_port_basic_init(unit, port); 1183 1184 /* 1185 * Only free memory during failure. 1186 * Memory is used by PORT module while port exists (attached). 1187 */ 1188 if (BCM_FAILURE(rv)) { 1189 rv1 = _bcm_td2p_port_software_free(unit, port); 1190 if (BCM_FAILURE(rv1)) { 1191 rv = rv1; 1192 } 1193 } 1194 1195 return rv; 1196 } 1197 1198 1199 /* 1200 * Function: 1201 * _bcm_td2_port_basic_detach 1202 * Purpose: 1203 * Clear the BCM PORT module portion (basic) for a given port. 1204 * Parameters: 1205 * unit - (IN) Unit number. 1206 * port - (IN) Logical port, BCM format. 1207 * Returns: 1208 * BCM_E_XXX 1209 * Notes: 1210 * - Assumes port is valid. 1211 * - Caller must call other corresponding module routines 1212 * where any port related information needs to be cleared. 1213 */ 1214 STATIC int 1215 _bcm_td2_port_basic_detach(int unit, bcm_port_t port) 1216 { 1217 _bcm_port_info_t *pinfo; 1218 bcm_pbmp_t port_pbmp; 1219 bcm_vlan_data_t vd; 1220 int value; 1221 1222 LOG_VERBOSE(BSL_LS_BCM_PORT, 1223 (BSL_META_U(unit, 1224 "BCM Detach Basic unit=%d port=%d(%s)\n"), 1225 unit, port, SOC_PORT_NAME(unit, port))); 1226 1227 /* Get PORT info structure pointer */ 1228 BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo)); 1229 if (pinfo == NULL) { 1230 LOG_ERROR(BSL_LS_BCM_PORT, 1231 (BSL_META_U(unit, 1232 "Unable to get PORT info data for " 1233 "unit=%d port=%d\n"), 1234 unit, port)); 1235 return BCM_E_INTERNAL; 1236 } 1237 1238 /********** 1239 * COS_MAP Profile 1240 */ 1241 if (SOC_IS_TRIDENT2PLUS(unit)) { 1242 BCM_IF_ERROR_RETURN 1243 (bcm_td2p_port_cosq_config_set(unit, port, FALSE)); 1244 } 1245 1246 /********** 1247 * HIGIG 1248 */ 1249 BCM_IF_ERROR_RETURN 1250 (bcmi_esw_portctrl_higig_mode_set(unit, port, FALSE)); 1251 #ifdef BCM_HIGIG2_SUPPORT 1252 /* soc_feature_higig2 */ 1253 BCM_IF_ERROR_RETURN 1254 (bcmi_esw_portctrl_higig2_mode_set(unit, port, FALSE)); 1255 SOC_HG2_ENABLED_PORT_REMOVE(unit, port); 1256 #endif /* BCM_HIGIG2_SUPPORT */ 1257 1258 /******* 1259 * EEE Config 1260 */ 1261 if (!IS_LB_PORT(unit, port) && !IS_CPU_PORT (unit, port) && 1262 !IS_TDM_PORT(unit, port)) { 1263 BCM_IF_ERROR_RETURN 1264 (bcmi_esw_port_eee_cfg_set(unit, port, 0)); 1265 } 1266 1267 /********** 1268 * Profile Indexes 1269 */ 1270 /* Program the VLAN_PROTOCOL_DATA / FP_PORT_FIELD_SEL_INDEX 1271 / PROTOCOL_PKT_INDEX pointers */ 1272 if (!IS_LB_PORT(unit, port) && !IS_TDM_PORT(unit, port)) { 1273 if (soc_mem_index_max(unit, VLAN_PROTOCOLm) > 0) { 1274 BCM_IF_ERROR_RETURN 1275 (_bcm_esw_port_tab_set(unit, port, 1276 _BCM_CPU_TABS_ETHER, 1277 VLAN_PROTOCOL_DATA_INDEXf, 1278 0)); 1279 } 1280 1281 BCM_IF_ERROR_RETURN 1282 (_bcm_esw_port_tab_set(unit, port, 1283 _BCM_CPU_TABS_ETHER, 1284 FP_PORT_FIELD_SEL_INDEXf, 1285 0)); 1286 BCM_IF_ERROR_RETURN 1287 (_bcm_esw_port_tab_get(unit, port, 1288 PROTOCOL_PKT_INDEXf, 1289 &value)); 1290 BCM_IF_ERROR_RETURN 1291 (_bcm_prot_pkt_ctrl_delete(unit, value)); 1292 } 1293 /* Initialize egress block profile pointer to invalid value */ 1294 BCM_IF_ERROR_RETURN 1295 (bcmi_esw_port_egr_prof_ptr_set(unit, port, -1)); 1296 1297 /********** 1298 * VLAN Action 1299 * soc_feature_vlan_action 1300 */ 1301 BCM_IF_ERROR_RETURN 1302 (_bcm_trx_vlan_port_egress_default_action_delete(unit, port)); 1303 1304 if (!IS_LB_PORT(unit, port)) { 1305 BCM_IF_ERROR_RETURN 1306 (_bcm_port_vlan_prot_index_free(unit, pinfo->vlan_prot_ptr)); 1307 } 1308 1309 /********** 1310 * VLAN TPID reference count 1311 */ 1312 BCM_IF_ERROR_RETURN 1313 (_bcm_td2p_port_outer_tpid_ref_count_update(unit, port, 0)); 1314 1315 /********** 1316 * Init port configuration tables 1317 */ 1318 SOC_PBMP_CLEAR(port_pbmp); 1319 BCM_PBMP_ASSIGN(port_pbmp, PBMP_ALL(unit)); 1320 SOC_PBMP_REMOVE(port_pbmp, PBMP_TDM(unit)); 1321 1322 vd.vlan_tag = BCM_VLAN_NONE; 1323 BCM_PBMP_ASSIGN(vd.port_bitmap, port_pbmp); 1324 BCM_PBMP_ASSIGN(vd.ut_port_bitmap, port_pbmp); 1325 BCM_PBMP_REMOVE(vd.ut_port_bitmap, PBMP_CMIC(unit)); 1326 1327 BCM_IF_ERROR_RETURN 1328 (mbcm_driver[unit]->mbcm_port_cfg_init(unit, port, &vd)); 1329 1330 BCM_IF_ERROR_RETURN(_bcm_td2p_port_bridge_port_init(unit, port, 0)); 1331 1332 BCM_IF_ERROR_RETURN(bcm_port_settings_init(unit, port)); 1333 1334 /********** 1335 * Reset fields 1336 * Deallocate SW memory 1337 */ 1338 BCM_IF_ERROR_RETURN(_bcm_td2p_port_software_free(unit, port)); 1339 1340 return BCM_E_NONE; 1341 } 1342 1343 #ifdef INCLUDE_L3 1344 1345 /* 1346 * Function: 1347 * _bcm_td2p_vfi_membership_change 1348 * Purpose: 1349 * Add/remove a port to/from the vlan_vfi_membership profile at the given 1350 * index. This is mainly used for adding a port to the default profile 1 1351 * for VFI membership. By default, the default porfile should contain all 1352 * port numbers. Normally profile should be accessed through 1353 * soc_profile_mem_xxx functions. 1354 * 1355 * Returns: 1356 * BCM_E_XXX 1357 */ 1358 1359 STATIC int 1360 _bcm_td2p_vfi_membership_change(int unit, int profile_inx,bcm_port_t port, int add) 1361 { 1362 bcm_pbmp_t pbmp; 1363 ing_vlan_vfi_membership_entry_t ing_vlan_vfi; 1364 egr_vlan_vfi_membership_entry_t egr_vlan_vfi; 1365 1366 BCM_PBMP_CLEAR(pbmp); 1367 BCM_IF_ERROR_RETURN(READ_ING_VLAN_VFI_MEMBERSHIPm(unit, 1368 MEM_BLOCK_ANY, profile_inx, &ing_vlan_vfi)); 1369 1370 soc_mem_pbmp_field_get(unit, ING_VLAN_VFI_MEMBERSHIPm, &ing_vlan_vfi, 1371 ING_PORT_BITMAPf, &pbmp); 1372 if (add) { 1373 BCM_PBMP_PORT_ADD(pbmp, port); 1374 } else { 1375 BCM_PBMP_PORT_REMOVE(pbmp, port); 1376 } 1377 soc_mem_pbmp_field_set(unit, ING_VLAN_VFI_MEMBERSHIPm, &ing_vlan_vfi, 1378 ING_PORT_BITMAPf, &pbmp); 1379 BCM_IF_ERROR_RETURN(WRITE_ING_VLAN_VFI_MEMBERSHIPm(unit, 1380 MEM_BLOCK_ALL, profile_inx, &ing_vlan_vfi)); 1381 1382 BCM_PBMP_CLEAR(pbmp); 1383 BCM_IF_ERROR_RETURN(READ_EGR_VLAN_VFI_MEMBERSHIPm(unit, 1384 MEM_BLOCK_ANY, profile_inx, &egr_vlan_vfi)); 1385 1386 soc_mem_pbmp_field_get(unit, EGR_VLAN_VFI_MEMBERSHIPm, &egr_vlan_vfi, 1387 PORT_BITMAPf, &pbmp); 1388 if (add) { 1389 BCM_PBMP_PORT_ADD(pbmp, port); 1390 } else { 1391 BCM_PBMP_PORT_REMOVE(pbmp, port); 1392 } 1393 1394 soc_mem_pbmp_field_set(unit, EGR_VLAN_VFI_MEMBERSHIPm, &egr_vlan_vfi, 1395 PORT_BITMAPf, &pbmp); 1396 BCM_IF_ERROR_RETURN(WRITE_EGR_VLAN_VFI_MEMBERSHIPm(unit, 1397 MEM_BLOCK_ALL, profile_inx, &egr_vlan_vfi)); 1398 return BCM_E_NONE; 1399 } 1400 1401 /* 1402 * Function: 1403 * _bcm_td2p_vfi_membership_port_attach 1404 * Purpose: 1405 * Add a port to the default vfi membership profile 1406 * 1407 * Returns: 1408 * BCM_E_XXX 1409 */ 1410 1411 int 1412 _bcm_td2p_vfi_membership_port_attach(int unit, bcm_port_t port) 1413 { 1414 BCM_IF_ERROR_RETURN(_bcm_td2p_vfi_membership_change(unit,1, port,TRUE)); 1415 return BCM_E_NONE; 1416 } 1417 1418 /* 1419 * Function: 1420 * _bcm_td2p_vfi_membership_port_detach 1421 * Purpose: 1422 * Remove a port from the default vfi membership profile 1423 * 1424 * Returns: 1425 * BCM_E_XXX 1426 */ 1427 1428 int 1429 _bcm_td2p_vfi_membership_port_detach(int unit, bcm_port_t port) 1430 { 1431 BCM_IF_ERROR_RETURN(_bcm_td2p_vfi_membership_change(unit,1, port,FALSE)); 1432 return BCM_E_NONE; 1433 } 1434 #endif /* INCLUDE_L3 */ 1435 1436 /* 1437 * Function: 1438 * _bcm_td2p_port_attach 1439 * Purpose: 1440 * Attach given port to the BCM layer and initialize it 1441 * to its default state. 1442 * Parameters: 1443 * unit - (IN) Unit number. 1444 * port - (IN) Logical port, BCM format. 1445 * Returns: 1446 * BCM_E_XXX 1447 * Note: 1448 * - Assumes port is a valid BCM logical port. 1449 * - Assumes function is called when a new port is added into the system, 1450 * so it is not called during WarmBoot. 1451 * - Assumes BCM PORT module initialization routine has 1452 * been called. 1453 * - Assumes this is NOT called during Warmboot. 1454 */ 1455 STATIC int 1456 _bcm_td2p_port_attach(int unit, bcm_port_t port) 1457 { 1458 int rv = BCM_E_NONE; 1459 #ifndef BCM_VLAN_NO_DEFAULT_ETHER 1460 bcm_pbmp_t pbmp; 1461 #endif 1462 1463 LOG_VERBOSE(BSL_LS_BCM_PORT, 1464 (BSL_META_U(unit, 1465 "BCM Attach unit=%d port=%d(%s)\n"), 1466 unit, port, SOC_PORT_NAME(unit, port))); 1467 1468 /* 1469 * Initialization of port logic in BCM modules 1470 * 1471 * There are order dependencies among the BCM modules. 1472 * This follows the current order of execution in _bcm_modules_init() 1473 * which is well established. 1474 */ 1475 1476 /* PORT */ 1477 rv = _bcm_td2_port_basic_attach(unit, port); 1478 if (BCM_FAILURE(rv)) { 1479 LOG_ERROR(BSL_LS_BCM_PORT, 1480 (BSL_META_U(unit, 1481 "Unable to initialize basic port " 1482 "unit=%d port=%d rv=%d\n"), 1483 unit, port, rv)); 1484 return rv; 1485 } 1486 1487 /* STG */ 1488 rv = bcm_esw_vlan_stp_set(unit, BCM_VLAN_DEFAULT, 1489 port, BCM_STG_STP_FORWARD); 1490 if (BCM_FAILURE(rv)) { 1491 LOG_ERROR(BSL_LS_BCM_PORT, 1492 (BSL_META_U(unit, 1493 "Unable to set port STP for default VLAN " 1494 "unit=%d port=%d rv=%d\n"), 1495 unit, port, rv)); 1496 return rv; 1497 } 1498 1499 /* VLAN */ 1500 #ifndef BCM_VLAN_NO_DEFAULT_ETHER 1501 /* Add ports to default VLAN only if vlan policy allows it */ 1502 BCM_PBMP_CLEAR(pbmp); 1503 BCM_PBMP_PORT_ADD(pbmp, port); 1504 rv = bcm_esw_vlan_port_add(unit, BCM_VLAN_DEFAULT, pbmp, pbmp); 1505 if (BCM_FAILURE(rv)) { 1506 LOG_ERROR(BSL_LS_BCM_PORT, 1507 (BSL_META_U(unit, 1508 "Unable to add port to default VLAN " 1509 "unit=%d port=%d rv=%d\n"), 1510 unit, port, rv)); 1511 return rv; 1512 } 1513 #endif 1514 1515 1516 /* TRUNK */ 1517 rv = _bcm_td2p_port_trunk_port_attach(unit, port); 1518 if (BCM_FAILURE(rv)) { 1519 LOG_ERROR(BSL_LS_BCM_PORT, 1520 (BSL_META_U(unit, 1521 "Unable to initialize port " 1522 "Source Trunk Map table " 1523 "unit=%d port=%d rv=%d\n"), 1524 unit, port, rv)); 1525 return rv; 1526 } 1527 1528 /* LINKSCAN */ 1529 rv = _soc_linkscan_hw_port_init(unit, port); 1530 if (SOC_FAILURE(rv)) { 1531 LOG_ERROR(BSL_LS_BCM_PORT, 1532 (BSL_META_U(unit, 1533 "Unable to initialize port Linkscan " 1534 "unit=%d port=%d rv=%d\n"), 1535 unit, port, rv)); 1536 return rv; 1537 } 1538 1539 /* STACK */ 1540 rv = _bcm_td2p_port_stack_port_attach(unit, port); 1541 if (BCM_FAILURE(rv)) { 1542 LOG_ERROR(BSL_LS_BCM_PORT, 1543 (BSL_META_U(unit, 1544 "Unable to initialize port Stack " 1545 "unit=%d port=%d rv=%d\n"), 1546 unit, port, rv)); 1547 return rv; 1548 } 1549 1550 /* STAT */ 1551 rv = bcmi_td2p_stat_port_attach(unit, port); 1552 if (BCM_FAILURE(rv)) { 1553 LOG_ERROR(BSL_LS_BCM_PORT, 1554 (BSL_META_U(unit, 1555 "Unable to initialize port Stat " 1556 "unit=%d port=%d rv=%d\n"), 1557 unit, port, rv)); 1558 return rv; 1559 } 1560 1561 /* RATE */ 1562 rv = _bcm_td2p_port_rate_port_attach(unit, port); 1563 if (BCM_FAILURE(rv)) { 1564 LOG_ERROR(BSL_LS_BCM_PORT, 1565 (BSL_META_U(unit, 1566 "Unable to initialize port Rate " 1567 "unit=%d port=%d rv=%d\n"), 1568 unit, port, rv)); 1569 return rv; 1570 } 1571 1572 #ifdef BCM_FIELD_SUPPORT 1573 /* FIELD */ 1574 rv = bcm_esw_port_control_set(unit, port, bcmPortControlFilterLookup, 1); 1575 if (BCM_SUCCESS(rv)) { 1576 rv = bcm_esw_port_control_set(unit, port, 1577 bcmPortControlFilterIngress, 1); 1578 } 1579 if (BCM_SUCCESS(rv)) { 1580 rv = bcm_esw_port_control_set(unit, port, 1581 bcmPortControlFilterEgress, 1); 1582 } 1583 if (BCM_FAILURE(rv)) { 1584 LOG_ERROR(BSL_LS_BCM_PORT, 1585 (BSL_META_U(unit, 1586 "Unable to initialize port Field " 1587 "unit=%d port=%d rv=%d\n"), 1588 unit, port, rv)); 1589 return rv; 1590 } 1591 #if defined(BCM_TRX_SUPPORT) 1592 rv = _bcm_field_flex_port_attach(unit, port); 1593 if (BCM_FAILURE(rv)) { 1594 LOG_ERROR(BSL_LS_BCM_PORT, 1595 (BSL_META_U(unit, 1596 "Unable to attach port in Field Port Based Groups" 1597 "unit=%d port=%d rv=%d\n"), 1598 unit, port, rv)); 1599 return rv; 1600 } 1601 #endif 1602 #endif /* BCM_FIELD_SUPPORT */ 1603 1604 /* MIRROR */ 1605 rv = bcmi_esw_mirror_port_attach(unit, port); 1606 if (BCM_FAILURE(rv)) { 1607 LOG_ERROR(BSL_LS_BCM_PORT, 1608 (BSL_META_U(unit, 1609 "Unable to initialize port Mirror " 1610 "unit=%d port=%d rv=%d\n"), 1611 unit, port, rv)); 1612 return rv; 1613 } 1614 1615 #ifdef INCLUDE_L3 1616 /* L3 */ 1617 if (!IS_ST_PORT(unit, port)) { 1618 rv = bcm_esw_port_control_set(unit, port, bcmPortControlIP4, 1); 1619 if (BCM_SUCCESS(rv)) { 1620 rv = bcm_esw_port_control_set(unit, port, bcmPortControlIP6, 1); 1621 } 1622 if (BCM_FAILURE(rv)) { 1623 LOG_ERROR(BSL_LS_BCM_PORT, 1624 (BSL_META_U(unit, 1625 "Unable to enable port L3 " 1626 "unit=%d port=%d rv=%d\n"), 1627 unit, port, rv)); 1628 return rv; 1629 } 1630 } 1631 1632 /* IPMC */ 1633 rv = _bcm_td2p_port_ipmc_port_attach(unit, port); 1634 if (BCM_FAILURE(rv)) { 1635 LOG_ERROR(BSL_LS_BCM_PORT, 1636 (BSL_META_U(unit, 1637 "Unable to enable port IPMC " 1638 "unit=%d port=%d rv=%d\n"), 1639 unit, port, rv)); 1640 return rv; 1641 } 1642 1643 #ifdef BCM_MPLS_SUPPORT 1644 /* MPLS */ 1645 if (!IS_ST_PORT(unit, port)) { 1646 rv = bcm_esw_port_control_set(unit, port, bcmPortControlMpls, 1); 1647 if (BCM_FAILURE(rv)) { 1648 LOG_ERROR(BSL_LS_BCM_PORT, 1649 (BSL_META_U(unit, 1650 "Unable to enable port MPLS " 1651 "unit=%d port=%d rv=%d\n"), 1652 unit, port, rv)); 1653 return rv; 1654 } 1655 } 1656 #endif /* BCM_MPLS_SUPPORT */ 1657 1658 /* MIM */ 1659 if (!IS_ST_PORT(unit, port) && soc_feature(unit, soc_feature_mim)) { 1660 rv = bcm_esw_port_control_set(unit, port, bcmPortControlMacInMac, 1); 1661 if (BCM_FAILURE(rv)) { 1662 LOG_ERROR(BSL_LS_BCM_PORT, 1663 (BSL_META_U(unit, 1664 "Unable to enable port MIM " 1665 "unit=%d port=%d rv=%d\n"), 1666 unit, port, rv)); 1667 return rv; 1668 } 1669 } 1670 1671 /* VFI */ 1672 rv = _bcm_td2p_vfi_membership_port_attach(unit, port); 1673 if (BCM_FAILURE(rv)) { 1674 LOG_ERROR(BSL_LS_BCM_PORT, 1675 (BSL_META_U(unit, 1676 "Unable to add port to default VFI membership " 1677 "unit=%d port=%d rv=%d\n"), 1678 unit, port, rv)); 1679 return rv; 1680 } 1681 #endif /* INCLUDE_L3 */ 1682 1683 /* PFC */ 1684 rv = bcm_esw_port_control_set(unit, port, bcmPortControlPFCPassFrames, 0); 1685 if (BCM_FAILURE(rv)) { 1686 LOG_ERROR(BSL_LS_BCM_PORT, 1687 (BSL_META_U(unit, 1688 "Unable to initialize PFC settings " 1689 "unit=%d port=%d rv=%d\n"), 1690 unit, port, rv)); 1691 return rv; 1692 } 1693 1694 if (SOC_IS_TRIDENT2PLUS(unit)) { 1695 rv = bcm_td2_cosq_default_llfc_profile_attach(unit, port); 1696 if (BCM_FAILURE(rv)) { 1697 LOG_ERROR(BSL_LS_BCM_PORT, 1698 (BSL_META_U(unit, 1699 "Unable to add default entries for PRIO2COS_PROFILE" 1700 "register profile unit=%d port=%d rv=%d\n"), 1701 unit, port, rv)); 1702 return rv; 1703 } 1704 } 1705 1706 return BCM_E_NONE; 1707 } 1708 1709 1710 /* 1711 * Function: 1712 * _bcm_td2p_port_detach 1713 * Purpose: 1714 * Detach given port from the BCM layer and clear any data 1715 * that is normally configured when a port is initialized. 1716 * Parameters: 1717 * unit - (IN) Unit number. 1718 * port - (IN) Logical port, BCM format. 1719 * Returns: 1720 * BCM_E_XXX 1721 * Note: 1722 * - Assumes port is a valid BCM logical port. 1723 * - Assumes this is NOT called during Warmboot. 1724 */ 1725 STATIC int 1726 _bcm_td2p_port_detach(int unit, bcm_port_t port) 1727 { 1728 int rv = BCM_E_NONE; 1729 bcm_pbmp_t pbmp; 1730 1731 LOG_VERBOSE(BSL_LS_BCM_PORT, 1732 (BSL_META_U(unit, 1733 "BCM Detach unit=%d port=%d(%s)\n"), 1734 unit, port, SOC_PORT_NAME(unit, port))); 1735 1736 /* 1737 * Clear of port logic in BCM modules 1738 * 1739 * For the most part, this follows the reverse logic 1740 * of its counter part function _bcm_td2p_port_attach(). 1741 */ 1742 1743 #ifdef INCLUDE_L3 1744 /* MIM */ 1745 if (!IS_ST_PORT(unit, port) && soc_feature(unit, soc_feature_mim)) { 1746 rv = bcm_esw_port_control_set(unit, port, bcmPortControlMacInMac, 0); 1747 if (BCM_FAILURE(rv)) { 1748 LOG_ERROR(BSL_LS_BCM_PORT, 1749 (BSL_META_U(unit, 1750 "Unable to clear port MIM " 1751 "unit=%d port=%d rv=%d\n"), 1752 unit, port, rv)); 1753 return rv; 1754 } 1755 } 1756 1757 #ifdef BCM_MPLS_SUPPORT 1758 /* MPLS */ 1759 if (!IS_ST_PORT(unit, port)) { 1760 rv = bcm_esw_port_control_set(unit, port, bcmPortControlMpls, 0); 1761 if (BCM_FAILURE(rv)) { 1762 LOG_ERROR(BSL_LS_BCM_PORT, 1763 (BSL_META_U(unit, 1764 "Unable to clear port MPLS " 1765 "unit=%d port=%d rv=%d\n"), 1766 unit, port, rv)); 1767 return rv; 1768 } 1769 } 1770 #endif /* BCM_MPLS_SUPPORT */ 1771 1772 /* IPMC */ 1773 rv = _bcm_td2p_port_ipmc_port_detach(unit, port); 1774 if (BCM_FAILURE(rv)) { 1775 LOG_ERROR(BSL_LS_BCM_PORT, 1776 (BSL_META_U(unit, 1777 "Unable to clear port IPMC " 1778 "unit=%d port=%d rv=%d\n"), 1779 unit, port, rv)); 1780 return rv; 1781 } 1782 1783 /* L3 */ 1784 if (!IS_ST_PORT(unit, port)) { 1785 rv = bcm_esw_port_control_set(unit, port, bcmPortControlIP4, 0); 1786 if (BCM_SUCCESS(rv)) { 1787 rv = bcm_esw_port_control_set(unit, port, bcmPortControlIP6, 0); 1788 } 1789 if (BCM_FAILURE(rv)) { 1790 LOG_ERROR(BSL_LS_BCM_PORT, 1791 (BSL_META_U(unit, 1792 "Unable to clear port L3 " 1793 "unit=%d port=%d rv=%d\n"), 1794 unit, port, rv)); 1795 return rv; 1796 } 1797 } 1798 #endif /* INCLUDE_L3 */ 1799 1800 /* MIRROR */ 1801 rv = bcmi_esw_mirror_port_detach(unit, port); 1802 if (BCM_FAILURE(rv)) { 1803 LOG_ERROR(BSL_LS_BCM_PORT, 1804 (BSL_META_U(unit, 1805 "Unable to clear port Mirror " 1806 "unit=%d port=%d rv=%d\n"), 1807 unit, port, rv)); 1808 return rv; 1809 } 1810 1811 #ifdef BCM_FIELD_SUPPORT 1812 /* FIELD */ 1813 rv = bcm_esw_port_control_set(unit, port, bcmPortControlFilterLookup, 0); 1814 if (BCM_SUCCESS(rv)) { 1815 rv = bcm_esw_port_control_set(unit, port, 1816 bcmPortControlFilterIngress, 0); 1817 } 1818 if (BCM_SUCCESS(rv)) { 1819 rv = bcm_esw_port_control_set(unit, port, 1820 bcmPortControlFilterEgress, 0); 1821 } 1822 if (BCM_FAILURE(rv)) { 1823 LOG_ERROR(BSL_LS_BCM_PORT, 1824 (BSL_META_U(unit, 1825 "Unable clear port Field " 1826 "unit=%d port=%d rv=%d\n"), 1827 unit, port, rv)); 1828 return rv; 1829 } 1830 #if defined(BCM_TRX_SUPPORT) 1831 rv = _bcm_field_flex_port_detach(unit, port); 1832 if (BCM_FAILURE(rv)) { 1833 LOG_ERROR(BSL_LS_BCM_PORT, 1834 (BSL_META_U(unit, 1835 "Unable to clear port in Field Port Based Groups" 1836 "unit=%d port=%d rv=%d\n"), 1837 unit, port, rv)); 1838 return rv; 1839 } 1840 #endif 1841 #endif /* BCM_FIELD_SUPPORT */ 1842 1843 /* RATE */ 1844 rv = _bcm_td2p_port_rate_port_detach(unit, port); 1845 if (BCM_FAILURE(rv)) { 1846 LOG_ERROR(BSL_LS_BCM_PORT, 1847 (BSL_META_U(unit, 1848 "Unable to clear port Rate " 1849 "unit=%d port=%d rv=%d\n"), 1850 unit, port, rv)); 1851 return rv; 1852 } 1853 1854 /* STAT*/ 1855 rv = bcmi_td2p_stat_port_detach(unit, port); 1856 if (BCM_FAILURE(rv)) { 1857 LOG_ERROR(BSL_LS_BCM_PORT, 1858 (BSL_META_U(unit, 1859 "Unable to clear port Stat " 1860 "unit=%d port=%d rv=%d\n"), 1861 unit, port, rv)); 1862 return rv; 1863 } 1864 1865 /* STACK */ 1866 rv = _bcm_td2p_port_stack_port_detach(unit, port); 1867 if (BCM_FAILURE(rv)) { 1868 LOG_ERROR(BSL_LS_BCM_PORT, 1869 (BSL_META_U(unit, 1870 "Unable to clear port Stack " 1871 "unit=%d port=%d rv=%d\n"), 1872 unit, port, rv)); 1873 return rv; 1874 } 1875 1876 /* TRUNK */ 1877 rv = _bcm_td2p_port_trunk_port_detach(unit, port); 1878 if (BCM_FAILURE(rv)) { 1879 LOG_ERROR(BSL_LS_BCM_PORT, 1880 (BSL_META_U(unit, 1881 "Unable to clear port Source Trunk Map table " 1882 "unit=%d port=%d rv=%d\n"), 1883 unit, port, rv)); 1884 return rv; 1885 } 1886 1887 /* VLAN */ 1888 BCM_PBMP_CLEAR(pbmp); 1889 BCM_PBMP_PORT_ADD(pbmp, port); 1890 rv = bcm_esw_vlan_port_remove(unit, BCM_VLAN_DEFAULT, pbmp); 1891 if (BCM_FAILURE(rv)) { 1892 LOG_ERROR(BSL_LS_BCM_PORT, 1893 (BSL_META_U(unit, 1894 "Unable to remove port from default VLAN " 1895 "unit=%d port=%d rv=%d\n"), 1896 unit, port, rv)); 1897 return rv; 1898 } 1899 1900 /* STG */ 1901 rv = bcm_esw_vlan_stp_set(unit, BCM_VLAN_DEFAULT, 1902 port, BCM_STG_STP_DISABLE); 1903 if (BCM_FAILURE(rv)) { 1904 LOG_ERROR(BSL_LS_BCM_PORT, 1905 (BSL_META_U(unit, 1906 "Unable to clear port STP for default VLAN " 1907 "unit=%d port=%d rv=%d\n"), 1908 unit, port, rv)); 1909 return rv; 1910 } 1911 1912 /* PORT */ 1913 rv = _bcm_td2_port_basic_detach(unit, port); 1914 if (BCM_FAILURE(rv)) { 1915 LOG_ERROR(BSL_LS_BCM_PORT, 1916 (BSL_META_U(unit, 1917 "Unable to detach basic port " 1918 "unit=%d port=%d rv=%d\n"), 1919 unit, port, rv)); 1920 return rv; 1921 } 1922 1923 #ifdef INCLUDE_L3 1924 /* VFI */ 1925 rv = _bcm_td2p_vfi_membership_port_detach(unit, port); 1926 if (BCM_FAILURE(rv)) { 1927 LOG_ERROR(BSL_LS_BCM_PORT, 1928 (BSL_META_U(unit, 1929 "Unable to clear port in default VFI membership " 1930 "unit=%d port=%d rv=%d\n"), 1931 unit, port, rv)); 1932 return rv; 1933 } 1934 #endif /* INCLUDE_L3 */ 1935 /* PFC */ 1936 if (SOC_IS_TRIDENT2PLUS(unit)) { 1937 rv = bcm_td2_cosq_llfc_profile_detach(unit, port); 1938 if (BCM_FAILURE(rv)) { 1939 LOG_ERROR(BSL_LS_BCM_PORT, 1940 (BSL_META_U(unit, 1941 "Unable to delete default entries for PRIO2COS_PROFILE" 1942 "register profile unit=%d port=%d rv=%d\n"), 1943 unit, port, rv)); 1944 return rv; 1945 } 1946 } 1947 1948 return BCM_E_NONE; 1949 } 1950 1951 /* 1952 * Function: 1953 * bcm_esw_td2p_flexport_port_attach 1954 * Purpose: 1955 * External wrapper for _bcm_td2p_port_attach 1956 */ 1957 int 1958 bcm_esw_td2p_flexport_port_attach(int unit, bcm_port_t port) 1959 { 1960 return _bcm_td2p_port_attach(unit, port); 1961 } 1962 1963 1964 /* 1965 * Function: 1966 * bcm_esw_td2p_flexport_port_detach 1967 * Purpose: 1968 * External wrapper for _bcm_td2p_port_detach 1969 */ 1970 int 1971 bcm_esw_td2p_flexport_port_detach(int unit, bcm_port_t port) 1972 { 1973 return _bcm_td2p_port_detach(unit, port); 1974 } 1975 1976 1977 /* 1978 * Function: 1979 * _bcm_td2p_port_resource_attach 1980 * Purpose: 1981 * Attach ports to the BCM layer and initialize them 1982 * to the default state. 1983 * 1984 * Parameters: 1985 * unit - (IN) Unit number. 1986 * nport - (IN) Number of elements in array resource. 1987 * resource - (IN) Port Resource FlexPort configuration. 1988 * Returns: 1989 * BCM_E_XXX 1990 * Notes: 1991 * - Assumes caller have detached any ports that will be attached 1992 * in this routine. 1993 * - Assumes this is NOT called during Warmboot. 1994 * - Set current MY_MODID for all newly attached ports. 1995 */ 1996 STATIC int 1997 _bcm_td2p_port_resource_attach(int unit, 1998 int nport, 1999 bcm_td2p_port_resource_t *resource) 2000 { 2001 int rv = BCM_E_NONE; 2002 bcm_td2p_port_resource_t *pr; 2003 int i, my_modid; 2004 2005 LOG_VERBOSE(BSL_LS_BCM_PORT, 2006 (BSL_META_U(unit, 2007 "--- BCM Attach ---\n"))); 2008 2009 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 2010 2011 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2012 if (pr->flags & SOC_PORT_RESOURCE_ATTACH) { 2013 rv = _bcm_td2p_port_attach(unit, pr->port); 2014 if (BCM_FAILURE(rv)) { 2015 LOG_ERROR(BSL_LS_BCM_PORT, 2016 (BSL_META_U(unit, 2017 "Error: Unable to attach BCM port " 2018 "unit=%d port=%d rv=%d\n"), 2019 unit, pr->port, rv)); 2020 return rv; 2021 } 2022 } 2023 } 2024 2025 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_set(unit, my_modid)); 2026 2027 return BCM_E_NONE; 2028 } 2029 2030 2031 /* 2032 * Function: 2033 * _bcm_td2p_port_resource_detach 2034 * Purpose: 2035 * Detach ports from the BCM layer. 2036 * 2037 * It clears any HW or SW state that was programmed 2038 * by the SDK initialization routines. It does NOT clear 2039 * references to logical ports that have been programmed by the 2040 * application. Applications are responsible for doing that. 2041 * 2042 * Parameters: 2043 * unit - (IN) Unit number. 2044 * nport - (IN) Number of elements in array resource. 2045 * resource - (IN) Port Resource FlexPort configuration. 2046 * Returns: 2047 * BCM_E_XXX 2048 * Notes: 2049 * - Assumes this is NOT called during Warmboot. 2050 */ 2051 STATIC int 2052 _bcm_td2p_port_resource_detach(int unit, 2053 int nport, 2054 bcm_td2p_port_resource_t *resource) 2055 { 2056 int rv = BCM_E_NONE; 2057 bcm_td2p_port_resource_t *pr; 2058 int i; 2059 2060 LOG_VERBOSE(BSL_LS_BCM_PORT, 2061 (BSL_META_U(unit, 2062 "--- BCM Detach ---\n"))); 2063 2064 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2065 if (pr->flags & SOC_PORT_RESOURCE_DETACH) { 2066 rv = _bcm_td2p_port_detach(unit, pr->port); 2067 if (BCM_FAILURE(rv)) { 2068 LOG_ERROR(BSL_LS_BCM_PORT, 2069 (BSL_META_U(unit, 2070 "Error: Unable to detach BCM port " 2071 "unit=%d port=%d rv=%d\n"), 2072 unit, pr->port, rv)); 2073 return rv; 2074 } 2075 } 2076 } 2077 2078 return BCM_E_NONE; 2079 } 2080 2081 2082 /* 2083 * Function: 2084 * _bcm_td2p_port_resource_resolve 2085 * Purpose: 2086 * Convert logical port number GPORT to BCM local port format and 2087 * validate port numbers: 2088 * - Logical and physical port numbers are within the valid range. 2089 * - Ports must not be CPU or Loopback ports. 2090 * Parameters: 2091 * unit - (IN) Unit number. 2092 * nport - (IN) Number of elements in array resource. 2093 * resource - (IN/OUT) Port resource configuration array. 2094 * Returns: 2095 * BCM_E_XXX 2096 * Note: 2097 * - Assumes caller has lock. 2098 * - Resource is not NULL. 2099 */ 2100 STATIC int 2101 _bcm_td2p_port_resource_resolve(int unit, 2102 int nport, 2103 bcm_td2p_port_resource_t *resource) 2104 { 2105 int i; 2106 bcm_td2p_port_resource_t *pr; 2107 soc_info_t *si = &SOC_INFO(unit); 2108 2109 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2110 2111 /* Check that logical port number is addressable and convert */ 2112 BCM_IF_ERROR_RETURN 2113 (bcmi_xgs5_port_addressable_local_get(unit, 2114 pr->port, 2115 &pr->port)); 2116 2117 /* 2118 * Check that logical port number is valid for TD2+ 2119 * (above check is generic) 2120 */ 2121 SOC_IF_ERROR_RETURN 2122 (soc_td2p_port_addressable(unit, pr->port)); 2123 2124 /* Check that physical port is within the valid range */ 2125 if (pr->physical_port != -1) { 2126 SOC_IF_ERROR_RETURN 2127 (soc_td2p_phy_port_addressable(unit, pr->physical_port)); 2128 } 2129 2130 /* Check that ports, logical and physical, are not a management port */ 2131 if ((si->port_l2p_mapping[pr->port] == TD2P_PHY_PORT_CPU) || 2132 (si->port_l2p_mapping[pr->port] == TD2P_PHY_PORT_LB) || 2133 (pr->physical_port == TD2P_PHY_PORT_CPU) || 2134 (pr->physical_port == TD2P_PHY_PORT_LB) || 2135 SOC_PBMP_MEMBER(si->management_pbm, pr->port)) { 2136 LOG_ERROR(BSL_LS_BCM_PORT, 2137 (BSL_META_U(unit, 2138 "Port cannot be CPU, LB, or management " 2139 "port " 2140 "unit=%d port=%d\n"), 2141 unit, pr->port)); 2142 return BCM_E_PORT; 2143 } 2144 } 2145 2146 return BCM_E_NONE; 2147 } 2148 2149 2150 /* 2151 * Function: 2152 * _bcm_td2p_port_resource_input_validate 2153 * Purpose: 2154 * Validate function input requirements. 2155 * 2156 * This routine checks for function semantics and guidelines 2157 * from the API perspective: 2158 * - Check the order of elements in array, 'delete' operations must 2159 * be placed first in array. 2160 * - Ports must not be CPU or Loopback ports. 2161 * - Ports must be disabled. 2162 * - Ports linkscan mode must be NONE. 2163 * Parameters: 2164 * unit - (IN) Unit number. 2165 * nport - (IN) Number of elements in array resource. 2166 * resource - (IN/OUT) Port resource configuration array. 2167 * Returns: 2168 * BCM_E_XXX 2169 * Note: 2170 * - Assumes caller has lock. 2171 * - Resource is not NULL. 2172 * - Assumes port values has been validated. 2173 */ 2174 STATIC int 2175 _bcm_td2p_port_resource_input_validate(int unit, 2176 int nport, 2177 bcm_td2p_port_resource_t *resource) 2178 { 2179 int i; 2180 bcm_td2p_port_resource_t *pr; 2181 int delete = 1; 2182 int enable; 2183 soc_info_t *si = &SOC_INFO(unit); 2184 2185 2186 /* Check array order and port state disable */ 2187 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2188 2189 /* Skip check for speed change */ 2190 if (pr->flags & SOC_PORT_RESOURCE_SPEED) { 2191 continue; 2192 } 2193 2194 /* Check that delete operations are first */ 2195 if (pr->physical_port != -1) { /* First non-delete found */ 2196 delete = 0; 2197 } else if ((pr->physical_port == -1) && !delete) { 2198 LOG_ERROR(BSL_LS_BCM_PORT, 2199 (BSL_META_U(unit, 2200 "Delete operations must be " 2201 "first in array\n"))); 2202 return BCM_E_CONFIG; 2203 } 2204 2205 if ((pr->encap != BCM_PORT_ENCAP_IEEE) && 2206 (pr->encap != BCM_PORT_ENCAP_HIGIG2)) { 2207 LOG_ERROR(BSL_LS_BCM_PORT, 2208 (BSL_META_U(unit, 2209 "Encap modes can only be IEEE or HIGIG2 " 2210 "unit=%d port=%d\n"), 2211 unit, pr->port)); 2212 return BCM_E_CONFIG; 2213 } 2214 2215 /* Skip ports that are not currently defined */ 2216 if (si->port_l2p_mapping[pr->port] == -1) { 2217 continue; 2218 } 2219 2220 /* Check that ports are disabled */ 2221 BCM_IF_ERROR_RETURN 2222 (bcm_esw_port_enable_get(unit, pr->port, &enable)); 2223 if (enable) { 2224 LOG_ERROR(BSL_LS_BCM_PORT, 2225 (BSL_META_U(unit, 2226 "Port %d needs to be disabled\n"), 2227 pr->port)); 2228 return BCM_E_BUSY; 2229 } 2230 2231 /* 2232 * Check that ports to be 'detached' do not 2233 * have linkscan mode set. See _bcm_td2p_port_resource_pmap_get(). 2234 */ 2235 if (pr->flags & SOC_PORT_RESOURCE_DETACH) { 2236 if (bcm_esw_linkscan_enable_port_get(unit, pr->port) != 2237 BCM_E_DISABLED) { 2238 LOG_ERROR(BSL_LS_BCM_PORT, 2239 (BSL_META_U(unit, 2240 "Linkscan mode needs to be " 2241 "disabled on ports to be detached, " 2242 "port=%d\n"), 2243 pr->port)); 2244 return BCM_E_BUSY; 2245 } 2246 } 2247 } 2248 2249 return BCM_E_NONE; 2250 } 2251 2252 2253 /* 2254 * Function: 2255 * _bcm_td2p_port_resource_pmap_get 2256 * Purpose: 2257 * Determine the type of port mapping changes, if any, 2258 * as a result of the FlexPort operation. In addition, it 2259 * determines whether the port needs to go through the attach 2260 * and/or detach process. 2261 * 2262 * All ports that are being flexed will be detached except for those 2263 * that will become inactive (this is only for legacy mode). 2264 * All ports that are active after flexed are always attached (this is 2265 * for new and legacy mode). 2266 * 2267 * When a port is 'marked' as 'delete' (physical port is -1), 2268 * this does not mean the logical port will be destroyed. Depending 2269 * on the rest of the information in the array, the port mapping 2270 * may be the same, remapped, or it may no longer exist after FlexPort. 2271 * 2272 * Likewise, when a valid port mapping is given, the port may 2273 * not be necessarily new. 2274 * 2275 * Example: 2276 * 2277 * Main FlexPort array ('resource') (application input) 2278 * L1 --> -1 (current mapped to P1), mapping is SAME 2279 * L2 --> -1 (current mapped to P2), mapping is REMAP 2280 * L3 --> -1 (current mapped to P3), mapping is DESTROY 2281 * L1 --> P1 , mapping is SAME 2282 * L2 --> P5 , mapping is REMAP 2283 * L9 --> P9 , mapping is NEW 2284 * 2285 * Parameters: 2286 * unit - (IN) Unit number. 2287 * nport - (IN) Number of elements in array resource. 2288 * resource - (IN/OUT) Port Resource FlexPort configuration. 2289 * Returns: 2290 * SOC_E_XXX 2291 * Notes: 2292 * Assumes all 'delete' elements are first in array. 2293 */ 2294 STATIC int 2295 _bcm_td2p_port_resource_pmap_get(int unit, 2296 int nport, bcm_td2p_port_resource_t *resource) 2297 { 2298 int i; 2299 int j; 2300 bcm_td2p_port_resource_t *pr; 2301 soc_info_t *si = &SOC_INFO(unit); 2302 2303 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2304 2305 if (pr->physical_port == -1) { 2306 /* 2307 * Find if port is given in later elements. 2308 * If so, check if port is remapped. 2309 * If not found, port is marked to be destroyed 2310 * (port will no longer exist after FlexPort) 2311 * 2312 * Note that all the 'delete' ports must always first 2313 * in array. 2314 */ 2315 for (j = i; j < nport; j++) { 2316 if (resource[j].physical_port == -1) { 2317 continue; 2318 } 2319 if (resource[j].port == pr->port) { /* Found */ 2320 /* Check if mapping is same */ 2321 if (resource[j].physical_port != 2322 si->port_l2p_mapping[pr->port]) { 2323 pr->flags |= SOC_PORT_RESOURCE_REMAP; 2324 } 2325 break; 2326 } 2327 } 2328 2329 if (j >= nport) { /* Not found */ 2330 pr->flags |= SOC_PORT_RESOURCE_DESTROY; 2331 2332 } 2333 2334 /* 2335 * Detach only if the port is not becoming inactive (legacy). 2336 * 2337 * A port that is becoming inactive after flex is indicated 2338 * when both of the following flags are set: 2339 * DESTROY 2340 * I_MAP 2341 */ 2342 if (!(pr->flags & SOC_PORT_RESOURCE_DESTROY) || 2343 !(pr->flags & SOC_PORT_RESOURCE_I_MAP)) { 2344 pr->flags |= SOC_PORT_RESOURCE_DETACH; 2345 } 2346 2347 } else { 2348 2349 /* 2350 * Check if logical port is new (port does exist), or 2351 * port is being remapped. 2352 */ 2353 if (si->port_l2p_mapping[pr->port] == -1) { 2354 pr->flags |= SOC_PORT_RESOURCE_NEW; 2355 } else if (pr->physical_port != si->port_l2p_mapping[pr->port]) { 2356 pr->flags |= SOC_PORT_RESOURCE_REMAP; 2357 } 2358 2359 /* All active ports after flexed are always attached */ 2360 pr->flags |= SOC_PORT_RESOURCE_ATTACH; 2361 } 2362 2363 } 2364 2365 return BCM_E_NONE; 2366 } 2367 2368 2369 /* 2370 * Function: 2371 * _bcm_td2p_port_resource_op_get 2372 * Purpose: 2373 * Get the type of FlexPort operations/changes: 2374 * none, port-mapping, lanes, speed, encap. 2375 * 2376 * Some operations only need speed or encap changes. In this 2377 * case, the actual FlexPort operation is not necessary and 2378 * only calls to set to speed and/or encap mode are made. 2379 * 2380 * Parameters: 2381 * unit - (IN) Unit number. 2382 * nport - (IN) Number of elements in array resource. 2383 * resource - (IN) Port resource configuration array. 2384 * op - (OUT) FlexPort operation BCM_TD2P_PORT_RESOURCE_OP_... 2385 * Returns: 2386 * BCM_E_XXX 2387 * Note: 2388 * Assumes caller has lock. 2389 * Resource is not NULL. 2390 * Logical port in 'resource' is in BCM port format (non GPORT). 2391 */ 2392 STATIC int 2393 _bcm_td2p_port_resource_op_get(int unit, 2394 int nport, bcm_td2p_port_resource_t *resource, 2395 int *op) 2396 { 2397 int i; 2398 bcm_td2p_port_resource_t *pr; 2399 soc_info_t *si = &SOC_INFO(unit); 2400 int speed = 0; 2401 int encap = 0; 2402 2403 *op = BCM_TD2P_PORT_RESOURCE_OP_NONE; 2404 2405 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2406 2407 /* Check port speed */ 2408 if (pr->flags & SOC_PORT_RESOURCE_SPEED) { 2409 /* 2410 * NOTE: speed_set sequence 2411 * 2412 * pr->flags & SOC_PORT_RESOURCE_SPEED is set by speed_set API. 2413 * No logical-physical port mapping changes. 2414 * OP_PMAP flag doesn't need to be set in this case. 2415 * _bcm_td2p_port_resource_speed_execute will be called. 2416 */ 2417 *op |= BCM_TD2P_PORT_RESOURCE_OP_SPEED; 2418 LOG_VERBOSE(BSL_LS_BCM_PORT, 2419 (BSL_META_U(unit, 2420 "Speed change detected: " 2421 "logical=%d physical=%d\n"), 2422 pr->port, pr->physical_port)); 2423 continue; 2424 } 2425 2426 /* Check port mapping change */ 2427 if (pr->flags & 2428 (SOC_PORT_RESOURCE_NEW | SOC_PORT_RESOURCE_DESTROY | 2429 SOC_PORT_RESOURCE_REMAP)) { 2430 *op |= BCM_TD2P_PORT_RESOURCE_OP_PMAP; 2431 2432 LOG_VERBOSE(BSL_LS_BCM_PORT, 2433 (BSL_META_U(unit, 2434 "Port map change detected: " 2435 "%s %s %s l=%d p=%d\n"), 2436 (pr->flags & SOC_PORT_RESOURCE_NEW) ? "new" : "", 2437 (pr->flags & SOC_PORT_RESOURCE_DESTROY) ? 2438 "destroy" : "", 2439 (pr->flags & SOC_PORT_RESOURCE_REMAP) ? "remap" : "", 2440 pr->port, pr->physical_port)); 2441 } 2442 2443 /* Skip ports that are being deleted or not defined */ 2444 if ((pr->physical_port == -1) || 2445 (si->port_l2p_mapping[pr->port] == -1)) { 2446 continue; 2447 } 2448 2449 /* 2450 * NOTE: Execute full flex operation if speed is different 2451 */ 2452 if (!(*op & BCM_TD2P_PORT_RESOURCE_OP_SPEED)) { 2453 BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, pr->port, &speed)); 2454 if (pr->speed != speed) { 2455 *op |= BCM_TD2P_PORT_RESOURCE_OP_PMAP; 2456 } 2457 } 2458 2459 /* Check port lanes */ 2460 if (!(*op & BCM_TD2P_PORT_RESOURCE_OP_LANES)) { 2461 if (pr->lanes != si->port_num_lanes[pr->port]) { 2462 *op |= BCM_TD2P_PORT_RESOURCE_OP_LANES; 2463 } 2464 } 2465 2466 /* Check port encap */ 2467 if (!(*op & BCM_TD2P_PORT_RESOURCE_OP_ENCAP)) { 2468 BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, pr->port, &encap)); 2469 if (pr->encap != encap) { 2470 *op |= BCM_TD2P_PORT_RESOURCE_OP_ENCAP; 2471 } 2472 } 2473 2474 /* If all are set, no more checking is necessary */ 2475 if (*op == BCM_TD2P_PORT_RESOURCE_OP_ALL) { 2476 break; 2477 } 2478 } 2479 2480 return BCM_E_NONE; 2481 } 2482 2483 2484 /* 2485 * Function: 2486 * _bcm_td2p_port_resource_loopback_clear 2487 * Purpose: 2488 * Clear the loopback mode for the given set of ports. 2489 * 2490 * Parameters: 2491 * unit - (IN) Unit number. 2492 * nport - (IN) Number of elements in array resource. 2493 * resource - (IN) Port Resource FlexPort configuration. 2494 * Returns: 2495 * SOC_E_XXX 2496 * Notes: 2497 * Assumes all 'delete' elements are first in array. 2498 */ 2499 STATIC int 2500 _bcm_td2p_port_resource_loopback_clear(int unit, 2501 int nport, 2502 bcm_td2p_port_resource_t *resource) 2503 { 2504 int i; 2505 int loopback; 2506 bcm_td2p_port_resource_t *pr; 2507 2508 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2509 if (pr->physical_port == -1) { 2510 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_get(unit, 2511 pr->port, &loopback)); 2512 if (loopback != BCM_PORT_LOOPBACK_NONE) { 2513 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_set(unit, 2514 pr->port, 2515 BCM_PORT_LOOPBACK_NONE)); 2516 } 2517 } 2518 } 2519 2520 return BCM_E_NONE; 2521 2522 } 2523 2524 /* 2525 * Function: 2526 * _bcm_td2p_port_soc_resource_validate 2527 * Purpose: 2528 * Perform soc resource validation. 2529 * 2530 * Parameters: 2531 * unit - (IN) Unit number. 2532 * nport - (IN) Number of elements in array resource. 2533 * resource - (IN) Port resource configuration array. 2534 * Returns: 2535 * BCM_E_XXX 2536 * Note: 2537 * Assumes caller has lock. 2538 * Assumes BCM data has been validated (basic API semantics) 2539 */ 2540 STATIC int 2541 _bcm_td2p_port_soc_resource_validate(int unit, 2542 int nport, bcm_td2p_port_resource_t *resource) 2543 { 2544 int rv; 2545 int i; 2546 soc_port_resource_t *soc_resource; 2547 2548 soc_resource = sal_alloc(sizeof(soc_port_resource_t) * nport, 2549 "port_resource"); 2550 if (soc_resource == NULL) { 2551 LOG_ERROR(BSL_LS_BCM_PORT, 2552 (BSL_META_U(unit, 2553 "Unable to allocate memory for SOC FlexPort " 2554 "array\n"))); 2555 return BCM_E_MEMORY; 2556 } 2557 2558 /* Clear data structure */ 2559 sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport); 2560 2561 /* Copy initial information */ 2562 for (i = 0; i < nport; i++) { 2563 soc_resource[i].flags = resource[i].flags; 2564 soc_resource[i].logical_port = resource[i].port; 2565 soc_resource[i].physical_port = resource[i].physical_port; 2566 soc_resource[i].speed = resource[i].speed; 2567 soc_resource[i].num_lanes = resource[i].lanes; 2568 soc_resource[i].encap = resource[i].encap; 2569 } 2570 2571 rv = soc_td2p_port_resource_validate(unit, nport, soc_resource); 2572 if (SOC_FAILURE(rv)) { 2573 sal_free(soc_resource); 2574 return rv; 2575 } 2576 2577 sal_free(soc_resource); 2578 2579 return rv; 2580 } 2581 2582 /* 2583 * Function: 2584 * _bcm_td2p_port_resource_speed_execute 2585 * Purpose: 2586 * Perform a speed set operation. 2587 * This includes speed change only 2588 * 2589 * Parameters: 2590 * unit - (IN) Unit number. 2591 * nport - (IN) Number of elements in array resource. 2592 * resource - (IN) Port resource configuration array. 2593 * Returns: 2594 * BCM_E_XXX 2595 * Note: 2596 * Assumes caller has lock. 2597 * Assumes BCM data has been validated (basic API semantics) 2598 * 2599 * Details: 2600 * This function is pretty similar as _bcm_td2p_port_resource_execute. 2601 * But speed set doesn't change logical-physical port mapping. 2602 * So this function should skip detach, attach function calls. 2603 * _bcm_td2p_port_resource_detach 2604 * _bcm_td2p_port_resource_attach 2605 * Also this calls soc_td2p_port_resource_configure with 2606 * the flag:SOC_PORT_RESOURCE_CONFIGURE_SPEED_SET to make slightly 2607 * different sequence from full flex operation. 2608 */ 2609 STATIC int 2610 _bcm_td2p_port_resource_speed_execute(int unit, 2611 int nport, bcm_td2p_port_resource_t *resource) 2612 { 2613 int rv; 2614 int i; 2615 soc_port_resource_t *soc_resource; 2616 2617 soc_resource = sal_alloc(sizeof(soc_port_resource_t) * nport, 2618 "port_resource"); 2619 if (soc_resource == NULL) { 2620 LOG_ERROR(BSL_LS_BCM_PORT, 2621 (BSL_META_U(unit, 2622 "Unable to allocate memory for SOC FlexPort " 2623 "array\n"))); 2624 return BCM_E_MEMORY; 2625 } 2626 2627 /* Clear data structure */ 2628 sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport); 2629 2630 /* Copy initial information */ 2631 for (i = 0; i < nport; i++) { 2632 soc_resource[i].flags = resource[i].flags; 2633 soc_resource[i].logical_port = resource[i].port; 2634 soc_resource[i].physical_port = resource[i].physical_port; 2635 soc_resource[i].speed = resource[i].speed; 2636 soc_resource[i].num_lanes = resource[i].lanes; 2637 soc_resource[i].encap = resource[i].encap; 2638 } 2639 2640 rv = soc_td2p_port_resource_validate(unit, nport, soc_resource); 2641 if (SOC_FAILURE(rv)) { 2642 sal_free(soc_resource); 2643 return rv; 2644 } 2645 2646 /* SOC Port Resource Configure */ 2647 rv = soc_td2p_port_resource_configure(unit, nport, soc_resource, 2648 SOC_PORT_RESOURCE_CONFIGURE_SPEED_ONLY); 2649 2650 if (BCM_FAILURE(rv)) { 2651 LOG_ERROR(BSL_LS_BCM_PORT, 2652 (BSL_META_U(unit, 2653 "Changes to device may have been partially " 2654 "executed. System may be unstable.\n"))); 2655 } 2656 2657 sal_free(soc_resource); 2658 2659 return rv; 2660 } 2661 2662 /* 2663 * Function: 2664 * _bcm_td2p_port_resource_execute 2665 * Purpose: 2666 * Perform a FlexPort operation. 2667 * This includes changes that involve: 2668 * - Logical to physical port mapping 2669 * - Speed 2670 * - Number of PHY lanes 2671 * 2672 * Parameters: 2673 * unit - (IN) Unit number. 2674 * nport - (IN) Number of elements in array resource. 2675 * resource - (IN) Port resource configuration array. 2676 * Returns: 2677 * BCM_E_XXX 2678 * Note: 2679 * Assumes caller has lock. 2680 * Assumes BCM data has been validated (basic API semantics) 2681 * 2682 * Details: 2683 * 2684 * Port Mapping 2685 * ------------ 2686 * A logical to physical port mapping is given as part of the port resource 2687 * array. This can lead to the following operations: 2688 * - Port Mapping Delete (or clear) 2689 * This is indicated when the physical port is set to (-1) and 2690 * the port to be flexed is considered an 'old' port. 2691 * The logical port in the array entry must always be valid. 2692 * A 'delete' may result in the following actions for a port mapping: 2693 * (1) Destroyed 2694 * (2) Same 2695 * (3) Remapped 2696 * 2697 * - Port Mapping Add (or set) 2698 * This is indicated when the physical port is set to a valid 2699 * physical port number (>=0). 2700 * The logical port in the array entry must always be valid. 2701 * An 'add' may result in the following actions for a port mapping: 2702 * (1) New 2703 * (2) Same 2704 * (3) Remapped 2705 * 2706 * Destroyed: Logical port no longer exist after FlexPort. 2707 * Remapped: Logical port will continue to exist after FlexPort 2708 * but is mapped to a different physical port. 2709 * New: Logical port did not exist before FlexPort. 2710 * Same: Logical to physical port mapping remains the same. 2711 */ 2712 STATIC int 2713 _bcm_td2p_port_resource_execute(int unit, 2714 int nport, bcm_td2p_port_resource_t *resource, 2715 int op) 2716 { 2717 int rv; 2718 int i; 2719 int flag; 2720 soc_port_resource_t *soc_resource; 2721 2722 /* 2723 * Main FlexPort Sequence 2724 * 2725 * - SOC Validation: 2726 * + More validation takes place in the SOC layer. 2727 * + These check for abilities and configurations based on 2728 * the physical aspects of the device. 2729 * 2730 * NOTE: Up to this point, no changes has taken place in SW 2731 * data structures or HW. 2732 * From this point forward, HW and SW data will be modified, 2733 * any errors will leave the system unstabled. 2734 * 2735 * - Clear any port related settings in BCM layer as needed. 2736 * 2737 * - Detach 'old' ports from BCM layer: 2738 * + These are all ports to be cleared/deleted (indicated by physical 2739 * port -1), EXCEPT those that will become inactive after the 2740 * FlexPort operation (this is only true with legacy API). 2741 * + The port state should be the same as the state of a 2742 * port that was never configured during SDK initialization. 2743 * + This involves SW and HW changes. 2744 * 2745 * - SOC Port Resource Configure: 2746 * Takes place in the SOC layer. 2747 * It consists primarliy of these steps: 2748 * + Delete ports in SOC layer (SOC_INFO SW, HW update). 2749 * + Add ports in SOC layer (SOC_INFO SW, HW update). 2750 * + Execute FlexPort operation as defined by HW specs. 2751 * 2752 * - Attach 'new' ports to BCM layer: 2753 * + These are all ports that are active after the FlexPort operation. 2754 * + Ports are initialized to a default state 2755 * (same state when a port is brought up after SDK is initialized). 2756 * + This involves SW and HW changes. 2757 * 2758 * - Set BCM properties on flexed ports as needed. 2759 */ 2760 2761 /* 2762 * SOC Port Structure initialization 2763 */ 2764 /* Allocate memory for SOC Port Resource array data structure */ 2765 soc_resource = sal_alloc(sizeof(soc_port_resource_t) * nport, 2766 "port_resource"); 2767 if (soc_resource == NULL) { 2768 LOG_ERROR(BSL_LS_BCM_PORT, 2769 (BSL_META_U(unit, 2770 "Unable to allocate memory for SOC FlexPort " 2771 "array\n"))); 2772 return BCM_E_MEMORY; 2773 } 2774 2775 /* Clear data structure */ 2776 sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport); 2777 2778 /* Copy initial information */ 2779 for (i = 0; i < nport; i++) { 2780 soc_resource[i].flags = resource[i].flags; 2781 soc_resource[i].logical_port = resource[i].port; 2782 soc_resource[i].physical_port = resource[i].physical_port; 2783 soc_resource[i].speed = resource[i].speed; 2784 soc_resource[i].num_lanes = resource[i].lanes; 2785 soc_resource[i].encap = resource[i].encap; 2786 } 2787 2788 2789 /* SOC Validation */ 2790 rv = soc_td2p_port_resource_validate(unit, nport, soc_resource); 2791 if (SOC_FAILURE(rv)) { 2792 sal_free(soc_resource); 2793 return rv; 2794 } 2795 2796 /* Detach ports from BCM layer */ 2797 rv = _bcm_td2p_port_resource_detach(unit, nport, resource); 2798 2799 /* SOC Port Resource Configure */ 2800 if (op == BCM_TD2P_PORT_RESOURCE_OP_LANES) { 2801 flag = SOC_PORT_RESOURCE_CONFIGURE_LANES_ONLY; 2802 } else { 2803 flag = SOC_PORT_RESOURCE_CONFIGURE_FLEX; 2804 } 2805 if (BCM_SUCCESS(rv)) { 2806 rv = soc_td2p_port_resource_configure(unit, nport, soc_resource, flag); 2807 } 2808 2809 /* Attach ports to BCM layer */ 2810 if (BCM_SUCCESS(rv)) { 2811 rv = _bcm_td2p_port_resource_attach(unit, nport, resource); 2812 } 2813 2814 if (BCM_FAILURE(rv)) { 2815 LOG_ERROR(BSL_LS_BCM_PORT, 2816 (BSL_META_U(unit, 2817 "Changes to device may have been partially " 2818 "executed. System may be unstable.\n"))); 2819 } 2820 2821 sal_free(soc_resource); 2822 2823 return rv; 2824 } 2825 2826 2827 /* 2828 * Function: 2829 * _bcm_td2p_port_resource_configure 2830 * Purpose: 2831 * Modify the following port resources: 2832 * - Logical to physical port mapping 2833 * - Speed 2834 * - Number of PHY lanes 2835 * - Encapsulation mode 2836 * Parameters: 2837 * unit - (IN) Unit number. 2838 * nport - (IN) Number of elements in array resource. 2839 * resource - (IN/OUT) Port resource configuration array. 2840 * Returns: 2841 * BCM_E_XXX 2842 * Note: 2843 * - Assumes caller has lock. 2844 * - The data is modified by the function. 2845 * - It takes the internal bcm_td2p_port_resource_t data type. 2846 */ 2847 STATIC int 2848 _bcm_td2p_port_resource_configure(int unit, 2849 int nport, 2850 bcm_td2p_port_resource_t *resource) 2851 { 2852 int op; 2853 int i; 2854 2855 /* Convert port format and validate logical and physical port numbers */ 2856 BCM_IF_ERROR_RETURN 2857 (_bcm_td2p_port_resource_resolve(unit, 2858 nport, resource)); 2859 2860 /* Get port mapping change */ 2861 BCM_IF_ERROR_RETURN 2862 (_bcm_td2p_port_resource_pmap_get(unit, nport, resource)); 2863 2864 /* clear loopback */ 2865 BCM_IF_ERROR_RETURN 2866 (_bcm_td2p_port_resource_loopback_clear(unit, nport, resource)); 2867 2868 /* 2869 * Validate function input requirements 2870 * 2871 * This steps checks for function semantics and guidelines 2872 * from the API perspective. 2873 */ 2874 BCM_IF_ERROR_RETURN 2875 (_bcm_td2p_port_resource_input_validate(unit, nport, resource)); 2876 2877 /* 2878 * FlexPort operations types: 2879 * NONE => Nothing to do 2880 * PMAP or LANES => FlexPort sequence 2881 * ENCAP => Encap set 2882 * SPEED, but not PMAP or LANES => Speed set 2883 */ 2884 BCM_IF_ERROR_RETURN 2885 (_bcm_td2p_port_resource_op_get(unit, nport, resource, &op)); 2886 2887 LOG_VERBOSE(BSL_LS_BCM_PORT, 2888 (BSL_META_U(unit, 2889 "FlexPort operations 0x%x: %s %s %s %s\n"), 2890 op, 2891 (op & BCM_TD2P_PORT_RESOURCE_OP_PMAP) ? "pmap" : "", 2892 (op & BCM_TD2P_PORT_RESOURCE_OP_SPEED) ? "speed" : "", 2893 (op & BCM_TD2P_PORT_RESOURCE_OP_LANES) ? "lanes" : "", 2894 (op & BCM_TD2P_PORT_RESOURCE_OP_ENCAP) ? "encap" : "")); 2895 2896 if (op == BCM_TD2P_PORT_RESOURCE_OP_NONE) { 2897 return BCM_E_NONE; /* No changes, just return */ 2898 } 2899 2900 /* 2901 * Port Mapping / Lane 2902 * 2903 * These changes always require a FlexPort operation. 2904 */ 2905 if ((op & BCM_TD2P_PORT_RESOURCE_OP_PMAP) || 2906 (op & BCM_TD2P_PORT_RESOURCE_OP_LANES)) { 2907 LOG_VERBOSE(BSL_LS_BCM_PORT, 2908 (BSL_META_U(unit, 2909 "--- Execute FlexPort sequence ---\n"))); 2910 BCM_IF_ERROR_RETURN 2911 (_bcm_td2p_port_resource_execute(unit, 2912 nport, resource, op)); 2913 /* 2914 * Bring new ports down to ensure port state is proper 2915 */ 2916 for (i = 0; i < nport; i++) { 2917 if (resource[i].physical_port == -1) { 2918 continue; 2919 } 2920 BCM_IF_ERROR_RETURN 2921 (bcmi_esw_portctrl_enable_set(unit, resource[i].port, 0)); 2922 } 2923 } else if (op & BCM_TD2P_PORT_RESOURCE_OP_SPEED) { 2924 LOG_VERBOSE(BSL_LS_BCM_PORT, 2925 (BSL_META_U(unit, 2926 "--- Execute Speed Set sequence ---\n"))); 2927 BCM_IF_ERROR_RETURN 2928 (_bcm_td2p_port_resource_speed_execute(unit, 2929 nport, resource)); 2930 } else if (op & BCM_TD2P_PORT_RESOURCE_OP_ENCAP) { 2931 BCM_IF_ERROR_RETURN 2932 (_bcm_td2p_port_soc_resource_validate(unit, nport, resource)); 2933 } 2934 2935 /* 2936 * Encap 2937 */ 2938 if (op & BCM_TD2P_PORT_RESOURCE_OP_ENCAP) { 2939 LOG_VERBOSE(BSL_LS_BCM_PORT, 2940 (BSL_META_U(unit, 2941 "Execute Encap change\n"))); 2942 2943 for (i = 0; i < nport; i++) { 2944 if (resource[i].physical_port == -1) { 2945 continue; 2946 } 2947 2948 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_encap_set_execute(unit, 2949 resource[i].port, 2950 resource[i].encap, TRUE)); 2951 } 2952 } 2953 2954 return BCM_E_NONE; 2955 } 2956 2957 2958 /* 2959 * Function: 2960 * _bcm_td2p_port_resource_multi_set 2961 * Purpose: 2962 * Modify the following port resources: 2963 * - Logical to physical port mapping 2964 * - Speed 2965 * - Number of PHY lanes 2966 * - Encapsulation mode 2967 * Parameters: 2968 * unit - (IN) Unit number. 2969 * nport - (IN) Number of elements in array resource. 2970 * resource - (IN) Port resource configuration array. 2971 * Returns: 2972 * BCM_E_XXX 2973 * Note: 2974 * - Assumes caller has lock. 2975 * - This is to be called by the API dispatch driver. 2976 * - It takes the public bcm_port_resource_t data type. 2977 */ 2978 STATIC int 2979 _bcm_td2p_port_resource_multi_set(int unit, 2980 int nport, 2981 bcm_port_resource_t *resource) 2982 { 2983 int rv; 2984 int i; 2985 bcm_td2p_port_resource_t *port_resource; 2986 2987 if (resource == NULL) { 2988 return BCM_E_PARAM; 2989 } 2990 2991 /* 2992 * Use internal port resource structure type. 2993 * Called routines will be modifying the data, so 2994 * having a copy avoids modifying user's data. 2995 */ 2996 port_resource = sal_alloc(sizeof(bcm_td2p_port_resource_t) * nport, 2997 "port_resource"); 2998 if (port_resource == NULL) { 2999 LOG_ERROR(BSL_LS_BCM_PORT, 3000 (BSL_META_U(unit, 3001 "Unable to allocate memory for internal " 3002 "FlexPort array\n"))); 3003 return BCM_E_MEMORY; 3004 } 3005 3006 /* Clear data structure */ 3007 sal_memset(port_resource, 0, sizeof(bcm_td2p_port_resource_t) * nport); 3008 3009 /* Copy initial information */ 3010 for (i = 0; i < nport; i++) { 3011 /* 3012 * No current flags defined in bcm_port_resource_t, otherwise 3013 * need to translate from public to internal flags. 3014 */ 3015 port_resource[i].flags = 0; 3016 port_resource[i].port = resource[i].port; 3017 port_resource[i].physical_port = resource[i].physical_port; 3018 port_resource[i].speed = resource[i].speed; 3019 port_resource[i].lanes = resource[i].lanes; 3020 port_resource[i].encap = resource[i].encap; 3021 } 3022 3023 rv = _bcm_td2p_port_resource_configure(unit, nport, port_resource); 3024 3025 sal_free(port_resource); 3026 3027 return rv; 3028 } 3029 3030 /* 3031 * Function: 3032 * _bcm_td2p_port_core_chip_speed_get 3033 * Purpose: 3034 * This API is to obtain core chip speed 3035 * Parameters: 3036 * unit - (IN) Unit number 3037 * port - (IN) Logical port number(bcm_port_t, not bcm_gport_t) 3038 * speed - (IN) Port speed 3039 * Returns: 3040 * BCM_E_XXX 3041 * Note: 3042 * - Assumes caller has lock. 3043 * - This is to be called by the API dispatch driver. 3044 */ 3045 STATIC int 3046 _bcm_td2p_port_core_chip_speed_get(int unit, bcm_port_t port, int *speed) 3047 { 3048 SOC_IF_ERROR_RETURN(soc_td2p_port_speed_get(unit, port, speed)); 3049 3050 return BCM_E_NONE; 3051 } 3052 3053 /* 3054 * Function: 3055 * _bcm_td2p_port_resource_speed_set 3056 * Purpose: 3057 * Changes the speed but keeps the same number of lanes 3058 * Parameters: 3059 * unit - (IN) Unit number 3060 * port - (IN) Logical port number(bcm_port_t, not bcm_gport_t) 3061 * speed - (IN) Port speed 3062 * Returns: 3063 * BCM_E_XXX 3064 * Note: 3065 * - Assumes caller has lock. 3066 * - This is to be called by the API dispatch driver. 3067 */ 3068 STATIC int 3069 _bcm_td2p_port_resource_speed_set(int unit, bcm_port_t port, int speed) 3070 { 3071 soc_info_t *si = &SOC_INFO(unit); 3072 bcm_td2p_port_resource_t resource[2]; /* resource for pre and post */ 3073 int cur_lanes, cur_speed, cur_encap; 3074 int phy_port; 3075 3076 /* Get current core chip port speed */ 3077 BCM_IF_ERROR_RETURN(_bcm_td2p_port_core_chip_speed_get( 3078 unit, port, &cur_speed)); 3079 if (cur_speed == 0) { 3080 /* port is detached */ 3081 cur_speed = SOC_INFO(unit).port_speed_max[port]; 3082 } 3083 3084 if (cur_speed == speed) { 3085 LOG_VERBOSE(BSL_LS_BCM_PORT, 3086 (BSL_META_U(unit, 3087 "Speed is already configured as %d\n"), cur_speed)); 3088 return BCM_E_NONE; 3089 } 3090 3091 /* Check current number of lanes */ 3092 BCM_IF_ERROR_RETURN(bcmi_td2p_port_lanes_get(unit, port, &cur_lanes)); 3093 3094 /* Get current port encap */ 3095 BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, port, &cur_encap)); 3096 3097 /* 3098 * Clear mapping for physical ports involved in FlexPort operation. 3099 */ 3100 phy_port = si->port_l2p_mapping[port]; 3101 /* Check valid physical port */ 3102 if (phy_port == -1) { 3103 LOG_ERROR(BSL_LS_BCM_PORT, 3104 (BSL_META_U(unit, 3105 "Invalid physical port " 3106 "for logical port %d\n"), 3107 port)); 3108 return BCM_E_INTERNAL; 3109 } 3110 3111 resource[0].flags = SOC_PORT_RESOURCE_I_MAP | SOC_PORT_RESOURCE_SPEED; 3112 resource[0].port = port; 3113 resource[0].physical_port = -1; 3114 3115 resource[1].flags = SOC_PORT_RESOURCE_I_MAP | SOC_PORT_RESOURCE_SPEED; 3116 resource[1].port = port; 3117 resource[1].physical_port = phy_port; 3118 resource[1].speed = speed; 3119 resource[1].lanes = cur_lanes; 3120 resource[1].encap = cur_encap; 3121 3122 BCM_IF_ERROR_RETURN(_bcm_td2p_port_resource_configure(unit, 2, resource)); 3123 3124 return BCM_E_NONE; 3125 } 3126 3127 /* 3128 * Function: 3129 * bcmi_td2p_port_lanes_get 3130 * Purpose: 3131 * Get the number of PHY lanes for the given port. 3132 * Parameters: 3133 * unit - (IN) Unit number. 3134 * port - (IN) Logical port. 3135 * lanes - (OUT) Returns number of lanes for port. 3136 * Returns: 3137 * BCM_E_XXX 3138 */ 3139 int 3140 bcmi_td2p_port_lanes_get(int unit, bcm_port_t port, int *lanes) 3141 { 3142 bcm_port_resource_t resource; 3143 3144 BCM_IF_ERROR_RETURN(bcm_esw_port_resource_get(unit, port, &resource)); 3145 3146 *lanes = resource.lanes; 3147 3148 return BCM_E_NONE; 3149 } 3150 3151 3152 /* 3153 * Function: 3154 * bcmi_td2p_port_lanes_set 3155 * Purpose: 3156 * Set the number of PHY lanes for the given port. 3157 * 3158 * This function should only be used to support the legacy 3159 * FlexPort API bcm_port_control_set(... , bcmPortControlLanes). 3160 * 3161 * The legacy API does not delete the port mappings when flexing 3162 * to fewer lanes. Ports which lanes are used by the base 3163 * physical port becomes inactive. 3164 * 3165 * Parameters: 3166 * unit - (IN) Unit number. 3167 * port - (IN) Logical port. 3168 * lanes - (IN) Number of lanes to set on given port. 3169 * Returns: 3170 * BCM_E_XXX 3171 * Notes: 3172 * - Only to be used by legacy API to support TD2 behavior 3173 * bcm_port_control_set(... , bcmPortControlLanes). 3174 * - Supports only up to 4 lanes (TSC-4). 3175 * - 'port' must be in BCM port format (non-GPORT) and mapped to 3176 * the base physical port. 3177 * - Several calls to legacy API may be required to 3178 * achieve desired configuration. 3179 */ 3180 int 3181 bcmi_td2p_port_lanes_set(int unit, bcm_port_t port, int lanes) 3182 { 3183 soc_info_t *si = &SOC_INFO(unit); 3184 bcm_td2p_port_resource_t resource[8]; /* Max sz to support up to 4 lanes */ 3185 int max_array_cnt; 3186 int i; 3187 int cur_lanes; 3188 int cur_speed; 3189 int cur_encap = 0; 3190 int phy_port; 3191 int speed; 3192 int num_ports_clear; 3193 int num_ports_new; 3194 3195 /* Support legacy API up to 4 lanes */ 3196 if ((lanes != 1) && (lanes != 2) && (lanes != 4)) { 3197 return BCM_E_PARAM; 3198 } 3199 3200 /* Check current number of lanes */ 3201 BCM_IF_ERROR_RETURN(bcmi_td2p_port_lanes_get(unit, port, &cur_lanes)); 3202 if (cur_lanes == lanes) { 3203 return BCM_E_NONE; 3204 } 3205 3206 /* Check that port can support number of lanes specified */ 3207 SOC_IF_ERROR_RETURN(soc_td2p_port_lanes_valid(unit, port, lanes)); 3208 3209 /* Get current port speed */ 3210 BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, port, &cur_speed)); 3211 3212 /* Get current port encap */ 3213 BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, port, &cur_encap)); 3214 3215 /* Clear array */ 3216 max_array_cnt = COUNTOF(resource); 3217 sal_memset(resource, 0, sizeof(resource)); 3218 3219 /* 3220 * Build port resource array 3221 * Certain information is derived from 'best' guess, 3222 * similar to the legacy behaviour. 3223 */ 3224 3225 /* 3226 * Select speed based on number of lanes 3227 * 3228 * For HG, if the current HG speed is the higher speed 3229 * (i.e. 42 vs 40) select the higher HG speed for the number of lanes. 3230 * Example 3231 * 1xHG[42] --> 4xHG[11] 3232 * 1xHG[40] --> 4xHG[10] 3233 * 3234 * Notes: Assumes encap is HIGIG2 if it is not IEEE 3235 */ 3236 switch(lanes) { 3237 case 1: 3238 if (cur_encap == BCM_PORT_ENCAP_IEEE) { /* IEEE */ 3239 speed = 10000; 3240 } else { /* Assume HG */ 3241 if (((cur_lanes == 4) && (cur_speed > 40000)) || 3242 ((cur_lanes == 2) && (cur_speed > 20000))) { 3243 speed = 11000; 3244 } else { 3245 speed = 10000; 3246 } 3247 } 3248 break; 3249 case 2: 3250 if (cur_encap == BCM_PORT_ENCAP_IEEE) { /* IEEE */ 3251 speed = 20000; 3252 } else { /* Assume HG */ 3253 if (((cur_lanes == 4) && (cur_speed > 40000)) || 3254 ((cur_lanes == 1) && (cur_speed > 10000))) { 3255 speed = 21000; 3256 } else { 3257 speed = 20000; 3258 } 3259 } 3260 break; 3261 case 4: 3262 if (cur_encap == BCM_PORT_ENCAP_IEEE) { /* IEEE */ 3263 speed = 40000; 3264 } else { /* Assume HG */ 3265 if (((cur_lanes == 2) && (cur_speed > 20000)) || 3266 ((cur_lanes == 1) && (cur_speed > 10000))) { 3267 speed = 42000; 3268 } else { 3269 speed = 40000; 3270 } 3271 } 3272 break; 3273 /* 3274 * COVERITY 3275 * 3276 * Case for default is intentional as a defensive check. 3277 */ 3278 /* coverity[dead_error_begin] */ 3279 default: 3280 return BCM_E_PARAM; 3281 break; 3282 } 3283 3284 switch (cur_lanes) { 3285 case 1: 3286 /* 3287 * 2x10 flex to: 2 lanes -> 1x20 3288 * 4x10 flex to: 4 lanes -> 1x40 3289 */ 3290 if (lanes == 2) { 3291 int first_phy_port; 3292 int physical_port = si->port_l2p_mapping[port]; 3293 3294 SOC_IF_ERROR_RETURN (soc_td2p_port_macro_first_phy_port_get(unit, 3295 physical_port, &first_phy_port)); 3296 3297 /* In tri-mode, either first two lanes of a tsc (1,2) can be 3298 * selected for 20G speed, or the last two lanes (3, 4). In the 3299 * second case, we should create only one new 20G port 3300 */ 3301 if (physical_port == first_phy_port) { 3302 num_ports_clear = 4; 3303 num_ports_new = 2; 3304 } else { 3305 num_ports_clear = 2; 3306 num_ports_new = 1; 3307 } 3308 } else { 3309 num_ports_clear = 4; 3310 num_ports_new = 1; 3311 } 3312 break; 3313 case 2: 3314 /* 3315 * 1x20 flex to: 1 lane -> 2x10 3316 * 2x20 flex to: 4 lanes -> 1x40 3317 */ 3318 if (lanes == 1) { 3319 num_ports_clear = 2; 3320 num_ports_new = 2; 3321 } else { 3322 num_ports_clear = 4; 3323 num_ports_new = 1; 3324 } 3325 break; 3326 case 4: 3327 /* 3328 * 1x40 flex to: 1 lane -> 4x10 3329 * 2 lanes -> 2x20 3330 */ 3331 if (lanes == 1) { 3332 num_ports_clear = 4; 3333 num_ports_new = 4; 3334 } else { 3335 num_ports_clear = 4; 3336 num_ports_new = 2; 3337 } 3338 break; 3339 default: 3340 return BCM_E_CONFIG; 3341 break; 3342 } 3343 3344 if ((num_ports_clear + num_ports_new) > max_array_cnt) { 3345 LOG_ERROR(BSL_LS_BCM_PORT, 3346 (BSL_META_U(unit, 3347 "Invalid array FlexPort calculation " 3348 "num_ports_clear=%d num_ports_new=%d " 3349 "max_array=%d\n"), 3350 num_ports_clear, num_ports_new, max_array_cnt)); 3351 return BCM_E_INTERNAL; 3352 } 3353 3354 /* 3355 * Clear mapping for physical ports involved in FlexPort operation. 3356 * Assume physical ports are numbered consecutively in device. 3357 */ 3358 phy_port = si->port_l2p_mapping[port]; 3359 for (i = 0; i < num_ports_clear; i++) { 3360 resource[i].flags = SOC_PORT_RESOURCE_I_MAP; 3361 resource[i].port = si->port_p2l_mapping[phy_port++]; 3362 resource[i].physical_port = -1; 3363 } 3364 3365 /* 3366 * Map new ports 3367 * 3368 * Legacy API requires that logical-physical port mapping 3369 * is valid in the SOC_INFO SW data. 3370 */ 3371 phy_port = si->port_l2p_mapping[port]; 3372 for (; i < (num_ports_clear + num_ports_new); i++) { 3373 /* Check valid physical port */ 3374 if (phy_port == -1) { 3375 LOG_ERROR(BSL_LS_BCM_PORT, 3376 (BSL_META_U(unit, 3377 "Invalid physical port " 3378 "for logical port %d\n"), 3379 port)); 3380 return BCM_E_INTERNAL; 3381 } 3382 3383 resource[i].flags = SOC_PORT_RESOURCE_I_MAP; 3384 resource[i].port = si->port_p2l_mapping[phy_port]; 3385 resource[i].physical_port = phy_port; 3386 resource[i].lanes = lanes; 3387 resource[i].speed = speed; 3388 resource[i].encap = cur_encap; 3389 phy_port += lanes; 3390 } 3391 3392 BCM_IF_ERROR_RETURN 3393 (_bcm_td2p_port_resource_configure(unit, 3394 (num_ports_clear + num_ports_new), 3395 resource)); 3396 3397 return BCM_E_NONE; 3398 } 3399 3400 /* 3401 * Function: 3402 * bcm_td2p_flexport_pbmp_update 3403 * Description: 3404 * given a pbmp, add flexport pbmp 3405 * Parameters: 3406 * unit - (IN) BCM device number 3407 * pbmp - (IN/OUT) port bit map 3408 */ 3409 3410 int 3411 bcm_td2p_flexport_pbmp_update(int unit, bcm_pbmp_t *pbmp) 3412 { 3413 bcm_port_t port; 3414 3415 if (NULL == pbmp) { 3416 return BCM_E_PARAM; 3417 } 3418 for (port = 0; port < TD2P_MAX_NUM_PORTS; port++) { 3419 BCM_PBMP_PORT_ADD(*pbmp, port); 3420 } 3421 return BCM_E_NONE; 3422 } 3423 3424 /* 3425 * Function: 3426 * _bcm_td2p_port_control_class_select_set 3427 * Description: 3428 * Function to add an entry to MISC_PORT_PROFILE table. 3429 * Parameters: 3430 * unit - (IN) Device number 3431 * port - (IN) Port number 3432 * table_id - (IN) 0 for FP_I2E_CLASSID_SELECTm 3433 * 1 for FP_HG_CLASSID_SELECT 3434 * mem - (IN) FP_I2E_CLASSID_SELECTm or FP_HG_CLASSID_SELECTm 3435 * field - (IN) Field to modify. 3436 * value - (IN) New field value. 3437 * Return Value: 3438 * BCM_E_XXX 3439 */ 3440 STATIC int 3441 _bcm_td2p_port_control_class_select_set(int unit, bcm_port_t port, int table_id, 3442 soc_mem_t mem, soc_field_t field, uint32 value) 3443 { 3444 fp_i2e_classid_select_entry_t fp_ent; 3445 fp_hg_classid_select_entry_t hg_ent; 3446 void *entries[2]; 3447 uint32 profile_index = 0; 3448 int cur_profile_index = 0; 3449 3450 entries[0] = &fp_ent; 3451 entries[1] = &hg_ent; 3452 3453 BCM_IF_ERROR_RETURN 3454 (_bcm_esw_port_tab_get(unit, port, MISC_PORT_PROFILE_INDEXf, &cur_profile_index)); 3455 3456 BCM_IF_ERROR_RETURN 3457 (_bcm_misc_port_profile_entry_get(unit, cur_profile_index, 1, entries)); 3458 3459 soc_mem_field32_set(unit, mem, entries[table_id], field, value); 3460 3461 BCM_IF_ERROR_RETURN 3462 (_bcm_misc_port_profile_entry_add(unit, entries, 1, &profile_index)); 3463 3464 BCM_IF_ERROR_RETURN 3465 (_bcm_esw_port_tab_set(unit, port,_BCM_CPU_TABS_NONE, 3466 MISC_PORT_PROFILE_INDEXf, profile_index)); 3467 3468 if (cur_profile_index != 0) { 3469 BCM_IF_ERROR_RETURN 3470 (_bcm_misc_port_profile_entry_delete(unit, cur_profile_index)); 3471 } 3472 3473 return BCM_E_NONE; 3474 } 3475 3476 /* 3477 * Function: 3478 * _bcm_td2p_port_control_class_select_get 3479 * Description: 3480 * Funtion to get an entry from MISC_PORT_PROFILE table. 3481 * Parameters: 3482 * unit - (IN) Device number 3483 * port - (IN) Port number 3484 * table_id - (IN) 0 for FP_I2E_CLASSID_SELECTm 3485 * 1 for FP_HG_CLASSID_SELECT 3486 * mem - (IN) FP_I2E_CLASSID_SELECTm or FP_HG_CLASSID_SELECTm 3487 * field - (IN) Field to read. 3488 * value - (OUT) Field value. 3489 * Return Value: 3490 * BCM_E_XXX 3491 */ 3492 STATIC int 3493 _bcm_td2p_port_control_class_select_get(int unit, bcm_port_t port, int table_id, 3494 soc_mem_t mem, soc_field_t field, uint32* value) 3495 { 3496 fp_i2e_classid_select_entry_t fp_ent; 3497 fp_hg_classid_select_entry_t hg_ent; 3498 void *entries[2]; 3499 int profile_index; 3500 3501 entries[0] = &fp_ent; 3502 entries[1] = &hg_ent; 3503 3504 BCM_IF_ERROR_RETURN 3505 (_bcm_esw_port_tab_get(unit, port, MISC_PORT_PROFILE_INDEXf, &profile_index)); 3506 3507 BCM_IF_ERROR_RETURN(_bcm_misc_port_profile_entry_get(unit, profile_index, 1, entries)); 3508 3509 *value = soc_mem_field32_get(unit, mem, entries[table_id], field); 3510 3511 return BCM_E_NONE; 3512 } 3513 3514 /* 3515 * Function: 3516 * _bcm_td2p_port_control_egress_class_select_set 3517 * Description: 3518 * Helper funtion to modify fields in FP_I2E_CLASSID_SELECTm memory. 3519 * Parameters: 3520 * unit - (IN) Device number 3521 * port - (IN) Port number 3522 * value - (IN) New field value 3523 * Return Value: 3524 * BCM_E_XXX 3525 */ 3526 int 3527 _bcm_td2p_port_control_egress_class_select_set(int unit, bcm_port_t port, uint32 value) 3528 { 3529 soc_mem_t mem = FP_I2E_CLASSID_SELECTm; 3530 soc_field_t field = PORT_SELf; 3531 /* table_id = 0 for FP_I2E_CLASSID_SELECTm in MISC_PORT_PROFILE_TABLE */ 3532 int table_id = 0; 3533 /* Check for valid inputs for FP_I2E_CLASSID_SELECT */ 3534 /* coverity[unsigned_compare] : FALSE */ 3535 if ((value < bcmPortEgressClassSelectNone) || 3536 (value >= bcmPortEgressClassSelectFieldIngress)) { 3537 return BCM_E_PARAM; 3538 } 3539 3540 BCM_IF_ERROR_RETURN 3541 (_bcm_td2p_port_control_class_select_set(unit, port, table_id, mem, field, value)); 3542 3543 return BCM_E_NONE; 3544 } 3545 3546 /* 3547 * Function: 3548 * _bcm_td2p_port_control_egress_class_select_get 3549 * Description: 3550 * Helper funtion to get fields in FP_I2E_CLASSID_SELECTm memory. 3551 * Parameters: 3552 * unit - (IN) Device number 3553 * port - (IN) Port number 3554 * value - (OUT) New field value 3555 * Return Value: 3556 * BCM_E_XXX 3557 */ 3558 int 3559 _bcm_td2p_port_control_egress_class_select_get(int unit, bcm_port_t port, uint32 *value) 3560 { 3561 soc_mem_t mem = FP_I2E_CLASSID_SELECTm; 3562 soc_field_t field = PORT_SELf; 3563 /* table_id = 0 for FP_I2E_CLASSID_SELECTm in MISC_PORT_PROFILE_TABLE */ 3564 int table_id = 0; 3565 3566 BCM_IF_ERROR_RETURN 3567 (_bcm_td2p_port_control_class_select_get(unit, port, table_id, mem, field, value)); 3568 3569 return BCM_E_NONE; 3570 } 3571 3572 /* 3573 * Function: 3574 * _bcm_td2p_port_control_higig_class_select_set 3575 * Description: 3576 * Helper funtion to modify fields in FP_HG_CLASSID_SELECT memory. 3577 * Parameters: 3578 * unit - (IN) Device number 3579 * port - (IN) Port number 3580 * value - (IN) New field value 3581 * Return Value: 3582 * BCM_E_XXX 3583 */ 3584 int 3585 _bcm_td2p_port_control_higig_class_select_set(int unit, bcm_port_t port, uint32 value) 3586 { 3587 soc_mem_t mem = FP_HG_CLASSID_SELECTm; 3588 soc_field_t field = PORT_SELf; 3589 /* table_id = 1 for FP_HG_CLASSID_SELECTm in MISC_PORT_PROFILE_TABLE */ 3590 int table_id = 1; 3591 /* Check for valid inputs for FP_HG_CLASSID_SELECT */ 3592 /* coverity[unsigned_compare] : FALSE */ 3593 if ((value < bcmPortFieldHiGigClassSelectNone) || 3594 (value >= bcmPortFieldHiGigClassSelectCount) || 3595 (value == bcmPortFieldHiGigClassSelectL3Egress) || 3596 (value == bcmPortFieldHiGigClassSelectL3EgressIntf)) { 3597 return BCM_E_PARAM; 3598 } 3599 3600 BCM_IF_ERROR_RETURN 3601 (_bcm_td2p_port_control_class_select_set(unit, port, table_id, mem, field, value)); 3602 3603 return BCM_E_NONE; 3604 } 3605 3606 /* 3607 * Function: 3608 * _bcm_td2p_port_control_higig_class_select_get 3609 * Description: 3610 * Helper funtion to get fields in FP_HG_CLASSID_SELECT memory. 3611 * Parameters: 3612 * unit - (IN) Device number 3613 * port - (IN) Port number 3614 * value - (OUT) New field value 3615 * Return Value: 3616 * BCM_E_XXX 3617 */ 3618 int 3619 _bcm_td2p_port_control_higig_class_select_get(int unit, bcm_port_t port, uint32 *value) 3620 { 3621 soc_mem_t mem = FP_HG_CLASSID_SELECTm; 3622 soc_field_t field = PORT_SELf; 3623 /* table_id = 1 for FP_HG_CLASSID_SELECTm in MISC_PORT_PROFILE_TABLE */ 3624 int table_id = 1; 3625 3626 BCM_IF_ERROR_RETURN 3627 (_bcm_td2p_port_control_class_select_get(unit, port, table_id, mem, field, value)); 3628 3629 return BCM_E_NONE; 3630 } 3631 3632 #else /* BCM_TRIDENT2PLUS_SUPPORT */ 3633 int bcm_esw_td2p_port_not_empty; 3634 #endif /* BCM_TRIDENT2PLUS_SUPPORT */