trunk.c (175189B)
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 * XGS3 Trunking (Ether and Fabric) 8 */ 9 10 #include <soc/mem.h> 11 #include <soc/firebolt.h> 12 #include <shared/bsl.h> 13 #include <bcm/error.h> 14 #include <bcm/stack.h> 15 16 #include <bcm_int/esw/l2.h> /* MAC learn limit interaction */ 17 #include <bcm_int/esw/mbcm.h> 18 #include <bcm_int/esw/link.h> /* LAG failover support */ 19 #include <bcm_int/esw/stack.h> 20 21 #include <bcm_int/esw/trunk.h> 22 #include <bcm_int/esw_dispatch.h> 23 #if defined(BCM_TRX_SUPPORT) 24 #include <bcm_int/esw/trx.h> 25 #endif /* BCM_TRX_SUPPORT */ 26 #if defined(BCM_GREYHOUND2_SUPPORT) 27 #include <bcm_int/esw/vxlan.h> 28 #endif /* BCM_GREYHOUND2_SUPPORT */ 29 30 #define _BCM_FP_TRUNK_NUM_MAX 128 31 #define _BCM_FABRIC_TRUNK_NUM_MAX 16 32 #define _BCM_FABRIC_TRUNK_SWF_TID_OFFSET 200 33 #define _BCM_SCORPION_FABRIC_TRUNK_FAILOVER_PORT_NUM 16 34 #define _BCM_TRUNK_FAILOVER_PORT_NUM 8 35 #define _BCM_HURRICANE2_TRUNK_FAILOVER_PORT_NUM 4 36 37 /* 38 * Trunk Membership Info 39 */ 40 41 typedef struct { 42 uint8 num_ports; 43 uint16 modport[BCM_XGS3_TRUNK_MAX_PORTCNT]; 44 uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT]; 45 #ifdef BCM_WARM_BOOT_SUPPORT 46 uint8 recovered_from_scache; 47 #endif /* BCM_WARM_BOOT_SUPPORT */ 48 } _xgs3_member_info_t; 49 50 typedef struct { 51 _xgs3_member_info_t member_info[1]; 52 } _xgs3_trunk_member_info_t; 53 54 STATIC _xgs3_trunk_member_info_t *_xgs3_trunk_member_info[BCM_MAX_NUM_UNITS]; 55 56 #define MEMBER_INFO(_unit_, _tid_) (_xgs3_trunk_member_info[_unit_]->member_info[_tid_]) 57 58 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 59 /* 60 * Hardware Trunk Failover: 61 * 62 * For the devices which support hardware trunk failover, the failover 63 * configuration must be retained if it is one of the standard models 64 * for the retrieval function to use the same encoding as the set function. 65 * 66 * Note: The trunk members stored in _xgs3_tinfo_t's modport array do not 67 * include those members with the BCM_TRUNK_MEMBER_EGRESS_DISABLE set. 68 */ 69 70 typedef struct { 71 uint8 num_ports; 72 uint8 psc[BCM_XGS3_TRUNK_MAX_PORTCNT]; 73 uint16 modport[BCM_XGS3_TRUNK_MAX_PORTCNT]; 74 uint32 flags[BCM_XGS3_TRUNK_MAX_PORTCNT]; 75 } _xgs3_hw_tinfo_t; 76 77 typedef struct { 78 _xgs3_hw_tinfo_t hw_tinfo[_BCM_FP_TRUNK_NUM_MAX + _BCM_FABRIC_TRUNK_NUM_MAX]; 79 } _xgs3_trunk_hwfail_t; 80 81 STATIC _xgs3_trunk_hwfail_t *_xgs3_trunk_hwfail[BCM_MAX_NUM_UNITS]; 82 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 83 84 /* 85 * Software Trunk Failover: 86 * 87 * Even without hardware failover support, given the high speed link 88 * change notification possible with XGS3 devices, a port that has been 89 * indicated as link down can cause the trunk_group table to be immediately 90 * updated with the link down port removed. This works well for two cases: 91 * (1) this is a higig trunk, or (2) the local device is the only device 92 * in the system. 93 * 94 * Note: The trunk members stored in _xgs3_tinfo_t's modport array do not 95 * include those members with the BCM_TRUNK_MEMBER_EGRESS_DISABLE set. 96 * If a trunk member port is down, it'll be removed from _xg3_tinfo_t's 97 * modport array by _bcm_xgs3_trunk_swfailover_trigger. 98 */ 99 typedef struct { 100 uint8 rtag; 101 uint8 num_ports; 102 uint16 modport[BCM_XGS3_TRUNK_MAX_PORTCNT]; 103 uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT]; 104 } _xgs3_tinfo_t; 105 106 typedef struct { 107 uint8 mymodid; 108 bcm_trunk_t trunk[SOC_MAX_NUM_PORTS]; /* 0: unused; 109 1-129: ether; 110 200-207: higig */ 111 _xgs3_tinfo_t tinfo[_BCM_FP_TRUNK_NUM_MAX + _BCM_FABRIC_TRUNK_NUM_MAX]; 112 } _xgs3_trunk_swfail_t; 113 114 115 STATIC _xgs3_trunk_swfail_t *_xgs3_trunk_swfail[BCM_MAX_NUM_UNITS]; 116 117 STATIC int _bcm_xgs3_trunk_swfailover_set(int unit, 118 bcm_trunk_t tid, 119 int rtag, 120 int nports, 121 int mods[BCM_XGS3_TRUNK_MAX_PORTCNT], 122 int ports[BCM_XGS3_TRUNK_MAX_PORTCNT], 123 uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT]); 124 125 STATIC int _bcm_xgs3_trunk_swfailover_fabric_set(int unit, 126 bcm_trunk_t hgtid, 127 int rtag, 128 bcm_pbmp_t ports); 129 130 STATIC uint8 *_xgs3_mod_port_to_tid_map[BCM_MAX_NUM_UNITS]; 131 132 /* fields from TRUNK_GROUPm */ 133 static soc_field_t _xgs_portf[8] = { 134 PORT0f, PORT1f, PORT2f, PORT3f, 135 PORT4f, PORT5f, PORT6f, PORT7f 136 }; 137 138 static soc_field_t _xgs_modulef[8] = { 139 MODULE0f, MODULE1f, MODULE2f, MODULE3f, 140 MODULE4f, MODULE5f, MODULE6f, MODULE7f 141 }; 142 143 /* fields from FAST_TRUNK_GROUPm */ 144 static soc_field_t _xgs_fast_portf[8] = { 145 PORT_NUM_0f, PORT_NUM_1f, PORT_NUM_2f, PORT_NUM_3f, 146 PORT_NUM_4f, PORT_NUM_5f, PORT_NUM_6f, PORT_NUM_7f 147 }; 148 149 static soc_field_t _xgs_fast_modulef[8] = { 150 MODULE_ID_0f, MODULE_ID_1f, MODULE_ID_2f, MODULE_ID_3f, 151 MODULE_ID_4f, MODULE_ID_5f, MODULE_ID_6f, MODULE_ID_7f 152 }; 153 154 /* fields from HIGIG_TRUNK_GROUPr */ 155 static soc_field_t _hg_trunk0f[4] = { 156 HIGIG_TRUNK_ID0_PORT0f, HIGIG_TRUNK_ID0_PORT1f, 157 HIGIG_TRUNK_ID0_PORT2f, HIGIG_TRUNK_ID0_PORT3f 158 }; 159 160 static soc_field_t _hg_trunk1f[4] = { 161 HIGIG_TRUNK_ID1_PORT0f, HIGIG_TRUNK_ID1_PORT1f, 162 HIGIG_TRUNK_ID1_PORT2f, HIGIG_TRUNK_ID1_PORT3f 163 }; 164 165 /* fields from HIGIG_TRUNK_CONTROLr */ 166 static soc_field_t _hg_cntl0f[4] = { 167 HIGIG_TRUNK_ID0f, HIGIG_TRUNK_ID1f, 168 HIGIG_TRUNK_ID2f, HIGIG_TRUNK_ID3f 169 }; 170 171 static soc_field_t _hg_cntl1f[4] = { 172 HIGIG_TRUNK0f, HIGIG_TRUNK1f, 173 HIGIG_TRUNK2f, HIGIG_TRUNK3f 174 }; 175 176 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 177 /* fields from HG_TRUNK_GROUPr */ 178 /* Enduro has only 4 fields. Not 8. They will be checked in the executable code */ 179 static soc_field_t _hg_trunk[8] = { 180 HIGIG_TRUNK_PORT0f, HIGIG_TRUNK_PORT1f, 181 HIGIG_TRUNK_PORT2f, HIGIG_TRUNK_PORT3f, 182 HIGIG_TRUNK_PORT4f, HIGIG_TRUNK_PORT5f, 183 HIGIG_TRUNK_PORT6f, HIGIG_TRUNK_PORT7f 184 }; 185 #endif /* BCM_TRX_SUPPORT */ 186 #if defined(BCM_SCORPION_SUPPORT) 187 /* fields from HG_TRUNK_GROUP_HIr */ 188 static soc_field_t _hg_trunk_hi[8] = { 189 HIGIG_TRUNK_PORT8f, HIGIG_TRUNK_PORT9f, 190 HIGIG_TRUNK_PORT10f, HIGIG_TRUNK_PORT11f, 191 HIGIG_TRUNK_PORT12f, HIGIG_TRUNK_PORT13f, 192 HIGIG_TRUNK_PORT14f, HIGIG_TRUNK_PORT15f 193 }; 194 #endif /* BCM_SCORPION_SUPPORT */ 195 196 /* 197 * Function: 198 * _bcm_xgs3_trunk_member_init 199 * Purpose: 200 * Initialize trunk member info. 201 * Parameters: 202 * unit - (IN)SOC unit number. 203 * Returns: 204 * BCM_X_XXX 205 */ 206 int 207 _bcm_xgs3_trunk_member_init(int unit) 208 { 209 int trunk_num_groups = _BCM_FP_TRUNK_NUM_MAX + _BCM_FABRIC_TRUNK_NUM_MAX; 210 211 #ifdef BCM_TOMAHAWK_SUPPORT 212 if (soc_feature(unit, soc_feature_fastlag)) { 213 trunk_num_groups = soc_mem_index_count(unit, FAST_TRUNK_GROUPm) + 214 soc_mem_index_count(unit, HG_TRUNK_GROUPm); 215 } 216 #endif 217 218 if (_xgs3_trunk_member_info[unit] == NULL) { 219 _xgs3_trunk_member_info[unit] = 220 sal_alloc((sizeof(_xgs3_trunk_member_info_t) * trunk_num_groups), 221 "_xgs3_trunk_member_info"); 222 223 if (_xgs3_trunk_member_info[unit] == NULL) { 224 return BCM_E_MEMORY; 225 } 226 } 227 228 sal_memset(_xgs3_trunk_member_info[unit], 0, 229 (sizeof(_xgs3_trunk_member_info_t) * trunk_num_groups)); 230 return BCM_E_NONE; 231 } 232 233 /* 234 * Function: 235 * _bcm_xgs3_trunk_member_detach 236 * Purpose: 237 * De-allocate trunk member info. 238 * Parameters: 239 * unit - (IN)SOC unit number. 240 * Returns: 241 * None 242 */ 243 void 244 _bcm_xgs3_trunk_member_detach(int unit) 245 { 246 if (_xgs3_trunk_member_info[unit] != NULL) { 247 sal_free(_xgs3_trunk_member_info[unit]); 248 _xgs3_trunk_member_info[unit] = NULL; 249 } 250 } 251 252 /* 253 * Function: 254 * _bcm_xgs3_trunk_mod_port_map_set 255 * Purpose: 256 * Set (mod, port) to trunk id map. 257 * Map implements a software cache for the SOURCE_TRUNK_MAP_TABLE. 258 * Parameters: 259 * unit - (IN) BCM device number. 260 * modid - (IN) Member port module id. 261 * port - (IN) Member port number. 262 * trunk_id - (IN) Trunk number or negative value for reset. 263 * Returns: 264 * BCM_X_XXX 265 */ 266 STATIC int 267 _bcm_xgs3_trunk_mod_port_map_set(int unit, bcm_module_t modid, 268 bcm_port_t port, bcm_trunk_t trunk_id) 269 { 270 271 int idx; /* Map array index. */ 272 273 if (NULL == _xgs3_mod_port_to_tid_map[unit]) { 274 return (BCM_E_INIT); 275 } 276 277 /* Trunk id range check. */ 278 if (trunk_id >= 0xff) { 279 return (BCM_E_INTERNAL); 280 } 281 282 idx = modid * SOC_MAX_NUM_PORTS + port; 283 if (idx >= _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit)) { 284 return (BCM_E_PARAM); 285 } 286 287 _xgs3_mod_port_to_tid_map[unit][idx] = (trunk_id < 0) ? 0 : (++trunk_id); 288 289 return (BCM_E_NONE); 290 } 291 292 /* 293 * Function: 294 * _bcm_xgs3_trunk_mod_port_map_get 295 * Purpose: 296 * Read mapping (mod, port) to trunk id from software cache 297 * for the SOURCE_TRUNK_MAP_TABLE. 298 * Parameters: 299 * unit - (IN) BCM device number. 300 * modid - (IN) Member port module id. 301 * port - (IN) Member port number. 302 * trunk_id - (OUT) Trunk number or negative value for reset. 303 * Returns: 304 * BCM_X_XXX 305 */ 306 STATIC int 307 _bcm_xgs3_trunk_mod_port_map_get(int unit, bcm_module_t modid, 308 bcm_port_t port, bcm_trunk_t *trunk_id) 309 { 310 311 int idx; /* Map array index. */ 312 bcm_module_t mymodid; /* Local module id. */ 313 int isLocal; /* Local module id flag. */ 314 int rv; /* Operation return status. */ 315 316 if (NULL == _xgs3_mod_port_to_tid_map[unit]) { 317 return (BCM_E_INIT); 318 } 319 320 rv = _bcm_esw_modid_is_local(unit, modid, &isLocal); 321 BCM_IF_ERROR_RETURN(rv); 322 323 if (isLocal) { 324 rv = bcm_esw_stk_my_modid_get(unit, &mymodid); 325 BCM_IF_ERROR_RETURN(rv); 326 if (mymodid != modid) { 327 modid = mymodid; 328 port += 32; 329 } 330 } 331 332 idx = modid * SOC_MAX_NUM_PORTS + port; 333 if (idx >= _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit)) { 334 return (BCM_E_PARAM); 335 } 336 337 *trunk_id = _xgs3_mod_port_to_tid_map[unit][idx] - 1; 338 339 return (_xgs3_mod_port_to_tid_map[unit][idx]) ? BCM_E_NONE : BCM_E_NOT_FOUND; 340 } 341 342 343 /* 344 * Function: 345 * _bcm_xgs3_trunk_mod_port_map_init 346 * Purpose: 347 * Initialize a software cache for the SOURCE_TRUNK_MAP_TABLE. 348 * Parameters: 349 * unit - (IN)SOC unit number. 350 * Returns: 351 * BCM_X_XXX 352 */ 353 int 354 _bcm_xgs3_trunk_mod_port_map_init(int unit) 355 { 356 357 int mem_size; /* Allocated memory size. */ 358 uint8 *ptr; /* Allocation pointer. */ 359 360 if (NULL != _xgs3_mod_port_to_tid_map[unit]) { 361 _bcm_xgs3_trunk_mod_port_map_deinit(unit); 362 } 363 364 /* Allocated mapping array. */ 365 mem_size = _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit) * sizeof(uint8); 366 ptr = sal_alloc(mem_size, "Mod_Port_Trunk"); 367 if (NULL == ptr) { 368 return (BCM_E_MEMORY); 369 } 370 /* Reset allocated buffer. */ 371 sal_memset(ptr, 0, mem_size); 372 373 _xgs3_mod_port_to_tid_map[unit] = ptr; 374 375 return (BCM_E_NONE); 376 } 377 378 /* 379 * Function: 380 * _bcm_xgs3_trunk_mod_port_map_deinit 381 * Purpose: 382 * Deinitialize a software cache for the SOURCE_TRUNK_MAP_TABLE. 383 * Parameters: 384 * unit - (IN)SOC unit number. 385 * Returns: 386 * BCM_X_XXX 387 */ 388 int 389 _bcm_xgs3_trunk_mod_port_map_deinit(int unit) 390 { 391 void *ptr; 392 393 ptr = (void *)_xgs3_mod_port_to_tid_map[unit]; 394 395 _xgs3_mod_port_to_tid_map[unit] = NULL; 396 397 if (NULL != ptr) { 398 sal_free(ptr); 399 } 400 return (BCM_E_NONE); 401 } 402 403 404 #if defined (BCM_WARM_BOOT_SUPPORT) 405 #ifdef BCM_HURRICANE3_SUPPORT 406 /* 407 * Function: 408 * _bcm_xgs3_trunk_mod_port_map_reinit 409 * Purpose: 410 * Reinitialize the software cache for the SOURCE_TRUNK_MAP_TABLE. 411 * Recover trunk members with egress disable flag set. 412 * Parameters: 413 * unit - (IN) SOC unit number. 414 * mod - (IN) Module ID. 415 * base_index - (IN) Module ID's base index. 416 * num_ports - (IN) Number of ports in the given module. 417 * Returns: 418 * BCM_X_XXX 419 * Notes: 420 * This function is called during stacking module reinit, since 421 * the number of ports in a given module is not known until then. 422 */ 423 int 424 _bcm_xgs3_trunk_mod_port_map_reinit(int unit, bcm_module_t mod, 425 int base_index, int num_ports) 426 { 427 bcm_port_t port; 428 int rv = BCM_E_NONE; 429 source_trunk_map_table_entry_t stm; 430 int port_type; 431 bcm_trunk_t tid; 432 int array_size; 433 bcm_module_t *mod_array = NULL; 434 bcm_port_t *port_array = NULL; 435 uint32 *flags_array = NULL; 436 int i, found; 437 438 if (!soc_feature(unit, soc_feature_src_modid_base_index)) { 439 return BCM_E_UNAVAIL; 440 } 441 442 /* 443 * Recover from SOURCE_TRUNK_MAP tables. 444 */ 445 for (port = 0; port < num_ports; port++) { 446 447 rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY, 448 base_index + port, &stm); 449 if (BCM_FAILURE(rv)) { 450 return rv; 451 } 452 453 port_type = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm, 454 PORT_TYPEf); 455 if (port_type != 1) { 456 continue; 457 } 458 459 tid = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm, TGIDf); 460 461 /* Recover source trunk map cache */ 462 rv = _bcm_xgs3_trunk_mod_port_map_set(unit, mod, port, tid); 463 if (BCM_FAILURE(rv)) { 464 return rv; 465 } 466 467 /* Allocate arrays that can accommodate an additional member, 468 * in case a new member needs to be added to the trunk group. 469 */ 470 array_size = MEMBER_INFO(unit, tid).num_ports + 1; 471 mod_array = sal_alloc(sizeof(bcm_module_t) * array_size, "mod_array"); 472 if (mod_array == NULL) { 473 return BCM_E_MEMORY; 474 } 475 sal_memset(mod_array, 0, sizeof(bcm_module_t) * array_size); 476 477 port_array = sal_alloc(sizeof(bcm_port_t) * array_size, "port_array"); 478 if (port_array == NULL) { 479 sal_free(mod_array); 480 return BCM_E_MEMORY; 481 } 482 sal_memset(port_array, 0, sizeof(bcm_port_t) * array_size); 483 484 flags_array = sal_alloc(sizeof(uint32) * array_size, "flags_array"); 485 if (flags_array == NULL) { 486 sal_free(mod_array); 487 sal_free(port_array); 488 return BCM_E_MEMORY; 489 } 490 sal_memset(flags_array, 0, sizeof(uint32) * array_size); 491 492 /* Try to find mod-port in the trunk group */ 493 found = 0; 494 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 495 mod_array[i] = MEMBER_INFO(unit, tid).modport[i] >> 8; 496 port_array[i] = MEMBER_INFO(unit, tid).modport[i] & 0xff; 497 flags_array[i] = MEMBER_INFO(unit, tid).member_flags[i]; 498 if (port_array[i] == port && mod_array[i] == mod) { 499 found = 1; 500 break; 501 } 502 } 503 504 /* If the mod-port was not found, then add it with 505 * EGRESS_DISABLE flag set. 506 */ 507 if (!found && !MEMBER_INFO(unit, tid).recovered_from_scache) { 508 /* Find where to insert */ 509 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 510 if (port > port_array[i] || mod != mod_array[i]) { 511 continue; 512 } 513 break; 514 } 515 516 /* Insert at the required location in sw state */ 517 mod_array[i] = mod; 518 port_array[i] = port; 519 flags_array[i] |= BCM_TRUNK_MEMBER_EGRESS_DISABLE; 520 521 /* Copy remaining members as is */ 522 for (; i < MEMBER_INFO(unit, tid).num_ports; i++) { 523 mod_array[i+1] = MEMBER_INFO(unit, tid).modport[i] >> 8; 524 port_array[i+1] = MEMBER_INFO(unit, tid).modport[i] & 0xff; 525 flags_array[i+1] = MEMBER_INFO(unit, tid).member_flags[i]; 526 } 527 528 MEMBER_INFO(unit, tid).num_ports++; 529 530 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 531 MEMBER_INFO(unit, tid).modport[i] = (mod_array[i] << 8) | 532 port_array[i]; 533 MEMBER_INFO(unit, tid).member_flags[i] = flags_array[i]; 534 } 535 } 536 537 sal_free(mod_array); 538 mod_array = NULL; 539 sal_free(port_array); 540 port_array = NULL; 541 sal_free(flags_array); 542 flags_array = NULL; 543 } 544 545 return rv; 546 } 547 #endif /* BCM_HURRICANE3_SUPPORT */ 548 549 /* 550 * Function: 551 * _xgs3_trunk_mod_port_map_reinit 552 * Purpose: 553 * Reinitialize a software cache for the SOURCE_TRUNK_MAP_TABLE. 554 * Parameters: 555 * unit - (IN)SOC unit number. 556 * Returns: 557 * BCM_X_XXX 558 */ 559 STATIC int 560 _xgs3_trunk_mod_port_map_reinit(int unit) 561 { 562 source_trunk_map_table_entry_t stm; /* Hw entry buffer. */ 563 soc_mem_t mem; /* Hw table memory. */ 564 int idx; /* Hw table iterator index.*/ 565 int idx_max; /* Hw table index max. */ 566 uint32 valid; /* Trunk valid indicator. */ 567 bcm_trunk_t tid; /* Trunk id. */ 568 bcm_module_t modid; /* Member module id. */ 569 bcm_port_t port; /* Member port id. */ 570 int rv = BCM_E_NONE; /* Operation return status.*/ 571 bcm_module_t om[BCM_XGS3_TRUNK_MAX_PORTCNT]; /* new mod list */ 572 bcm_port_t op[BCM_XGS3_TRUNK_MAX_PORTCNT]; /* new port list */ 573 uint32 of[BCM_XGS3_TRUNK_MAX_PORTCNT]; /* new flag list */ 574 int i, found; 575 soc_field_t tid_fld = TGIDf; 576 577 if (soc_feature(unit, soc_feature_src_tgid_valid)) { 578 tid_fld = SRC_TGIDf; 579 } 580 /* Initialize mod, port to trunk id array. */ 581 BCM_IF_ERROR_RETURN(_bcm_xgs3_trunk_mod_port_map_init(unit)); 582 583 /* 584 * Iterate over all trunk map entries & populate valid 585 * entries into sw mod, port to trunk id map array. 586 */ 587 mem = SOURCE_TRUNK_MAP_TABLEm; 588 idx_max = soc_mem_index_max(unit,mem); 589 590 soc_mem_lock(unit, mem); 591 for (idx = soc_mem_index_min(unit, mem); idx <= idx_max; idx++) { 592 /* Read hw entry. */ 593 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &stm); 594 if (BCM_FAILURE(rv)) { 595 break; 596 } 597 598 /* Check if trunk id is valid. */ 599 valid = soc_mem_field32_get(unit, mem, (uint32 *)&stm, PORT_TYPEf); 600 if (0 == valid) { 601 continue; 602 } 603 604 tid = soc_mem_field32_get(unit, mem, (uint32 *)&stm, tid_fld); 605 606 /* Translate index into modid port. */ 607 #ifdef BCM_TRX_SUPPORT 608 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 609 modid = idx / (SOC_PORT_ADDR_MAX(unit) + 1); 610 port = idx - modid * (SOC_PORT_ADDR_MAX(unit) + 1); 611 } else 612 #endif 613 { 614 modid = idx >> SOC_TRUNK_BIT_POS(unit); 615 port = idx - (modid << SOC_TRUNK_BIT_POS(unit)); 616 } 617 rv = _bcm_xgs3_trunk_mod_port_map_set(unit, modid, port, tid); 618 if (BCM_FAILURE(rv)) { 619 break; 620 } 621 622 /* Compare values with trunk groups to recreate egress disable flag */ 623 found = 0; 624 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 625 om[i] = MEMBER_INFO(unit, tid).modport[i] >> 8; 626 op[i] = MEMBER_INFO(unit, tid).modport[i] & 0xff; 627 of[i] = MEMBER_INFO(unit, tid).member_flags[i]; 628 if (op[i] == port && om[i] == modid) { 629 found = 1; 630 break; 631 } 632 } 633 634 /* If the mod-port was not found, and if member info was not recovered 635 * from scache, then add the mod-port to member info 636 */ 637 if (!found && !MEMBER_INFO(unit, tid).recovered_from_scache) { 638 /* Find where to insert */ 639 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 640 if (port > op[i] || modid != om[i]) { 641 continue; 642 } 643 break; 644 } 645 646 /* Insert at the required location in sw state */ 647 om[i] = modid; 648 op[i] = port; 649 of[i] = BCM_TRUNK_MEMBER_EGRESS_DISABLE; 650 651 /* Copy remaining values as is */ 652 for (; i < MEMBER_INFO(unit, tid).num_ports; i++) { 653 /* sw state */ 654 op[i+1] = MEMBER_INFO(unit, tid).modport[i] & 0xff; 655 om[i+1] = MEMBER_INFO(unit, tid).modport[i] >> 8; 656 of[i+1] = MEMBER_INFO(unit, tid).member_flags[i]; 657 } 658 659 MEMBER_INFO(unit, tid).num_ports++; 660 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 661 MEMBER_INFO(unit, tid).modport[i] = (om[i] << 8) | op[i]; 662 MEMBER_INFO(unit, tid).member_flags[i] = of[i]; 663 } 664 } 665 } 666 667 soc_mem_unlock(unit, mem); 668 669 return rv; 670 } 671 #endif /* BCM_WARM_BOOT_SUPPORT */ 672 673 /* 674 * Mark a mod/port pair as being in a particular trunk (or not) 675 * A negative tid sets the mod/port back to non-trunk status. 676 */ 677 STATIC int 678 _bcm_xgs3_trunk_set_port_property(int unit, 679 bcm_module_t mod, 680 bcm_port_t port, 681 int tid) 682 { 683 source_trunk_map_table_entry_t stm; 684 soc_mem_t mem; 685 int idx, rv, ptype_get, ptype_set, tid_get, tid_set; 686 soc_field_t tid_fld = TGIDf; 687 688 if (soc_feature(unit, soc_feature_src_tgid_valid)) { 689 tid_fld = SRC_TGIDf; 690 } 691 692 if (tid < 0) { 693 ptype_set = 0; /* normal port */ 694 tid_set = 0; 695 } else { 696 ptype_set = 1; /* trunk port */ 697 tid_set = tid; 698 } 699 700 BCM_IF_ERROR_RETURN 701 (_bcm_esw_src_mod_port_table_index_get(unit, mod, port, &idx)); 702 703 mem = SOURCE_TRUNK_MAP_TABLEm; 704 soc_mem_lock(unit, mem); 705 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &stm); 706 if (BCM_SUCCESS(rv)) { 707 ptype_get = soc_mem_field32_get(unit, mem, (uint32 *)&stm, PORT_TYPEf); 708 tid_get = soc_mem_field32_get(unit, mem, (uint32 *)&stm, tid_fld); 709 if ((ptype_get != ptype_set) || (tid_get != tid_set)) { 710 soc_mem_field32_set(unit, mem, (uint32 *)&stm, 711 PORT_TYPEf, ptype_set); 712 soc_mem_field32_set(unit, mem, (uint32 *)&stm, 713 tid_fld, tid_set); 714 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, &stm); 715 } 716 } 717 soc_mem_unlock(unit, mem); 718 719 /* Update SW module, port to tid mapping. */ 720 if (BCM_SUCCESS(rv)) { 721 rv = _bcm_xgs3_trunk_mod_port_map_set(unit, mod, port, tid); 722 } 723 724 return rv; 725 } 726 727 int 728 _bcm_xgs3_trunk_get_port_property(int unit, 729 bcm_module_t mod, 730 bcm_port_t port, 731 int *tid) 732 { 733 return _bcm_xgs3_trunk_mod_port_map_get(unit, mod, port, tid); 734 } 735 736 /* 737 * Function: 738 * _bcm_xgs3_trunk_fabric_find 739 * Description: 740 * Get fabric trunk id that contains the given Higig port 741 * Parameters: 742 * unit - Unit number 743 * port - Port number 744 * tid - (OUT) Fabric trunk id 745 * Returns: 746 * BCM_E_xxxx 747 */ 748 int 749 _bcm_xgs3_trunk_fabric_find(int unit, 750 bcm_port_t port, 751 int *tid) 752 { 753 bcm_trunk_chip_info_t chip_info; 754 int num_hg_trunk_groups; 755 int hgtid; 756 pbmp_t hg_pbmp, pbmp; 757 758 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 759 if (chip_info.trunk_fabric_id_min == -1) { 760 return BCM_E_NOT_FOUND; 761 } else { 762 num_hg_trunk_groups = chip_info.trunk_fabric_id_max - 763 chip_info.trunk_fabric_id_min + 1; 764 } 765 766 if ((SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) && 767 soc_feature(unit, soc_feature_hg_trunking)) { 768 uint32 val; 769 soc_field_t bmapf; 770 771 SOC_IF_ERROR_RETURN(READ_HIGIG_TRUNK_CONTROLr(unit, &val)); 772 for (hgtid = 0; hgtid < num_hg_trunk_groups; hgtid++) { 773 switch (hgtid) { 774 case 0: 775 bmapf = HIGIG_TRUNK_BITMAP0f; 776 break; 777 case 1: 778 bmapf = HIGIG_TRUNK_BITMAP1f; 779 break; 780 default: 781 return BCM_E_INTERNAL; 782 } 783 784 SOC_PBMP_CLEAR(hg_pbmp); 785 SOC_PBMP_WORD_SET(hg_pbmp, 0, 786 soc_reg_field_get(unit, HIGIG_TRUNK_CONTROLr, 787 val, bmapf)); 788 SOC_PBMP_CLEAR(pbmp); 789 if (SOC_IS_RAVEN(unit)) { 790 /* For Raven, use the bitmap directly */ 791 SOC_PBMP_ASSIGN(pbmp, hg_pbmp); 792 } else { 793 /* For other FBX, convert to the physical bitmap */ 794 SOC_IF_ERROR_RETURN 795 (soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbmp, &pbmp)); 796 } 797 if (SOC_PBMP_MEMBER(pbmp, port)) { 798 *tid = hgtid + chip_info.trunk_fabric_id_min; 799 return BCM_E_NONE; 800 } 801 } 802 return BCM_E_NOT_FOUND; 803 } 804 #if defined(BCM_TRIUMPH2_SUPPORT) 805 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 806 SOC_IS_VALKYRIE2(unit)) { 807 uint64 val64; 808 809 for (hgtid = 0; hgtid < num_hg_trunk_groups; hgtid++) { 810 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_BITMAP_64r(unit, hgtid, &val64)); 811 SOC_PBMP_CLEAR(hg_pbmp); 812 SOC_PBMP_WORD_SET(hg_pbmp, 0, 813 soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r, 814 val64, HIGIG_TRUNK_BITMAP_LOf)); 815 SOC_PBMP_WORD_SET(hg_pbmp, 1, 816 soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r, 817 val64, HIGIG_TRUNK_BITMAP_HIf)); 818 if (SOC_PBMP_MEMBER(hg_pbmp, port)) { 819 *tid = hgtid + chip_info.trunk_fabric_id_min; 820 return BCM_E_NONE; 821 } 822 } 823 return BCM_E_NOT_FOUND; 824 } 825 #endif /* BCM_TRIUMPH2_SUPPORT */ 826 #ifdef BCM_GREYHOUND2_SUPPORT 827 if (soc_feature(unit, soc_feature_high_portcount_register)) { 828 uint64 val64, hg_trunk_bmap_f; 829 830 for (hgtid = 0; hgtid < num_hg_trunk_groups; hgtid++) { 831 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_BITMAP_LOr(unit, hgtid, &val64)); 832 hg_trunk_bmap_f = 833 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_LOr, 834 val64, HIGIG_TRUNK_BITMAPf); 835 836 SOC_PBMP_CLEAR(hg_pbmp); 837 SOC_PBMP_WORD_SET(hg_pbmp, 0, COMPILER_64_LO(hg_trunk_bmap_f)); 838 SOC_PBMP_WORD_SET(hg_pbmp, 1, COMPILER_64_HI(hg_trunk_bmap_f)); 839 840 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_BITMAP_HIr(unit, hgtid, &val64)); 841 hg_trunk_bmap_f = 842 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_HIr, 843 val64, HIGIG_TRUNK_BITMAPf); 844 845 SOC_PBMP_WORD_SET(hg_pbmp, 2, COMPILER_64_LO(hg_trunk_bmap_f)); 846 847 if (SOC_PBMP_MEMBER(hg_pbmp, port)) { 848 *tid = hgtid + chip_info.trunk_fabric_id_min; 849 return BCM_E_NONE; 850 } 851 } 852 return BCM_E_NOT_FOUND; 853 } 854 #endif /* BCM_GREYHOUND2_SUPPORT */ 855 #if defined(BCM_BRADLEY_SUPPORT) 856 if (SOC_IS_HBX(unit) || SOC_IS_TRX(unit)) { 857 uint32 val; 858 859 for (hgtid = 0; hgtid < num_hg_trunk_groups; hgtid++) { 860 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_BITMAPr(unit, hgtid, &val)); 861 SOC_PBMP_CLEAR(hg_pbmp); 862 SOC_PBMP_WORD_SET(hg_pbmp, 0, 863 soc_reg_field_get(unit, HG_TRUNK_BITMAPr, 864 val, HIGIG_TRUNK_BITMAPf)); 865 SOC_PBMP_CLEAR(pbmp); 866 soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbmp, &pbmp); 867 if (SOC_PBMP_MEMBER(pbmp, port)) { 868 *tid = hgtid + chip_info.trunk_fabric_id_min; 869 return BCM_E_NONE; 870 } 871 } 872 return BCM_E_NOT_FOUND; 873 } 874 #endif /* BCM_BRADLEY_SUPPORT */ 875 876 return BCM_E_UNAVAIL; 877 } 878 879 /* 880 * Update the trunk block mask table. 881 * Old ports are cleared and new ports are added to each entry. 882 * Each hash index location entry is owned by a specific unit/modid 883 * across all units in a stack. Hash index location entry owned by 884 * local unit/modid is provided by my_modid_bmap. member_count is 885 * the number of NUC forwarding eligible ports in the trunk group. 886 * Each eligible entry also has a rolling port that is not masked 887 * from among the new NUC forwarding eligible ports (nuc_ports). 888 * This is what spreads non-unicast traffic across multiple ports. 889 */ 890 STATIC int 891 _bcm_xgs3_trunk_block_mask(int unit, 892 pbmp_t old_ports, 893 pbmp_t new_ports, 894 pbmp_t nuc_ports, 895 uint32 my_modid_bmap, 896 uint32 member_count) 897 { 898 bcm_port_t port; 899 int localcount, localports[BCM_XGS3_TRUNK_MAX_PORTCNT]; 900 int index_count, max_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 901 902 localcount = 0; 903 #if defined(BCM_SCORPION_SUPPORT) 904 if (SOC_IS_SC_CQ(unit)) { 905 max_ports = BCM_XGS3_TRUNK_MAX_PORTCNT; 906 } 907 #endif 908 if (SOC_PBMP_NOT_NULL(nuc_ports)) { 909 PBMP_ITER(nuc_ports, port) { 910 localports[localcount++] = port; 911 if (localcount >= max_ports) { 912 break; 913 } 914 } 915 } 916 917 #if defined(BCM_FIREBOLT_SUPPORT) 918 if (SOC_IS_FBX(unit)) { 919 int i, imax, rv; 920 soc_mem_t mem; 921 nonucast_trunk_block_mask_entry_t mask_entry; 922 bcm_pbmp_t pbmp, old_pbmp; 923 924 rv = BCM_E_NONE; 925 mem = NONUCAST_TRUNK_BLOCK_MASKm; 926 i = soc_mem_index_min(unit, mem); 927 imax = soc_mem_index_max(unit, mem); 928 soc_mem_lock(unit, mem); 929 index_count = 0; 930 for (; i <= imax; i++) { 931 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, &mask_entry); 932 if (rv < 0) { 933 break; 934 } 935 soc_mem_pbmp_field_get(unit, mem, &mask_entry, BLOCK_MASKf, &pbmp); 936 old_pbmp = pbmp; 937 SOC_PBMP_REMOVE(pbmp, old_ports); 938 SOC_PBMP_OR(pbmp, new_ports); 939 if (localcount > 0) { 940 if ((i % 16) == 0) { 941 /* On Firebolt, NONUCAST_TRUNK_BLOCK_MASK contains 16 942 * entries. On Triumph, there are 64 entries, separated 943 * into 4 regions: IPMC, L2MC, broadcast, and unknown 944 * packets. To make Firebolt interoperate with Triumph, 945 * the index_count needs to be reset every 16 entries. 946 */ 947 index_count = 0; 948 } 949 if (my_modid_bmap & (1 << ((i & 0xf) % member_count))) { 950 SOC_PBMP_PORT_REMOVE(pbmp, localports[index_count % localcount]); 951 index_count++; 952 } 953 } 954 if (SOC_PBMP_EQ(pbmp, old_pbmp)) { 955 continue; 956 } 957 soc_mem_pbmp_field_set(unit, mem, &mask_entry, BLOCK_MASKf, &pbmp); 958 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, &mask_entry); 959 if (rv < 0) { 960 break; 961 } 962 } 963 soc_mem_unlock(unit, mem); 964 return rv; 965 } 966 #endif /* BCM_FIREBOLT_SUPPORT */ 967 968 return BCM_E_NONE; 969 } 970 971 STATIC int 972 _bcm_xgs3_trunk_psc_to_rtag(int unit, int psc, int *rtag) 973 { 974 switch (psc) { 975 case BCM_TRUNK_PSC_SRCMAC: 976 case BCM_TRUNK_PSC_DSTMAC: 977 case BCM_TRUNK_PSC_SRCDSTMAC: 978 case BCM_TRUNK_PSC_SRCIP: 979 case BCM_TRUNK_PSC_DSTIP: 980 case BCM_TRUNK_PSC_SRCDSTIP: 981 /* These BCM_TRUNK_PSC_ values match the hardware RTAG values */ 982 *rtag = psc; 983 break; 984 case BCM_TRUNK_PSC_PORTINDEX: 985 if (!soc_feature(unit, soc_feature_port_trunk_index)) { 986 return BCM_E_PARAM; 987 } 988 *rtag = 7; 989 break; 990 case BCM_TRUNK_PSC_PORTFLOW: 991 if (!soc_feature(unit, soc_feature_port_flow_hash)) { 992 return BCM_E_PARAM; 993 } 994 *rtag = 7; 995 break; 996 case BCM_TRUNK_PSC_DYNAMIC: 997 case BCM_TRUNK_PSC_DYNAMIC_ASSIGNED: 998 case BCM_TRUNK_PSC_DYNAMIC_OPTIMAL: 999 *rtag = 7; 1000 if (SOC_IS_ENDURO(unit)) { 1001 if (!soc_feature(unit, soc_feature_lag_dlb)) { 1002 return BCM_E_UNAVAIL; 1003 } 1004 } 1005 break; 1006 default: 1007 return BCM_E_PARAM; 1008 } 1009 1010 if ((*rtag == 7) && 1011 (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit))) { 1012 /* Hurricanex/Greyhound don't support enhanced hashing */ 1013 return BCM_E_PARAM; 1014 } 1015 1016 return BCM_E_NONE; 1017 } 1018 1019 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 1020 int 1021 _bcm_xgs3_trunk_hwfailover_init(int unit) 1022 { 1023 if (_xgs3_trunk_hwfail[unit] == NULL) { 1024 _xgs3_trunk_hwfail[unit] = sal_alloc(sizeof(_xgs3_trunk_hwfail_t), 1025 "_xgs3_trunk_hwfail"); 1026 if (_xgs3_trunk_hwfail[unit] == NULL) { 1027 return BCM_E_MEMORY; 1028 } 1029 } 1030 sal_memset(_xgs3_trunk_hwfail[unit], 0, sizeof(_xgs3_trunk_hwfail_t)); 1031 return BCM_E_NONE; 1032 } 1033 1034 void 1035 _bcm_xgs3_trunk_hwfailover_detach(int unit) 1036 { 1037 if (_xgs3_trunk_hwfail[unit] != NULL) { 1038 sal_free(_xgs3_trunk_hwfail[unit]); 1039 _xgs3_trunk_hwfail[unit] = NULL; 1040 } 1041 } 1042 1043 static soc_field_t _hg_trunk_failover_portf[_BCM_SCORPION_FABRIC_TRUNK_FAILOVER_PORT_NUM] = { 1044 PORT0f, PORT1f, PORT2f, PORT3f, 1045 PORT4f, PORT5f, PORT6f, PORT7f, 1046 PORT8f, PORT9f, PORT10f, PORT11f, 1047 PORT12f, PORT13f, PORT14f, PORT15f 1048 }; 1049 1050 static soc_field_t _trunk_failover_portf[_BCM_TRUNK_FAILOVER_PORT_NUM] = { 1051 PORT0f, PORT1f, PORT2f, PORT3f, 1052 PORT4f, PORT5f, PORT6f, PORT7f 1053 }; 1054 1055 static soc_field_t _trunk_failover_modulef[_BCM_TRUNK_FAILOVER_PORT_NUM] = { 1056 MODULE0f, MODULE1f, MODULE2f, MODULE3f, 1057 MODULE4f, MODULE5f, MODULE6f, MODULE7f 1058 }; 1059 1060 STATIC int 1061 _bcm_xgs3_trunk_hwfailover_hg_write(int unit, bcm_port_t failport, int rtag, 1062 int hw_count, bcm_port_t *ftp) 1063 { 1064 hg_trunk_failover_set_entry_t fail_entry; 1065 uint32 val, oval = 0; 1066 bcm_pbmp_t fail_ports, hgp; 1067 bcm_port_t hg_failport; 1068 int ix, fs_ports; 1069 #ifdef BCM_GREYHOUND2_SUPPORT 1070 uint64 val64_hi, oval64_hi; 1071 uint64 hg_trunk_bmap_f; 1072 #endif /* BCM_GREYHOUND2_SUPPORT */ 1073 #ifdef BCM_TRIUMPH2_SUPPORT 1074 uint64 val64, oval64; 1075 COMPILER_64_ZERO(oval64); 1076 #endif 1077 1078 #ifdef BCM_GREYHOUND2_SUPPORT 1079 COMPILER_64_ZERO(oval64_hi); 1080 #endif /* BCM_GREYHOUND2_SUPPORT */ 1081 1082 if(SOC_IS_SC_CQ(unit) && !IS_GX_PORT(unit, failport)) { 1083 /* We should never hit this case for a fabric trunk */ 1084 return BCM_E_PORT; 1085 } 1086 1087 sal_memset(&fail_entry, 0, sizeof(fail_entry)); 1088 1089 if (hw_count) { /* Enabling HG trunk failover */ 1090 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1091 SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND(unit) || 1092 SOC_IS_HURRICANE3(unit) || 1093 soc_feature(unit, soc_feature_high_portcount_register)) { 1094 /* These devices have a 1-1 mapping for HG port number */ 1095 hg_failport = failport; 1096 } else { 1097 SOC_IF_ERROR_RETURN 1098 (soc_xgs3_port_num_to_higig_port_num(unit, failport, 1099 &hg_failport)); 1100 } 1101 if (soc_mem_field_valid(unit, HG_TRUNK_FAILOVER_SETm, 1102 FAILOVER_SET_SIZEf)) { 1103 soc_mem_field32_set(unit, HG_TRUNK_FAILOVER_SETm, 1104 (uint32 *)&fail_entry, 1105 FAILOVER_SET_SIZEf, hw_count - 1); 1106 } 1107 soc_mem_field32_set(unit, HG_TRUNK_FAILOVER_SETm, 1108 (uint32 *)&fail_entry, RTAGf, rtag); 1109 1110 fs_ports = SOC_IS_SC_CQ(unit) ? 1111 _BCM_SCORPION_FABRIC_TRUNK_FAILOVER_PORT_NUM : 1112 (SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) ? 1113 _BCM_HURRICANE2_TRUNK_FAILOVER_PORT_NUM : 1114 _BCM_TRUNK_FAILOVER_PORT_NUM; 1115 1116 for (ix = 0; ix < fs_ports; ix++) { 1117 soc_mem_field32_set(unit, HG_TRUNK_FAILOVER_SETm, 1118 (uint32 *)&fail_entry, 1119 _hg_trunk_failover_portf[ix], 1120 ftp[ix % hw_count]); 1121 } 1122 SOC_IF_ERROR_RETURN 1123 (WRITE_HG_TRUNK_FAILOVER_SETm(unit, MEM_BLOCK_ALL, hg_failport, 1124 &fail_entry)); 1125 } 1126 1127 /* Update HG trunk mode selection bitmap */ 1128 SOC_PBMP_CLEAR(fail_ports); 1129 #ifdef BCM_TRIUMPH2_SUPPORT 1130 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1131 SOC_IS_VALKYRIE2(unit)) { 1132 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_64r(unit, &val64)); 1133 COMPILER_64_SET(oval64, COMPILER_64_HI(val64), 1134 COMPILER_64_LO(val64)); 1135 SOC_PBMP_WORD_SET(fail_ports, 0, 1136 soc_reg64_field32_get(unit, HG_TRUNK_FAILOVER_ENABLE_64r, 1137 val64, BITMAP_LOf)); 1138 SOC_PBMP_WORD_SET(fail_ports, 1, 1139 soc_reg64_field32_get(unit, HG_TRUNK_FAILOVER_ENABLE_64r, 1140 val64, BITMAP_HIf)); 1141 } else 1142 #endif 1143 #ifdef BCM_GREYHOUND2_SUPPORT 1144 if (soc_feature(unit, soc_feature_high_portcount_register)) { 1145 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_LOr(unit, &val64)); 1146 COMPILER_64_SET(oval64, COMPILER_64_HI(val64), 1147 COMPILER_64_LO(val64)); 1148 hg_trunk_bmap_f = soc_reg64_field_get(unit, 1149 HG_TRUNK_FAILOVER_ENABLE_LOr, val64, BITMAPf); 1150 1151 SOC_PBMP_WORD_SET(fail_ports, 0, COMPILER_64_LO(hg_trunk_bmap_f)); 1152 SOC_PBMP_WORD_SET(fail_ports, 1, COMPILER_64_HI(hg_trunk_bmap_f)); 1153 1154 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_HIr(unit, &val64_hi)); 1155 COMPILER_64_SET(oval64_hi, COMPILER_64_HI(val64_hi), 1156 COMPILER_64_LO(val64_hi)); 1157 hg_trunk_bmap_f = soc_reg64_field_get(unit, 1158 HG_TRUNK_FAILOVER_ENABLE_HIr, val64_hi, BITMAPf); 1159 1160 SOC_PBMP_WORD_SET(fail_ports, 2, COMPILER_64_LO(hg_trunk_bmap_f)); 1161 1162 } else 1163 #endif /* BCM_GREYHOUND2_SUPPORT */ 1164 { 1165 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLEr(unit, &val)); 1166 oval = val; 1167 SOC_PBMP_CLEAR(hgp); 1168 SOC_PBMP_WORD_SET(hgp, 0, 1169 soc_reg_field_get(unit, HG_TRUNK_FAILOVER_ENABLEr, 1170 val, BITMAPf)); 1171 SOC_IF_ERROR_RETURN 1172 (soc_xgs3_higig_bitmap_to_bitmap(unit, hgp, &fail_ports)); 1173 } 1174 1175 if (hw_count) { 1176 SOC_PBMP_PORT_ADD(fail_ports, failport); 1177 } else { 1178 SOC_PBMP_PORT_REMOVE(fail_ports, failport); 1179 } 1180 1181 #ifdef BCM_TRIUMPH2_SUPPORT 1182 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1183 SOC_IS_VALKYRIE2(unit)) { 1184 soc_reg64_field32_set(unit, HG_TRUNK_FAILOVER_ENABLE_64r, &val64, 1185 BITMAP_LOf, SOC_PBMP_WORD_GET(fail_ports, 0)); 1186 soc_reg64_field32_set(unit, HG_TRUNK_FAILOVER_ENABLE_64r, &val64, 1187 BITMAP_HIf, SOC_PBMP_WORD_GET(fail_ports, 1)); 1188 if (COMPILER_64_NE(val64, oval64)) { 1189 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_FAILOVER_ENABLE_64r(unit, val64)); 1190 } 1191 } else 1192 #endif 1193 #ifdef BCM_GREYHOUND2_SUPPORT 1194 if (soc_feature(unit, soc_feature_high_portcount_register)) { 1195 COMPILER_64_SET(hg_trunk_bmap_f, SOC_PBMP_WORD_GET(fail_ports, 1), 1196 SOC_PBMP_WORD_GET(fail_ports, 0)); 1197 soc_reg64_field_set(unit, HG_TRUNK_FAILOVER_ENABLE_LOr, &val64, 1198 BITMAPf, hg_trunk_bmap_f); 1199 COMPILER_64_SET(hg_trunk_bmap_f, 0, 1200 SOC_PBMP_WORD_GET(fail_ports, 2)); 1201 soc_reg64_field_set(unit, HG_TRUNK_FAILOVER_ENABLE_HIr, &val64_hi, 1202 BITMAPf, hg_trunk_bmap_f); 1203 if (COMPILER_64_NE(val64, oval64)) { 1204 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_FAILOVER_ENABLE_LOr(unit, val64)); 1205 } 1206 if (COMPILER_64_NE(val64_hi, oval64_hi)) { 1207 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_FAILOVER_ENABLE_HIr(unit, val64_hi)); 1208 } 1209 } else 1210 #endif /* BCM_GREYHOUND2_SUPPORT */ 1211 { 1212 SOC_PBMP_CLEAR(hgp); 1213 SOC_IF_ERROR_RETURN 1214 (soc_xgs3_bitmap_to_higig_bitmap(unit, fail_ports, &hgp)); 1215 soc_reg_field_set(unit, HG_TRUNK_FAILOVER_ENABLEr, &val, BITMAPf, 1216 SOC_PBMP_WORD_GET(hgp, 0)); 1217 if (val != oval) { 1218 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_FAILOVER_ENABLEr(unit, val)); 1219 } 1220 } 1221 1222 return BCM_E_NONE; 1223 } 1224 1225 STATIC int 1226 _bcm_xgs3_trunk_hwfailover_hg_read(int unit, bcm_port_t failport, 1227 int array_size, int *rtag, 1228 bcm_port_t *ftp, bcm_module_t *ftm, 1229 int *array_count) 1230 { 1231 hg_trunk_failover_set_entry_t fail_entry; 1232 uint32 val; 1233 bcm_pbmp_t fail_ports, hgp; 1234 bcm_port_t hg_failport; 1235 int ix, hw_count = 0; 1236 #ifdef BCM_TRIUMPH2_SUPPORT 1237 uint64 val64; 1238 #endif 1239 #ifdef BCM_GREYHOUND2_SUPPORT 1240 uint64 hg_trunk_bmap_f; 1241 #endif /* BCM_GREYHOUND2_SUPPORT */ 1242 1243 #ifdef BCM_TRIUMPH2_SUPPORT 1244 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1245 SOC_IS_VALKYRIE2(unit)) { 1246 /* These devices have a 1-1 mapping for HG port number */ 1247 hg_failport = failport; 1248 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_64r(unit, &val64)); 1249 SOC_PBMP_WORD_SET(fail_ports, 0, 1250 soc_reg64_field32_get(unit, HG_TRUNK_FAILOVER_ENABLE_64r, 1251 val64, BITMAP_LOf)); 1252 SOC_PBMP_WORD_SET(fail_ports, 1, 1253 soc_reg64_field32_get(unit, HG_TRUNK_FAILOVER_ENABLE_64r, 1254 val64, BITMAP_HIf)); 1255 } else 1256 #endif 1257 #ifdef BCM_GREYHOUND2_SUPPORT 1258 if (soc_feature(unit, soc_feature_high_portcount_register)) { 1259 /* These devices have a 1-1 mapping for HG port number */ 1260 hg_failport = failport; 1261 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_LOr(unit, &val64)); 1262 hg_trunk_bmap_f = soc_reg64_field_get(unit, 1263 HG_TRUNK_FAILOVER_ENABLE_LOr, val64, BITMAPf); 1264 1265 SOC_PBMP_WORD_SET(fail_ports, 0, COMPILER_64_LO(hg_trunk_bmap_f)); 1266 SOC_PBMP_WORD_SET(fail_ports, 1, COMPILER_64_HI(hg_trunk_bmap_f)); 1267 1268 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLE_HIr(unit, &val64)); 1269 hg_trunk_bmap_f = soc_reg64_field_get(unit, 1270 HG_TRUNK_FAILOVER_ENABLE_HIr, val64, BITMAPf); 1271 1272 SOC_PBMP_WORD_SET(fail_ports, 2, COMPILER_64_LO(hg_trunk_bmap_f)); 1273 } else 1274 #endif /* BCM_GREYHOUND2_SUPPORT */ 1275 { 1276 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) { 1277 hg_failport = failport; 1278 } else { 1279 SOC_IF_ERROR_RETURN 1280 (soc_xgs3_port_num_to_higig_port_num(unit, failport, 1281 &hg_failport)); 1282 } 1283 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_FAILOVER_ENABLEr(unit, &val)); 1284 SOC_PBMP_CLEAR(hgp); 1285 SOC_PBMP_WORD_SET(hgp, 0, 1286 soc_reg_field_get(unit, HG_TRUNK_FAILOVER_ENABLEr, 1287 val, BITMAPf)); 1288 SOC_PBMP_CLEAR(fail_ports); 1289 SOC_IF_ERROR_RETURN 1290 (soc_xgs3_higig_bitmap_to_bitmap(unit, hgp, &fail_ports)); 1291 } 1292 1293 if (SOC_PBMP_MEMBER(fail_ports, failport)) { 1294 SOC_IF_ERROR_RETURN 1295 (READ_HG_TRUNK_FAILOVER_SETm(unit, MEM_BLOCK_ALL, hg_failport, 1296 &fail_entry)); 1297 1298 if (soc_mem_field_valid(unit, HG_TRUNK_FAILOVER_SETm, 1299 FAILOVER_SET_SIZEf)) { 1300 hw_count = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm, 1301 (uint32 *)&fail_entry, 1302 FAILOVER_SET_SIZEf) + 1; 1303 } else { 1304 hw_count = SOC_IS_SC_CQ(unit) ? 1305 _BCM_SCORPION_FABRIC_TRUNK_FAILOVER_PORT_NUM : 1306 (SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) ? 1307 _BCM_HURRICANE2_TRUNK_FAILOVER_PORT_NUM : 1308 _BCM_TRUNK_FAILOVER_PORT_NUM; 1309 } 1310 1311 if (((NULL != ftp) || (NULL != ftm)) && (hw_count > array_size)) { 1312 hw_count = array_size; 1313 } 1314 for (ix = 0; ix < hw_count; ix++) { 1315 if (NULL != ftm) { 1316 ftm[ix] = 0; 1317 } 1318 if (NULL != ftp) { 1319 ftp[ix] = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm, 1320 (uint32 *)&fail_entry, 1321 _hg_trunk_failover_portf[ix]); 1322 } 1323 } 1324 if (NULL != rtag) { 1325 *rtag = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm, 1326 (uint32 *)&fail_entry, RTAGf); 1327 } 1328 if (NULL != array_count) { 1329 *array_count = hw_count; 1330 } 1331 } else { 1332 if (NULL != array_count) { 1333 *array_count = 0; 1334 } 1335 } 1336 return BCM_E_NONE; 1337 } 1338 1339 STATIC int 1340 _bcm_xgs3_trunk_hwfailover_write(int unit, bcm_port_t failport, int rtag, 1341 int hw_count, 1342 bcm_port_t *ftp, bcm_module_t *ftm) 1343 { 1344 port_lag_failover_set_entry_t fail_entry; 1345 uint32 val, oval; 1346 int ix, mirror_enable; 1347 1348 if(SOC_IS_SC_CQ(unit) && !IS_GX_PORT(unit, failport)) { 1349 /* Not supported, but no error due to trunk config implicit use */ 1350 return BCM_E_NONE; 1351 } 1352 1353 SOC_IF_ERROR_RETURN 1354 (READ_GXPORT_LAG_FAILOVER_STATUSr(unit, failport, &val)); 1355 if (soc_reg_field_get(unit, GXPORT_LAG_FAILOVER_STATUSr, 1356 val, LAG_FAILOVER_LOOPBACKf)) { 1357 /* 1358 * Already in failover mode. Do not change HW settings! 1359 * This should be dealt with as part of the port link processing. 1360 */ 1361 if (hw_count == 0) { 1362 /* Notify linkscan of port removal from trunk */ 1363 BCM_IF_ERROR_RETURN 1364 (_bcm_esw_link_failover_set(unit, failport, FALSE)); 1365 return BCM_E_NONE; 1366 } else { 1367 return BCM_E_PORT; 1368 } 1369 } 1370 1371 if (hw_count) { /* Enabling trunk failover */ 1372 /* We must be in directed mirroring mode to use this feature */ 1373 BCM_IF_ERROR_RETURN 1374 (bcm_esw_switch_control_get(unit, bcmSwitchDirectedMirroring, 1375 &mirror_enable)); 1376 if (!mirror_enable) { 1377 return BCM_E_CONFIG; 1378 } 1379 1380 sal_memset(&fail_entry, 0, sizeof(fail_entry)); 1381 soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm, 1382 (uint32 *)&fail_entry, 1383 FAILOVER_SET_SIZEf, hw_count - 1); 1384 soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm, 1385 (uint32 *)&fail_entry, RTAGf, rtag); 1386 1387 for (ix = 0; ix < _BCM_TRUNK_FAILOVER_PORT_NUM; ix++) { 1388 soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm, 1389 (uint32 *)&fail_entry, 1390 _trunk_failover_portf[ix], 1391 ftp[ix % hw_count]); 1392 soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm, 1393 (uint32 *)&fail_entry, 1394 _trunk_failover_modulef[ix], 1395 ftm[ix % hw_count]); 1396 } 1397 SOC_IF_ERROR_RETURN 1398 (WRITE_PORT_LAG_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport, 1399 &fail_entry)); 1400 } 1401 1402 SOC_IF_ERROR_RETURN 1403 (READ_GXPORT_LAG_FAILOVER_CONFIGr(unit, failport, &val)); 1404 oval = val; 1405 soc_reg_field_set(unit, GXPORT_LAG_FAILOVER_CONFIGr, &val, 1406 LAG_FAILOVER_ENf, (hw_count != 0) ? 1 : 0); 1407 if (val != oval) { 1408 SOC_IF_ERROR_RETURN 1409 (WRITE_GXPORT_LAG_FAILOVER_CONFIGr(unit, failport, val)); 1410 } 1411 1412 /* Notify linkscan of failover status */ 1413 BCM_IF_ERROR_RETURN 1414 (_bcm_esw_link_failover_set(unit, failport, (hw_count != 0))); 1415 1416 return BCM_E_NONE; 1417 } 1418 1419 STATIC int 1420 _bcm_xgs3_trunk_hwfailover_read(int unit, bcm_port_t failport, 1421 int array_size, int *rtag, 1422 bcm_port_t *ftp, bcm_module_t *ftm, 1423 int *array_count) 1424 { 1425 port_lag_failover_set_entry_t fail_entry; 1426 uint32 val; 1427 int ix, hw_count, enable = FALSE; 1428 1429 1430 if(IS_GX_PORT(unit, failport)) { 1431 SOC_IF_ERROR_RETURN 1432 (READ_GXPORT_LAG_FAILOVER_CONFIGr(unit, failport, &val)); 1433 enable = soc_reg_field_get(unit, GXPORT_LAG_FAILOVER_CONFIGr, val, 1434 LAG_FAILOVER_ENf); 1435 } 1436 1437 if (enable) { 1438 SOC_IF_ERROR_RETURN 1439 (READ_PORT_LAG_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport, 1440 &fail_entry)); 1441 hw_count = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm, 1442 (uint32 *)&fail_entry, 1443 FAILOVER_SET_SIZEf) + 1; 1444 if (((NULL != ftp) || (NULL != ftm)) && (hw_count > array_size)) { 1445 hw_count = array_size; 1446 } 1447 for (ix = 0; ix < hw_count; ix++) { 1448 if (NULL != ftp) { 1449 ftp[ix] = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm, 1450 (uint32 *)&fail_entry, 1451 _trunk_failover_portf[ix]); 1452 } 1453 if (NULL != ftm) { 1454 ftm[ix] = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm, 1455 (uint32 *)&fail_entry, 1456 _trunk_failover_modulef[ix]); 1457 } 1458 } 1459 if (NULL != rtag) { 1460 *rtag = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm, 1461 (uint32 *)&fail_entry, RTAGf); 1462 } 1463 if (NULL != array_count) { 1464 *array_count = hw_count; 1465 } 1466 } else { 1467 if (NULL != array_count) { 1468 *array_count = 0; 1469 } 1470 if (NULL != rtag) { 1471 *rtag = 0; 1472 } 1473 } 1474 1475 return BCM_E_NONE; 1476 } 1477 1478 int 1479 _bcm_xgs3_trunk_hwfailover_set(int unit, bcm_trunk_t tid, int hg_trunk, 1480 bcm_port_t port, bcm_module_t modid, 1481 int psc, uint32 flags, int count, 1482 bcm_port_t *ftp, bcm_module_t *ftm) 1483 { 1484 int ix, tix, tid_ix, tports, next, local, mod_is_local, hw_count, rtag; 1485 uint8 tp_mod; 1486 uint16 fail_modport; 1487 bcm_gport_t gport; 1488 bcm_port_t local_port, port_list[BCM_XGS3_TRUNK_MAX_PORTCNT]; 1489 bcm_module_t modid_list[BCM_XGS3_TRUNK_MAX_PORTCNT]; 1490 _xgs3_hw_tinfo_t *hwft; 1491 1492 /* Need the HW port number for the table write later */ 1493 if (hg_trunk) { 1494 fail_modport = local_port = port; 1495 } else { 1496 BCM_GPORT_MODPORT_SET(gport, modid, port); 1497 BCM_IF_ERROR_RETURN 1498 (bcm_esw_port_local_get(unit, gport, &local_port)); 1499 1500 fail_modport = (modid << 8) | port; 1501 } 1502 1503 BCM_IF_ERROR_RETURN 1504 (_bcm_xgs3_trunk_psc_to_rtag(unit, psc, &rtag)); 1505 1506 tid_ix = tid + (hg_trunk ? _BCM_FP_TRUNK_NUM_MAX : 0); 1507 hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix]); 1508 1509 /* Where is our port in the trunk list? */ 1510 tports = hwft->num_ports; 1511 for (tix = 0; tix < tports; tix++) { 1512 if (fail_modport == hwft->modport[tix]) { 1513 break; 1514 } 1515 } 1516 1517 if ((0 != count) && (tix == tports)) { 1518 /* Port not in trunk! */ 1519 return BCM_E_NOT_FOUND; 1520 } 1521 1522 if (flags) { 1523 switch (flags) { 1524 case BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL: 1525 next = TRUE; 1526 local = TRUE; 1527 break; 1528 case BCM_TRUNK_FLAG_FAILOVER_NEXT: 1529 next = TRUE; 1530 local = FALSE; 1531 break; 1532 case BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL: 1533 next = FALSE; 1534 local = TRUE; 1535 break; 1536 case BCM_TRUNK_FLAG_FAILOVER_ALL: 1537 next = FALSE; 1538 local = FALSE; 1539 break; 1540 default: 1541 /* Illegal flags setting */ 1542 return BCM_E_PARAM; 1543 } 1544 1545 hw_count = 0; 1546 1547 for (ix = ((tix + 1) % tports); /* Start after fail port */ 1548 ix != tix; /* Stop when we get back */ 1549 ix = ((ix + 1) % tports)) { /* Cycle through trunk port list */ 1550 tp_mod = hwft->modport[ix] >> 8; 1551 if (local && !hg_trunk) { 1552 BCM_IF_ERROR_RETURN 1553 (_bcm_esw_modid_is_local(unit, tp_mod, 1554 &mod_is_local)); 1555 if (!mod_is_local) { 1556 continue; 1557 } 1558 } 1559 port_list[hw_count] = hwft->modport[ix] & 0xff; 1560 modid_list[hw_count] = tp_mod; 1561 hw_count++; 1562 if (next) { 1563 break; 1564 } 1565 } 1566 } else { 1567 if (count) { 1568 for (ix = 0; ix < count; ix++) { 1569 port_list[ix] = ftp[ix]; 1570 modid_list[ix] = ftm[ix]; 1571 } 1572 } 1573 hw_count = count; 1574 } 1575 1576 if (hg_trunk) { 1577 BCM_IF_ERROR_RETURN 1578 (_bcm_xgs3_trunk_hwfailover_hg_write(unit, local_port, rtag, 1579 hw_count, port_list)); 1580 } else { 1581 BCM_IF_ERROR_RETURN 1582 (_bcm_xgs3_trunk_hwfailover_write(unit, local_port, rtag, 1583 hw_count, port_list, modid_list)); 1584 } 1585 1586 if (tix < hwft->num_ports) { 1587 hwft->flags[tix] = flags; 1588 hwft->psc[tix] = psc; 1589 } 1590 return BCM_E_NONE; 1591 } 1592 1593 int 1594 _bcm_xgs3_trunk_hwfailover_get(int unit, bcm_trunk_t tid, int hg_trunk, 1595 bcm_port_t port, bcm_module_t modid, 1596 int *psc, uint32 *flags, int array_size, 1597 bcm_port_t *ftp, bcm_module_t *ftm, 1598 int *array_count) 1599 { 1600 int tix, tid_ix, tports; 1601 uint16 fail_modport; 1602 bcm_gport_t gport; 1603 bcm_port_t local_port; 1604 _xgs3_hw_tinfo_t *hwft; 1605 1606 /* Need the HW port number for the table write later */ 1607 if (hg_trunk) { 1608 fail_modport = local_port = port; 1609 } else { 1610 BCM_GPORT_MODPORT_SET(gport, modid, port); 1611 BCM_IF_ERROR_RETURN 1612 (bcm_esw_port_local_get(unit, gport, &local_port)); 1613 1614 fail_modport = (modid << 8) | port; 1615 } 1616 1617 tid_ix = tid + (hg_trunk ? _BCM_FP_TRUNK_NUM_MAX : 0); 1618 hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix]); 1619 1620 /* Where is our port in the trunk list? */ 1621 tports = hwft->num_ports; 1622 for (tix = 0; tix < tports; tix++) { 1623 if (fail_modport == hwft->modport[tix]) { 1624 break; 1625 } 1626 } 1627 1628 if (tix == tports) { 1629 /* Port not in trunk! */ 1630 return BCM_E_NOT_FOUND; 1631 } 1632 1633 *psc = hwft->psc[tix]; 1634 1635 if (hwft->flags[tix]) { 1636 /* Just return the flags value */ 1637 *flags = hwft->flags[tix]; 1638 *array_count = 0; 1639 } else { 1640 /* Access the HW to get the list */ 1641 *flags = 0; 1642 if (hg_trunk) { 1643 BCM_IF_ERROR_RETURN 1644 (_bcm_xgs3_trunk_hwfailover_hg_read(unit, local_port, 1645 array_size, NULL, ftp, ftm, array_count)); 1646 } else { 1647 BCM_IF_ERROR_RETURN 1648 (_bcm_xgs3_trunk_hwfailover_read(unit, local_port, 1649 array_size, NULL, ftp, ftm, array_count)); 1650 } 1651 } 1652 1653 return BCM_E_NONE; 1654 } 1655 1656 /* 1657 *Trunk group set/destroy Trunk Failover config 1658 */ 1659 STATIC int 1660 _bcm_xgs3_trunk_failover_set(int unit, bcm_trunk_t tid, int hg_trunk, 1661 _esw_trunk_add_info_t *add_info) 1662 { 1663 int tix, mod_is_local, tid_ix; 1664 bcm_port_t tp_port; 1665 bcm_module_t tp_mod = -1; 1666 _xgs3_hw_tinfo_t *hwft; 1667 int num_hwft_ports; 1668 bcm_port_t port_array[BCM_XGS3_TRUNK_MAX_PORTCNT]; 1669 bcm_module_t mod_array[BCM_XGS3_TRUNK_MAX_PORTCNT]; 1670 int failover_flags; 1671 1672 failover_flags = 0; 1673 if (add_info != NULL) { 1674 if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_NEXT) { 1675 failover_flags = BCM_TRUNK_FLAG_FAILOVER_NEXT; 1676 } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL) { 1677 failover_flags = BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL; 1678 } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_ALL) { 1679 failover_flags = BCM_TRUNK_FLAG_FAILOVER_ALL; 1680 } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL) { 1681 failover_flags = BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL; 1682 } 1683 } 1684 1685 tid_ix = tid + (hg_trunk ? _BCM_FP_TRUNK_NUM_MAX : 0); 1686 hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix]); 1687 1688 if ((NULL == add_info) || (0 != failover_flags)) { 1689 for (tix = 0; tix < hwft->num_ports; tix++) { 1690 if (!hg_trunk) { 1691 tp_mod = hwft->modport[tix] >> 8; 1692 BCM_IF_ERROR_RETURN 1693 (_bcm_esw_modid_is_local(unit, tp_mod, &mod_is_local)); 1694 if (!mod_is_local) { 1695 continue; 1696 } 1697 } 1698 tp_port = hwft->modport[tix] & 0xff; 1699 BCM_IF_ERROR_RETURN 1700 (_bcm_xgs3_trunk_hwfailover_set(unit, tid, hg_trunk, 1701 tp_port, tp_mod, 1702 hwft->psc[tix], 1703 0, 0, NULL, NULL)); 1704 } 1705 } 1706 /* Else, updating trunk with add_info->flags == 0, 1707 * do not change failover configuration */ 1708 1709 if (NULL == add_info) { 1710 /* We're deleting the trunk, flush the info structure */ 1711 hwft->num_ports = 0; 1712 return BCM_E_NONE; 1713 } 1714 1715 /* Record trunk data */ 1716 num_hwft_ports = 0; 1717 for (tix = 0; tix < add_info->num_ports; tix++) { 1718 if (add_info->member_flags[tix] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) { 1719 continue; 1720 } 1721 hwft->flags[num_hwft_ports] = failover_flags; 1722 hwft->psc[num_hwft_ports] = add_info->psc; 1723 hwft->modport[num_hwft_ports] = add_info->tp[tix]; 1724 port_array[num_hwft_ports] = add_info->tp[tix]; 1725 if (!hg_trunk) { 1726 hwft->modport[num_hwft_ports] |= (add_info->tm[tix] << 8); 1727 mod_array[num_hwft_ports] = add_info->tm[tix]; 1728 } 1729 num_hwft_ports++; 1730 } 1731 hwft->num_ports = num_hwft_ports; 1732 1733 /* No flags in trunk_set means no failover changes */ 1734 if (0 != failover_flags) { 1735 /* Configure new trunk failover info */ 1736 for (tix = 0; tix < hwft->num_ports; tix++) { 1737 if (!hg_trunk) { 1738 BCM_IF_ERROR_RETURN 1739 (_bcm_esw_modid_is_local(unit, hwft->modport[tix] >> 8, 1740 &mod_is_local)); 1741 if (!mod_is_local) { 1742 continue; 1743 } 1744 } 1745 BCM_IF_ERROR_RETURN 1746 (_bcm_xgs3_trunk_hwfailover_set(unit, tid, hg_trunk, 1747 hwft->modport[tix] & 0xff, 1748 hwft->modport[tix] >> 8, 1749 hwft->psc[tix], hwft->flags[tix], hwft->num_ports, 1750 port_array, mod_array)); 1751 } 1752 } 1753 return BCM_E_NONE; 1754 } 1755 1756 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRX_SUPPORT */ 1757 1758 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 1759 /* 1760 * Update port table for fabric trunks. 1761 * SOC_IS_HBX only. 1762 */ 1763 STATIC int 1764 _bcm_xgs3_trunk_fabric_port_set(int unit, 1765 bcm_trunk_t hgtid, 1766 pbmp_t old_ports, 1767 pbmp_t new_ports) 1768 { 1769 bcm_port_t port; 1770 int ctid; 1771 1772 PBMP_PORT_ITER(unit, port) { 1773 if (!(IS_HG_PORT(unit, port) || IS_HL_PORT(unit, port))) { 1774 continue; 1775 } 1776 if (BCM_PBMP_MEMBER(new_ports, port)) { 1777 ctid = hgtid; 1778 } else if (BCM_PBMP_MEMBER(old_ports, port)) { 1779 ctid = -1; 1780 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 1781 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 1782 /* Clear HW failover info for deleted port */ 1783 BCM_IF_ERROR_RETURN 1784 (_bcm_xgs3_trunk_hwfailover_set(unit, hgtid, TRUE, 1785 port, -1, 1786 BCM_TRUNK_PSC_DEFAULT, 1787 0, 0, NULL, NULL)); 1788 } 1789 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 1790 } else { 1791 continue; 1792 } 1793 BCM_IF_ERROR_RETURN 1794 (_bcm_esw_port_config_set(unit, port, 1795 _bcmPortHigigTrunkId, ctid)); 1796 } 1797 return BCM_E_NONE; 1798 } 1799 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_BRADLEY_SUPPORT */ 1800 1801 STATIC int 1802 _bcm_xgs3_trunk_fabric_set(int unit, 1803 bcm_trunk_t hgtid, 1804 _esw_trunk_add_info_t *add_info, 1805 trunk_private_t *t_info) 1806 { 1807 int i, local_id; 1808 int port[BCM_XGS3_TRUNK_MAX_PORTCNT]; 1809 pbmp_t old_trunk_pbmp, new_trunk_pbmp, hg_pbm, pbm; 1810 bcm_gport_t gport; 1811 bcm_module_t mod_id; 1812 bcm_trunk_t trunk, tid; 1813 1814 SOC_PBMP_CLEAR(new_trunk_pbmp); 1815 tid = hgtid + _BCM_FP_TRUNK_NUM_MAX; 1816 for (i = 0; i < add_info->num_ports; i++) { 1817 /* if given modid is -1 devport was used */ 1818 if (BCM_MODID_INVALID != add_info->tm[i]) { 1819 BCM_GPORT_MODPORT_SET(gport, add_info->tm[i], add_info->tp[i]); 1820 1821 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport, &mod_id, 1822 &port[i], &trunk, &local_id)); 1823 } else { 1824 port[i] = add_info->tp[i]; 1825 } 1826 1827 if (!SOC_PORT_VALID(unit, port[i])) { 1828 return BCM_E_PORT; 1829 } 1830 if (!IS_ST_PORT(unit, port[i])) { 1831 return BCM_E_PARAM; 1832 } 1833 SOC_PBMP_PORT_ADD(new_trunk_pbmp, port[i]); 1834 1835 /* Save new trunk member info */ 1836 MEMBER_INFO(unit, tid).modport[i] = port[i]; 1837 MEMBER_INFO(unit, tid).member_flags[i] = add_info->member_flags[i]; 1838 } 1839 MEMBER_INFO(unit, tid).num_ports = add_info->num_ports; 1840 1841 if ((SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) && 1842 soc_feature(unit, soc_feature_hg_trunking)) { 1843 uint32 hg_group_entry, hg_cntl_entry; 1844 uint32 hgp, pword; 1845 soc_field_t *trunkf, rtagf, bmapf; 1846 bcm_port_t port; 1847 int cena, ctid; 1848 #if defined(BCM_FIREBOLT2_SUPPORT) 1849 soc_field_t sizef; 1850 #endif /* BCM_FIREBOLT2_SUPPORT */ 1851 1852 switch (hgtid) { 1853 case 0: 1854 trunkf = _hg_trunk0f; 1855 rtagf = HIGIG_TRUNK_RTAG0f; 1856 bmapf = HIGIG_TRUNK_BITMAP0f; 1857 #if defined(BCM_FIREBOLT2_SUPPORT) 1858 sizef = HIGIG_TRUNK_SIZE0f; 1859 #endif /* BCM_FIREBOLT2_SUPPORT */ 1860 break; 1861 case 1: 1862 trunkf = _hg_trunk1f; 1863 rtagf = HIGIG_TRUNK_RTAG1f; 1864 bmapf = HIGIG_TRUNK_BITMAP1f; 1865 #if defined(BCM_FIREBOLT2_SUPPORT) 1866 sizef = HIGIG_TRUNK_SIZE1f; 1867 #endif /* BCM_FIREBOLT2_SUPPORT */ 1868 break; 1869 default: 1870 return BCM_E_PARAM; 1871 } 1872 1873 SOC_IF_ERROR_RETURN(READ_HIGIG_TRUNK_GROUPr(unit, &hg_group_entry)); 1874 1875 for (i = 0; i < 4; i++) { 1876 if (SOC_IS_RAVEN(unit)) { 1877 /* For Raven, write port number directly */ 1878 hgp = add_info->tp[i%add_info->num_ports]; 1879 } else { 1880 /* For other FBX, write higig port number */ 1881 BCM_IF_ERROR_RETURN( 1882 soc_xgs3_port_to_higig_bitmap(unit, 1883 add_info->tp[i%add_info->num_ports], &hgp)); 1884 BCM_IF_ERROR_RETURN( 1885 soc_xgs3_higig_bitmap_to_higig_port_num(hgp, &hgp)); 1886 } 1887 soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry, 1888 trunkf[i], hgp); 1889 } 1890 1891 #if defined(BCM_FIREBOLT2_SUPPORT) 1892 if (soc_feature(unit, soc_feature_trunk_group_size)) { 1893 soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry, 1894 sizef, add_info->num_ports-1); 1895 } 1896 #endif /* BCM_FIREBOLT2_SUPPORT */ 1897 soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry, 1898 rtagf, t_info->rtag); 1899 SOC_IF_ERROR_RETURN(WRITE_HIGIG_TRUNK_GROUPr(unit, hg_group_entry)); 1900 1901 SOC_IF_ERROR_RETURN(READ_HIGIG_TRUNK_CONTROLr(unit, &hg_cntl_entry)); 1902 SOC_PBMP_CLEAR(old_trunk_pbmp); 1903 pword = soc_reg_field_get(unit, HIGIG_TRUNK_CONTROLr, 1904 hg_cntl_entry, bmapf); 1905 1906 if (SOC_IS_RAVEN(unit)) { 1907 /* Use the bitmap directly */ 1908 SOC_PBMP_WORD_SET(old_trunk_pbmp, 0, pword); 1909 } else { 1910 /* For other FBX, map the higig bitmap to the physical bitmap */ 1911 SOC_PBMP_WORD_SET(hg_pbm, 0, pword); 1912 SOC_PBMP_CLEAR(pbm); 1913 soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbm, &pbm); 1914 SOC_PBMP_ASSIGN(old_trunk_pbmp, pbm); 1915 } 1916 PBMP_ST_ITER(unit, port) { 1917 if (BCM_PBMP_MEMBER(new_trunk_pbmp, port)) { 1918 cena = 1; 1919 ctid = hgtid; 1920 } else if (BCM_PBMP_MEMBER(old_trunk_pbmp, port)) { 1921 cena = 0; 1922 ctid = 0; 1923 } else { 1924 continue; 1925 } 1926 BCM_IF_ERROR_RETURN( 1927 soc_xgs3_port_to_higig_bitmap(unit, port, &hgp)); 1928 BCM_IF_ERROR_RETURN( 1929 soc_xgs3_higig_bitmap_to_higig_port_num(hgp, &hgp)); 1930 soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry, 1931 _hg_cntl1f[hgp], cena); 1932 soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry, 1933 _hg_cntl0f[hgp], ctid); 1934 } 1935 if (SOC_IS_RAVEN(unit)) { 1936 soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry, 1937 bmapf, SOC_PBMP_WORD_GET(new_trunk_pbmp, 0)); 1938 } else { 1939 SOC_PBMP_CLEAR(hg_pbm); 1940 soc_xgs3_bitmap_to_higig_bitmap(unit, new_trunk_pbmp, &hg_pbm); 1941 soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry, 1942 bmapf, SOC_PBMP_WORD_GET(hg_pbm, 0)); 1943 } 1944 SOC_IF_ERROR_RETURN(WRITE_HIGIG_TRUNK_CONTROLr(unit, hg_cntl_entry)); 1945 1946 BCM_IF_ERROR_RETURN 1947 (_bcm_xgs3_trunk_swfailover_fabric_set(unit, 1948 hgtid, 1949 t_info->rtag, 1950 new_trunk_pbmp)); 1951 return BCM_E_NONE; 1952 } 1953 #if defined(BCM_TRIUMPH2_SUPPORT) 1954 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1955 SOC_IS_VALKYRIE2(unit)) { 1956 uint64 val64; 1957 1958 SOC_IF_ERROR_RETURN 1959 (READ_HG_TRUNK_BITMAP_64r(unit, hgtid, &val64)); 1960 SOC_PBMP_CLEAR(hg_pbm); 1961 SOC_PBMP_WORD_SET(hg_pbm, 0, 1962 soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r, 1963 val64, HIGIG_TRUNK_BITMAP_LOf)); 1964 SOC_PBMP_WORD_SET(hg_pbm, 1, 1965 soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r, 1966 val64, HIGIG_TRUNK_BITMAP_HIf)); 1967 SOC_PBMP_CLEAR(old_trunk_pbmp); 1968 SOC_PBMP_ASSIGN(old_trunk_pbmp, hg_pbm); 1969 1970 COMPILER_64_ZERO(val64); 1971 SOC_PBMP_CLEAR(hg_pbm); 1972 SOC_PBMP_ASSIGN(hg_pbm, new_trunk_pbmp); 1973 soc_reg64_field32_set(unit, HG_TRUNK_BITMAP_64r, &val64, 1974 HIGIG_TRUNK_BITMAP_LOf, 1975 SOC_PBMP_WORD_GET(hg_pbm, 0)); 1976 soc_reg64_field32_set(unit, HG_TRUNK_BITMAP_64r, &val64, 1977 HIGIG_TRUNK_BITMAP_HIf, 1978 SOC_PBMP_WORD_GET(hg_pbm, 1)); 1979 SOC_IF_ERROR_RETURN 1980 (WRITE_HG_TRUNK_BITMAP_64r(unit, hgtid, val64)); 1981 1982 COMPILER_64_ZERO(val64); 1983 for (i = 0; i < 8; i++) { 1984 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64, 1985 _hg_trunk[i], port[i%add_info->num_ports]); 1986 } 1987 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64, 1988 HIGIG_TRUNK_SIZEf, add_info->num_ports-1); 1989 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64, 1990 HIGIG_TRUNK_RTAGf, t_info->rtag); 1991 SOC_IF_ERROR_RETURN 1992 (WRITE_HG_TRUNK_GROUPr(unit, hgtid, val64)); 1993 COMPILER_64_ZERO(val64); 1994 1995 BCM_IF_ERROR_RETURN 1996 (_bcm_xgs3_trunk_fabric_port_set(unit, 1997 hgtid, 1998 old_trunk_pbmp, 1999 new_trunk_pbmp)); 2000 2001 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 2002 BCM_IF_ERROR_RETURN 2003 (_bcm_xgs3_trunk_failover_set(unit, hgtid, TRUE, add_info)); 2004 } 2005 2006 BCM_IF_ERROR_RETURN 2007 (_bcm_xgs3_trunk_swfailover_fabric_set(unit, 2008 hgtid, 2009 t_info->rtag, 2010 new_trunk_pbmp)); 2011 2012 return BCM_E_NONE; 2013 } 2014 #endif /* BCM_TRIUMPH2_SUPPORT */ 2015 #if defined(BCM_BRADLEY_SUPPORT) 2016 if (SOC_IS_HBX(unit) || SOC_IS_TRX(unit)) { 2017 uint32 val; 2018 uint64 val64; 2019 #if defined(BCM_GREYHOUND2_SUPPORT) 2020 uint64 hg_trunk_bmap_f; 2021 if (soc_feature(unit, soc_feature_high_portcount_register)) { 2022 SOC_IF_ERROR_RETURN 2023 (READ_HG_TRUNK_BITMAP_LOr(unit, hgtid, &val64)); 2024 hg_trunk_bmap_f = 2025 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_LOr, 2026 val64, HIGIG_TRUNK_BITMAPf); 2027 SOC_PBMP_CLEAR(hg_pbm); 2028 SOC_PBMP_WORD_SET(hg_pbm, 0, COMPILER_64_LO(hg_trunk_bmap_f)); 2029 SOC_PBMP_WORD_SET(hg_pbm, 1, COMPILER_64_HI(hg_trunk_bmap_f)); 2030 SOC_IF_ERROR_RETURN 2031 (READ_HG_TRUNK_BITMAP_HIr(unit, hgtid, &val64)); 2032 hg_trunk_bmap_f = 2033 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_HIr, 2034 val64, HIGIG_TRUNK_BITMAPf); 2035 SOC_PBMP_WORD_SET(hg_pbm, 2, COMPILER_64_LO(hg_trunk_bmap_f)); 2036 2037 SOC_PBMP_CLEAR(old_trunk_pbmp); 2038 SOC_PBMP_ASSIGN(old_trunk_pbmp, hg_pbm); 2039 2040 SOC_PBMP_CLEAR(hg_pbm); 2041 SOC_PBMP_ASSIGN(hg_pbm, new_trunk_pbmp); 2042 2043 COMPILER_64_ZERO(val64); 2044 COMPILER_64_SET(hg_trunk_bmap_f, SOC_PBMP_WORD_GET(hg_pbm, 1), 2045 SOC_PBMP_WORD_GET(hg_pbm, 0)); 2046 soc_reg64_field_set(unit, HG_TRUNK_BITMAP_LOr, &val64, 2047 HIGIG_TRUNK_BITMAPf, hg_trunk_bmap_f); 2048 SOC_IF_ERROR_RETURN 2049 (WRITE_HG_TRUNK_BITMAP_LOr(unit, hgtid, val64)); 2050 2051 COMPILER_64_ZERO(val64); 2052 COMPILER_64_SET(hg_trunk_bmap_f, 0, 2053 SOC_PBMP_WORD_GET(hg_pbm, 2)); 2054 soc_reg64_field_set(unit, HG_TRUNK_BITMAP_HIr, &val64, 2055 HIGIG_TRUNK_BITMAPf, hg_trunk_bmap_f); 2056 SOC_IF_ERROR_RETURN 2057 (WRITE_HG_TRUNK_BITMAP_HIr(unit, hgtid, val64)); 2058 2059 } else 2060 #endif /* BCM_GREYHOUND2_SUPPORT */ 2061 { 2062 SOC_IF_ERROR_RETURN 2063 (READ_HG_TRUNK_BITMAPr(unit, hgtid, &val)); 2064 SOC_PBMP_CLEAR(hg_pbm); 2065 SOC_PBMP_WORD_SET(hg_pbm, 0, 2066 soc_reg_field_get(unit, HG_TRUNK_BITMAPr, 2067 val, HIGIG_TRUNK_BITMAPf)); 2068 SOC_PBMP_CLEAR(old_trunk_pbmp); 2069 soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbm, &old_trunk_pbmp); 2070 2071 val = 0; 2072 SOC_PBMP_CLEAR(hg_pbm); 2073 soc_xgs3_bitmap_to_higig_bitmap(unit, new_trunk_pbmp, &hg_pbm); 2074 soc_reg_field_set(unit, HG_TRUNK_BITMAPr, &val, HIGIG_TRUNK_BITMAPf, 2075 SOC_PBMP_WORD_GET(hg_pbm, 0)); 2076 SOC_IF_ERROR_RETURN 2077 (WRITE_HG_TRUNK_BITMAPr(unit, hgtid, val)); 2078 } 2079 2080 COMPILER_64_ZERO(val64); 2081 if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit) || 2082 SOC_IS_HURRICANE2(unit) || 2083 soc_feature(unit, soc_feature_hg_trunk_group_members_max_4)) { 2084 for (i = 0; i < 4; i++) { 2085 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64, 2086 _hg_trunk[i], 2087 add_info->tp[i%add_info->num_ports]); 2088 } 2089 } else { 2090 for (i = 0; i < 8; i++) { 2091 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64, 2092 _hg_trunk[i], 2093 add_info->tp[i%add_info->num_ports]); 2094 } 2095 } 2096 if (SOC_REG_FIELD_VALID(unit, HG_TRUNK_GROUPr, HIGIG_TRUNK_SIZEf)) { /* PR 34459 */ 2097 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64, 2098 HIGIG_TRUNK_SIZEf, add_info->num_ports-1); 2099 } 2100 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &val64, 2101 HIGIG_TRUNK_RTAGf, t_info->rtag); 2102 SOC_IF_ERROR_RETURN 2103 (WRITE_HG_TRUNK_GROUPr(unit, hgtid, val64)); 2104 COMPILER_64_ZERO(val64); 2105 2106 #if defined(BCM_SCORPION_SUPPORT) 2107 if (SOC_IS_SC_CQ(unit)) { 2108 for (i = 8; i < 16; i++) { 2109 soc_reg64_field32_set(unit, HG_TRUNK_GROUP_HIr, &val64, 2110 _hg_trunk_hi[i - BCM_SWITCH_TRUNK_MAX_PORTCNT], 2111 add_info->tp[i%add_info->num_ports]); 2112 } 2113 SOC_IF_ERROR_RETURN 2114 (WRITE_HG_TRUNK_GROUP_HIr(unit, hgtid, val64)); 2115 } 2116 #endif 2117 2118 BCM_IF_ERROR_RETURN 2119 (_bcm_xgs3_trunk_fabric_port_set(unit, 2120 hgtid, 2121 old_trunk_pbmp, 2122 new_trunk_pbmp)); 2123 2124 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 2125 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 2126 BCM_IF_ERROR_RETURN 2127 (_bcm_xgs3_trunk_failover_set(unit, hgtid, TRUE, add_info)); 2128 } 2129 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 2130 2131 BCM_IF_ERROR_RETURN 2132 (_bcm_xgs3_trunk_swfailover_fabric_set(unit, 2133 hgtid, 2134 t_info->rtag, 2135 new_trunk_pbmp)); 2136 2137 return BCM_E_NONE; 2138 } 2139 #endif /* BCM_BRADLEY_SUPPORT */ 2140 return BCM_E_UNAVAIL; 2141 } 2142 2143 /* 2144 * Function: 2145 * _bcm_xgs3_trunk_property_migrate 2146 * Purpose: 2147 * Migrate trunk properties from old members to new members of the trunk 2148 * group 2149 * Parameters: 2150 * unit - (IN) SOC unit number. 2151 * num_leaving - (IN) Number of old members leaving the trunk group 2152 * leaving_arr - (IN) Array containing leaving members 2153 * num_staying - (IN) Number of old members staying in the trunk group 2154 * staying_arr - (IN) Array containing staying members 2155 * num_joining - (IN) Number of new members joining the trunk group 2156 * joining_arr - (IN) Array containing joining members 2157 * Returns: 2158 * BCM_X_XXX 2159 */ 2160 int 2161 _bcm_xgs3_trunk_property_migrate(int unit, 2162 int num_leaving, bcm_gport_t *leaving_arr, 2163 int num_staying, bcm_gport_t *staying_arr, 2164 int num_joining, bcm_gport_t *joining_arr) 2165 { 2166 bcm_module_t mod; 2167 bcm_port_t port; 2168 int stm_idx; 2169 source_trunk_map_table_entry_t stm_entry; 2170 int rv; 2171 2172 if ((num_leaving > 0) && (NULL == leaving_arr)) { 2173 return BCM_E_PARAM; 2174 } 2175 if ((num_staying > 0) && (NULL == staying_arr)) { 2176 return BCM_E_PARAM; 2177 } 2178 if ((num_joining > 0) && (NULL == joining_arr)) { 2179 return BCM_E_PARAM; 2180 } 2181 2182 if (num_leaving > 0) { 2183 if (!BCM_GPORT_IS_MODPORT(leaving_arr[0])) { 2184 return BCM_E_PARAM; 2185 } 2186 mod = BCM_GPORT_MODPORT_MODID_GET(leaving_arr[0]); 2187 port = BCM_GPORT_MODPORT_PORT_GET(leaving_arr[0]); 2188 2189 } else if (num_staying > 0) { 2190 if (!BCM_GPORT_IS_MODPORT(staying_arr[0])) { 2191 return BCM_E_PARAM; 2192 } 2193 mod = BCM_GPORT_MODPORT_MODID_GET(staying_arr[0]); 2194 port = BCM_GPORT_MODPORT_PORT_GET(staying_arr[0]); 2195 2196 } else { 2197 /* Both num_leaving and num_staying are zeroes. This is a newly 2198 * created trunk group. There is no trunk properties to migrate. 2199 */ 2200 return BCM_E_NONE; 2201 } 2202 2203 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 2204 rv = _bcm_esw_src_mod_port_table_index_get(unit, mod, 2205 port, &stm_idx); 2206 2207 if (SOC_FAILURE(rv)) { 2208 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2209 return rv; 2210 } 2211 2212 rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, stm_idx, 2213 &stm_entry); 2214 if (SOC_FAILURE(rv)) { 2215 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2216 return rv; 2217 } 2218 2219 if (soc_feature(unit, soc_feature_vlan_translation_range)) { 2220 #ifdef BCM_TRX_SUPPORT 2221 if (SOC_IS_TRX(unit)) { 2222 soc_field_t vlan_range_field; 2223 soc_field_t inner_vlan_range_field; 2224 int32 old_inner_vlan_range_idx, old_vlan_range_idx; 2225 int32 inner_vlan_range_idx, vlan_range_idx; 2226 int32 i; 2227 2228 if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, 2229 OUTER_VLAN_RANGE_IDXf)) { 2230 vlan_range_field = OUTER_VLAN_RANGE_IDXf; 2231 } else if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, 2232 VLAN_RANGE_IDXf)) { 2233 vlan_range_field = VLAN_RANGE_IDXf; 2234 } else { 2235 vlan_range_field = INVALIDf; 2236 } 2237 2238 if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, 2239 INNER_VLAN_RANGE_IDXf)) { 2240 inner_vlan_range_field = INNER_VLAN_RANGE_IDXf; 2241 } else { 2242 inner_vlan_range_field = INVALIDf; 2243 } 2244 2245 /* If VLAN RANGE fields are not valid to the device, return */ 2246 if ((vlan_range_field == INVALIDf) && 2247 (inner_vlan_range_field == INVALIDf)) { 2248 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2249 return BCM_E_NONE; 2250 } 2251 2252 /* Get trunk group's VLAN_RANGE_IDX */ 2253 vlan_range_idx = (vlan_range_field != INVALIDf) ? 2254 soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm, 2255 &stm_entry, vlan_range_field): -1; 2256 2257 /* Get trunk group's INNER_VLAN_RANGE_IDX */ 2258 inner_vlan_range_idx = (inner_vlan_range_field != INVALIDf) ? 2259 soc_mem_field32_get(unit, 2260 SOURCE_TRUNK_MAP_TABLEm, 2261 &stm_entry, inner_vlan_range_field): -1; 2262 2263 /* Update VLAN_RANGE_IDX for members joining the trunk group */ 2264 for (i = 0; i < num_joining; i++) { 2265 if (!BCM_GPORT_IS_MODPORT(joining_arr[i])) { 2266 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2267 return BCM_E_PARAM; 2268 } 2269 mod = BCM_GPORT_MODPORT_MODID_GET(joining_arr[i]); 2270 port = BCM_GPORT_MODPORT_PORT_GET(joining_arr[i]); 2271 2272 rv = _bcm_esw_src_mod_port_table_index_get(unit, 2273 mod, port, &stm_idx); 2274 if(BCM_FAILURE(rv)) { 2275 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2276 return rv; 2277 } 2278 2279 rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, 2280 MEM_BLOCK_ANY, stm_idx, &stm_entry); 2281 if(BCM_FAILURE(rv)) { 2282 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2283 return rv; 2284 } 2285 2286 if (vlan_range_field != INVALIDf) { 2287 /* Delete port's old VLAN range profile */ 2288 old_vlan_range_idx = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get( 2289 unit, &stm_entry, vlan_range_field); 2290 2291 rv = _bcm_trx_vlan_range_profile_entry_delete( 2292 unit, old_vlan_range_idx); 2293 2294 if(BCM_FAILURE(rv)) { 2295 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2296 return rv; 2297 } 2298 2299 /* Set port to use trunk group's VLAN range profile */ 2300 _bcm_trx_vlan_range_profile_entry_increment(unit, 2301 vlan_range_idx); 2302 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, 2303 vlan_range_field, vlan_range_idx); 2304 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, 2305 MEM_BLOCK_ALL, stm_idx, &stm_entry); 2306 if(BCM_FAILURE(rv)) { 2307 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2308 return rv; 2309 } 2310 } 2311 2312 if (inner_vlan_range_field != INVALIDf) { 2313 /* Delete port's old INNER VLAN range profile */ 2314 old_inner_vlan_range_idx = 2315 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry, 2316 inner_vlan_range_field); 2317 rv = _bcm_trx_vlan_range_profile_entry_delete( 2318 unit, 2319 old_inner_vlan_range_idx); 2320 2321 if(BCM_FAILURE(rv)) { 2322 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2323 return rv; 2324 } 2325 2326 /* Set port to use trunk group's INNER VLAN range profile */ 2327 _bcm_trx_vlan_range_profile_entry_increment(unit, 2328 inner_vlan_range_idx); 2329 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, 2330 inner_vlan_range_field, inner_vlan_range_idx); 2331 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, 2332 MEM_BLOCK_ALL, stm_idx, &stm_entry); 2333 if(BCM_FAILURE(rv)) { 2334 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2335 return rv; 2336 } 2337 } 2338 } 2339 2340 /* Update VLAN_RANGE_IDX for members leaving the trunk group */ 2341 for (i = 0; i < num_leaving; i++) { 2342 if (!BCM_GPORT_IS_MODPORT(leaving_arr[i])) { 2343 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2344 return BCM_E_PARAM; 2345 } 2346 mod = BCM_GPORT_MODPORT_MODID_GET(leaving_arr[i]); 2347 port = BCM_GPORT_MODPORT_PORT_GET(leaving_arr[i]); 2348 rv = _bcm_esw_src_mod_port_table_index_get(unit, 2349 mod, port, &stm_idx); 2350 if(BCM_FAILURE(rv)) { 2351 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2352 return rv; 2353 } 2354 2355 rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, 2356 MEM_BLOCK_ANY, stm_idx, &stm_entry); 2357 2358 if(BCM_FAILURE(rv)) { 2359 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2360 return rv; 2361 } 2362 2363 if (vlan_range_field != INVALIDf) { 2364 /* Delete port's old VLAN range profile */ 2365 old_vlan_range_idx = 2366 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 2367 &stm_entry, 2368 vlan_range_field); 2369 rv = _bcm_trx_vlan_range_profile_entry_delete(unit, 2370 old_vlan_range_idx); 2371 if(BCM_FAILURE(rv)) { 2372 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2373 return rv; 2374 } 2375 2376 /* Set port to use the default VLAN range profile 0 */ 2377 _bcm_trx_vlan_range_profile_entry_increment(unit, 0); 2378 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, 2379 &stm_entry, 2380 vlan_range_field, 0); 2381 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, 2382 MEM_BLOCK_ALL, stm_idx, &stm_entry); 2383 if(BCM_FAILURE(rv)) { 2384 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2385 return rv; 2386 } 2387 } 2388 2389 if (inner_vlan_range_field != INVALIDf) { 2390 /* Delete port's old INNER VLAN range profile */ 2391 old_inner_vlan_range_idx = 2392 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry, 2393 inner_vlan_range_field); 2394 rv = _bcm_trx_vlan_range_profile_entry_delete(unit, 2395 old_inner_vlan_range_idx); 2396 if(BCM_FAILURE(rv)) { 2397 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2398 return rv; 2399 } 2400 2401 /* Set port to use trunk group's INNER VLAN range profile */ 2402 _bcm_trx_vlan_range_profile_entry_increment(unit, 0); 2403 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, 2404 inner_vlan_range_field, 2405 0); 2406 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, 2407 MEM_BLOCK_ALL, stm_idx, &stm_entry); 2408 2409 if(BCM_FAILURE(rv)) { 2410 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2411 return rv; 2412 } 2413 } 2414 } 2415 2416 } 2417 #endif /* BCM_TRX_SUPPORT */ 2418 } 2419 2420 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 2421 return BCM_E_NONE; 2422 } 2423 2424 /* 2425 * Function: 2426 * _bcm_xgs3_trunk_set 2427 * Purpose: 2428 * Set trunk members. 2429 * Parameters: 2430 * unit - (IN) SOC unit number. 2431 * tid - (IN) Trunk group ID. 2432 * add_info - (IN) Pointer to trunk add info structure. 2433 * t_info - (IN) Pointer to trunk info. 2434 * Returns: 2435 * BCM_E_xxx 2436 */ 2437 STATIC int 2438 _bcm_xgs3_trunk_set(int unit, 2439 bcm_trunk_t tid, 2440 _esw_trunk_add_info_t *add_info, 2441 trunk_private_t *t_info) 2442 { 2443 int rv = BCM_E_NONE; 2444 trunk_bitmap_entry_t trunk_bitmap_entry; 2445 uint32 tg_entry[SOC_MAX_MEM_WORDS]; 2446 pbmp_t old_trunk_pbmp; 2447 pbmp_t new_trunk_pbmp; 2448 pbmp_t nuc_trunk_pbmp; 2449 bcm_gport_t gport; 2450 bcm_port_t loc_port; 2451 int port, mod, mod_out, port_out; 2452 int i, j, k, remove_trunk_port; 2453 int hwmod[BCM_XGS3_TRUNK_MAX_PORTCNT]; 2454 int egr_hwmod[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 }; 2455 int uc_egr_hwmod[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 }; 2456 int hwport[BCM_XGS3_TRUNK_MAX_PORTCNT]; 2457 int egr_hwport[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 }; 2458 int uc_egr_hwport[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 }; 2459 uint32 egr_member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 }; 2460 int max_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 2461 bcm_trunk_chip_info_t chip_info; 2462 uint32 my_modid_bmap = 0; 2463 uint32 nuc_member_count = 0; 2464 uint32 nuc_tpbm = 0; 2465 uint32 negr_disable_port = 0; 2466 uint32 num_uc_egr_disable_port = 0; 2467 int num_leaving_members = 0; 2468 bcm_gport_t leaving_members[BCM_SWITCH_TRUNK_MAX_PORTCNT]; 2469 int match_leaving_members; 2470 int num_staying_members = 0; 2471 bcm_gport_t staying_members[BCM_SWITCH_TRUNK_MAX_PORTCNT]; 2472 int match_staying_members; 2473 int num_joining_members = 0; 2474 bcm_gport_t joining_members[BCM_SWITCH_TRUNK_MAX_PORTCNT]; 2475 int match_joining_members; 2476 soc_mem_t trunk_mem = TRUNK_GROUPm; 2477 2478 if (soc_feature(unit, soc_feature_fastlag)) { 2479 trunk_mem = FAST_TRUNK_GROUPm; 2480 } 2481 2482 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 2483 if (chip_info.trunk_fabric_id_min >= 0 && 2484 tid >= chip_info.trunk_fabric_id_min) { /* fabric trunk */ 2485 tid -= chip_info.trunk_fabric_id_min; 2486 /* coverity[stack_use_callee] */ 2487 /* coverity[stack_use_overflow] */ 2488 return _bcm_xgs3_trunk_fabric_set(unit, tid, add_info, t_info); 2489 } 2490 2491 if (add_info->flags & BCM_TRUNK_FLAG_IPMC_CLEAVE) { 2492 return BCM_E_UNAVAIL; 2493 } 2494 2495 /* Audit unsupported flag combination */ 2496 for (i = 0; i < add_info->num_ports; i++) { 2497 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_INGRESS_DISABLE && 2498 add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) { 2499 return BCM_E_PARAM; 2500 } 2501 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE && 2502 add_info->member_flags[i] & BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) { 2503 return BCM_E_PARAM; 2504 } 2505 } 2506 2507 if (add_info->dlf_index == -1) { 2508 BCM_IF_ERROR_RETURN(_bcm_nuc_tpbm_get(unit, 2509 add_info->num_ports, 2510 add_info->tm, 2511 &nuc_tpbm)); 2512 } else { 2513 nuc_tpbm = (0x1 << add_info->dlf_index); 2514 } 2515 2516 SOC_PBMP_CLEAR(new_trunk_pbmp); 2517 SOC_PBMP_CLEAR(nuc_trunk_pbmp); 2518 for (i = 0; i < add_info->num_ports; i++) { 2519 mod = add_info->tm[i]; 2520 port = add_info->tp[i]; 2521 BCM_IF_ERROR_RETURN 2522 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 2523 mod, port, 2524 &mod_out, &port_out)); 2525 if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) { 2526 return BCM_E_BADID; 2527 } 2528 if (!SOC_PORT_ADDRESSABLE(unit, port_out)) { 2529 return BCM_E_PORT; 2530 } 2531 2532 /** Don't add the port in trunk group if egress disable is set */ 2533 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) { 2534 nuc_tpbm &= ~(1 << i); 2535 negr_disable_port++; 2536 } else if (add_info->member_flags[i] & 2537 BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) { 2538 num_uc_egr_disable_port++; 2539 } 2540 2541 /* Save mapped version */ 2542 hwmod[i] = mod_out; 2543 hwport[i] = port_out; 2544 2545 BCM_GPORT_MODPORT_SET(gport, mod_out, port_out); 2546 if (BCM_SUCCESS(bcm_esw_port_local_get(unit, gport, &loc_port))) { 2547 if (!IS_E_PORT(unit, loc_port)) { 2548 return BCM_E_PARAM; 2549 } 2550 SOC_PBMP_PORT_ADD(new_trunk_pbmp, loc_port); 2551 if (nuc_tpbm & (1 << i)) { 2552 /* Eligible for NUC forwarding */ 2553 SOC_PBMP_PORT_ADD(nuc_trunk_pbmp, loc_port); 2554 my_modid_bmap |= (1 << nuc_member_count); 2555 } 2556 } 2557 2558 if (nuc_tpbm & (1 << i)) { 2559 /* Eligible for NUC forwarding */ 2560 nuc_member_count++; 2561 } 2562 } 2563 2564 /* 2565 * Clean up old trunk membership 2566 */ 2567 SOC_PBMP_CLEAR(old_trunk_pbmp); 2568 if (t_info->in_use) { 2569 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 2570 mod = MEMBER_INFO(unit, tid).modport[i] >> 8; 2571 port = MEMBER_INFO(unit, tid).modport[i] & 0xff; 2572 BCM_GPORT_MODPORT_SET(gport, mod, port); 2573 if (BCM_SUCCESS(bcm_esw_port_local_get(unit, gport, &loc_port))) { 2574 if (SOC_PORT_VALID(unit, loc_port)) { 2575 SOC_PBMP_PORT_ADD(old_trunk_pbmp, loc_port); 2576 } 2577 } else { 2578 loc_port = BCM_GPORT_INVALID; 2579 } 2580 /* Invalidate port only if it is not a part of the new trunk group */ 2581 remove_trunk_port = TRUE; 2582 for (j = 0; j < add_info->num_ports; j++) { 2583 /* Note: Compare with the mapped version as thats the one set in h/w */ 2584 if (mod == hwmod[j] && port == hwport[j]) { 2585 remove_trunk_port = FALSE; 2586 } 2587 } 2588 if (remove_trunk_port) { 2589 /* Add port to array containing members leaving the trunk 2590 * group if it is different from previous leaving members 2591 */ 2592 match_leaving_members = FALSE; 2593 for (k = 0; k < num_leaving_members; k++) { 2594 if (gport == leaving_members[k]) { 2595 match_leaving_members = TRUE; 2596 break; 2597 } 2598 } 2599 if (!match_leaving_members) { 2600 leaving_members[num_leaving_members++] = gport; 2601 } 2602 2603 BCM_IF_ERROR_RETURN 2604 (_bcm_xgs3_trunk_set_port_property(unit, mod, port, -1)); 2605 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 2606 if (soc_feature(unit, soc_feature_port_lag_failover) && 2607 (BCM_GPORT_INVALID != loc_port) && 2608 IS_E_PORT(unit, loc_port)) 2609 { 2610 /* Clear HW failover info for deleted port */ 2611 BCM_IF_ERROR_RETURN 2612 (_bcm_xgs3_trunk_hwfailover_set(unit, tid, FALSE, 2613 port, mod, 2614 add_info->psc, 2615 0, 0, NULL, NULL)); 2616 } 2617 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 2618 } else { 2619 /* Add port to array containing members staying in the trunk 2620 * group if it is different from previous staying members 2621 */ 2622 match_staying_members = FALSE; 2623 for (k = 0; k < num_staying_members; k++) { 2624 if (gport == staying_members[k]) { 2625 match_staying_members = TRUE; 2626 break; 2627 } 2628 } 2629 if (!match_staying_members) { 2630 staying_members[num_staying_members++] = gport; 2631 } 2632 } 2633 } 2634 } 2635 2636 /* Generate array containing new members joining the trunk group */ 2637 for (i = 0; i < add_info->num_ports; i++) { 2638 BCM_GPORT_MODPORT_SET(gport, hwmod[i], hwport[i]); 2639 match_staying_members = FALSE; 2640 for (j = 0; j < num_staying_members; j++) { 2641 if (gport == staying_members[j]) { 2642 match_staying_members = TRUE; 2643 break; 2644 } 2645 } 2646 if (!match_staying_members) { 2647 match_joining_members = FALSE; 2648 for (j = 0; j < num_joining_members; j++) { 2649 if (gport == joining_members[j]) { 2650 match_joining_members = TRUE; 2651 break; 2652 } 2653 } 2654 if (!match_joining_members) { 2655 joining_members[num_joining_members++] = gport; 2656 } 2657 } 2658 } 2659 2660 sal_memset(&tg_entry, 0, sizeof(tg_entry)); 2661 2662 if (soc_feature(unit, soc_feature_fastlag)) { 2663 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, t_info->rtag); 2664 } else { 2665 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, t_info->rtag); 2666 } 2667 2668 if (soc_feature(unit, soc_feature_trunk_group_size)) { /* TG_SIZE field exists */ 2669 if ( (add_info->num_ports - negr_disable_port - 2670 num_uc_egr_disable_port) == 0 ) { 2671 if (soc_feature(unit, soc_feature_fastlag)) { 2672 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 0); 2673 } else { 2674 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 0); 2675 } 2676 } else { 2677 if (soc_feature(unit, soc_feature_fastlag)) { 2678 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 2679 add_info->num_ports - 1 2680 - negr_disable_port 2681 - num_uc_egr_disable_port); 2682 } else { 2683 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, 2684 TG_SIZEf, add_info->num_ports - 1 2685 - negr_disable_port 2686 - num_uc_egr_disable_port); 2687 } 2688 } 2689 } 2690 2691 if ((add_info->num_ports - negr_disable_port - num_uc_egr_disable_port) > 0 ) { 2692 for (i = 0, j = 0; i < add_info->num_ports; i++) { 2693 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) { 2694 continue; 2695 } 2696 egr_hwmod[j] = hwmod[i]; 2697 egr_hwport[j] = hwport[i]; 2698 egr_member_flags[j] = add_info->member_flags[i]; 2699 j++; 2700 } 2701 for (i = 0, k = 0; i < j; i++) { 2702 if (egr_member_flags[i] & BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) { 2703 continue; 2704 } 2705 uc_egr_hwmod[k] = egr_hwmod[i]; 2706 uc_egr_hwport[k] = egr_hwport[i]; 2707 k++; 2708 } 2709 if (k != 0) { 2710 for (i = 0; i < max_ports; i++) { 2711 mod = uc_egr_hwmod[i%k]; 2712 port = uc_egr_hwport[i%k]; 2713 if (soc_feature(unit, soc_feature_fastlag)) { 2714 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_fast_modulef[i], mod); 2715 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_fast_portf[i], port); 2716 } else { 2717 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_modulef[i], mod); 2718 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_portf[i], port); 2719 } 2720 } 2721 } 2722 } else { 2723 /** no ports are enabled in the trunk */ 2724 for ( i = 0; i < max_ports; i++ ) { 2725 /** drop packets */ 2726 if (soc_feature(unit, soc_feature_fastlag)) { 2727 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_fast_modulef[i], 0); 2728 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_fast_portf[i], 0); 2729 } else { 2730 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_modulef[i], 0); 2731 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, _xgs_portf[i], 0); 2732 } 2733 } 2734 } 2735 2736 /** Don't add the port in the source trunk map if ingress disable is set */ 2737 for (i = 0; i < add_info->num_ports; i++) { 2738 mod = hwmod[i%add_info->num_ports]; 2739 port = hwport[i%add_info->num_ports]; 2740 2741 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_INGRESS_DISABLE) { 2742 BCM_IF_ERROR_RETURN(_bcm_xgs3_trunk_set_port_property(unit, mod, 2743 port, -1)); 2744 } else { 2745 BCM_IF_ERROR_RETURN(_bcm_xgs3_trunk_set_port_property(unit, mod, 2746 port, tid)); 2747 } 2748 } 2749 2750 /* 2751 * Update TRUNK_BITMAP table 2752 */ 2753 BCM_IF_ERROR_RETURN( 2754 soc_mem_read(unit, TRUNK_BITMAPm, MEM_BLOCK_ANY, tid, 2755 &trunk_bitmap_entry)); 2756 soc_mem_pbmp_field_set(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 2757 TRUNK_BITMAPf, &new_trunk_pbmp); 2758 BCM_IF_ERROR_RETURN( 2759 soc_mem_write(unit, TRUNK_BITMAPm, MEM_BLOCK_ALL, tid, 2760 &trunk_bitmap_entry)); 2761 /* 2762 * Update TRUNK_GROUP table 2763 */ 2764 BCM_IF_ERROR_RETURN( 2765 soc_mem_write(unit, trunk_mem, MEM_BLOCK_ALL, tid, &tg_entry)); 2766 2767 /* 2768 * Update the trunk block mask 2769 */ 2770 if (SOC_PBMP_NOT_NULL(new_trunk_pbmp) || 2771 SOC_PBMP_NOT_NULL(old_trunk_pbmp)) { 2772 BCM_IF_ERROR_RETURN( 2773 _bcm_xgs3_trunk_block_mask(unit, 2774 old_trunk_pbmp, 2775 new_trunk_pbmp, 2776 nuc_trunk_pbmp, 2777 my_modid_bmap, 2778 nuc_member_count)); 2779 } 2780 /* 2781 * Trunk Failover 2782 */ 2783 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 2784 if (soc_feature(unit, soc_feature_port_lag_failover)) { 2785 BCM_IF_ERROR_RETURN 2786 (_bcm_xgs3_trunk_failover_set(unit, tid, FALSE, add_info)); 2787 } 2788 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 2789 BCM_IF_ERROR_RETURN 2790 (_bcm_xgs3_trunk_swfailover_set(unit, 2791 tid, 2792 t_info->rtag, 2793 add_info->num_ports - negr_disable_port, 2794 egr_hwmod, 2795 egr_hwport, 2796 egr_member_flags)); 2797 2798 /* Migrate trunk properties from old members to new members */ 2799 BCM_IF_ERROR_RETURN(_bcm_xgs3_trunk_property_migrate(unit, 2800 num_leaving_members, leaving_members, 2801 num_staying_members, staying_members, 2802 num_joining_members, joining_members)); 2803 2804 /* Save new trunk member info */ 2805 for (i = 0; i < add_info->num_ports; i++) { 2806 MEMBER_INFO(unit, tid).modport[i] = ((hwmod[i] & 0xff) << 8) | 2807 (hwport[i] & 0xff); 2808 MEMBER_INFO(unit, tid).member_flags[i] = add_info->member_flags[i]; 2809 } 2810 MEMBER_INFO(unit, tid).num_ports = add_info->num_ports; 2811 2812 #ifdef BCM_GREYHOUND2_SUPPORT 2813 #ifdef INCLUDE_L3 2814 /* Call VXLAN module to clear states for local leaving members */ 2815 if (soc_feature(unit, soc_feature_vxlan_lite)) { 2816 if (num_leaving_members > 0) { 2817 rv = _bcm_esw_vxlan_trunk_member_delete(unit, tid, 2818 num_leaving_members, 2819 leaving_members); 2820 if (BCM_FAILURE(rv)) { 2821 return rv; 2822 } 2823 } 2824 } 2825 #endif /* INCLUDE_L3 */ 2826 #endif /* BCM_GREYHOUND2_SUPPORT */ 2827 2828 return rv; 2829 } 2830 2831 /* 2832 * Function: 2833 * _xgs3_trunk_add_info_member_alloc 2834 * Purpose: 2835 * Allocate member_flags, tp, and tm of _esw_trunk_add_info_t. 2836 * Parameters: 2837 * add_info - (IN) Pointer to trunk add info structure. 2838 * num_ports - (IN) Number of member ports. 2839 * Returns: 2840 * BCM_E_xxx 2841 */ 2842 STATIC int 2843 _xgs3_trunk_add_info_member_alloc(_esw_trunk_add_info_t *add_info, 2844 int num_ports) 2845 { 2846 int rv = BCM_E_NONE; 2847 2848 add_info->member_flags = sal_alloc(sizeof(uint32) * num_ports, 2849 "_xgs3_trunk_add_info_member_flags"); 2850 if (add_info->member_flags == NULL) { 2851 rv = BCM_E_MEMORY; 2852 goto error; 2853 } 2854 sal_memset(add_info->member_flags, 0, sizeof(uint32) * num_ports); 2855 2856 add_info->tp = sal_alloc(sizeof(bcm_port_t) * num_ports, 2857 "_xgs3_trunk_add_info_tp"); 2858 if (add_info->tp == NULL) { 2859 rv = BCM_E_MEMORY; 2860 goto error; 2861 } 2862 sal_memset(add_info->tp, 0, sizeof(bcm_port_t) * num_ports); 2863 2864 add_info->tm = sal_alloc(sizeof(bcm_module_t) * num_ports, 2865 "_xgs3_trunk_add_info_tm"); 2866 if (add_info->tm == NULL) { 2867 rv = BCM_E_MEMORY; 2868 goto error; 2869 } 2870 sal_memset(add_info->tm, 0, sizeof(bcm_module_t) * num_ports); 2871 2872 return rv; 2873 2874 error: 2875 if (NULL != add_info->member_flags) { 2876 sal_free(add_info->member_flags); 2877 } 2878 if (NULL != add_info->tp) { 2879 sal_free(add_info->tp); 2880 } 2881 if (NULL != add_info->tm) { 2882 sal_free(add_info->tm); 2883 } 2884 2885 return rv; 2886 } 2887 2888 /* 2889 * Function: 2890 * _xgs3_trunk_add_info_member_free 2891 * Purpose: 2892 * Free member_flags, tp, and tm of _esw_trunk_add_info_t. 2893 * Parameters: 2894 * add_info - (IN) Pointer to trunk add info structure. 2895 * Returns: 2896 * BCM_E_xxx 2897 */ 2898 STATIC void 2899 _xgs3_trunk_add_info_member_free(_esw_trunk_add_info_t *add_info) 2900 { 2901 if (NULL != add_info->member_flags) { 2902 sal_free(add_info->member_flags); 2903 } 2904 if (NULL != add_info->tp) { 2905 sal_free(add_info->tp); 2906 } 2907 if (NULL != add_info->tm) { 2908 sal_free(add_info->tm); 2909 } 2910 } 2911 2912 /* 2913 * Function: 2914 * bcm_xgs3_trunk_modify 2915 * Purpose: 2916 * Set trunk members. 2917 * Parameters: 2918 * unit - (IN) SOC unit number. 2919 * tid - (IN) Trunk group ID. 2920 * trunk_info - (IN) Pointer to user provided trunk info. 2921 * member_count - (IN) Number of trunk members. 2922 * member_array - (IN) Array of trunk members. 2923 * t_info - (IN) Pointer to internal trunk info. 2924 * op - (IN) Not used by this procedure. 2925 * member - (IN) Not used by this procedure. 2926 * Returns: 2927 * BCM_E_xxx 2928 */ 2929 int 2930 bcm_xgs3_trunk_modify(int unit, 2931 bcm_trunk_t tid, 2932 bcm_trunk_info_t *trunk_info, 2933 int member_count, 2934 bcm_trunk_member_t *member_array, 2935 trunk_private_t *t_info, 2936 int op, 2937 bcm_trunk_member_t *member) 2938 { 2939 int rv = BCM_E_NONE; 2940 bcm_trunk_chip_info_t chip_info; 2941 _esw_trunk_add_info_t add_info; 2942 int i; 2943 int higig_trunk; 2944 2945 if (trunk_info->psc <= 0) { 2946 trunk_info->psc = BCM_TRUNK_PSC_DEFAULT; 2947 } 2948 BCM_IF_ERROR_RETURN 2949 (_bcm_xgs3_trunk_psc_to_rtag(unit, trunk_info->psc, &(t_info->rtag))); 2950 2951 t_info->flags = trunk_info->flags; 2952 2953 if ((trunk_info->dlf_index != trunk_info->mc_index) || 2954 (trunk_info->dlf_index != trunk_info->ipmc_index)) { 2955 return BCM_E_PARAM; 2956 } 2957 2958 t_info->dlf_index_spec = 2959 t_info->dlf_index_used = 2960 t_info->mc_index_spec = 2961 t_info->mc_index_used = 2962 t_info->ipmc_index_spec = 2963 t_info->ipmc_index_used = trunk_info->dlf_index; 2964 2965 if (member_count < 1) { 2966 if (t_info->in_use) { 2967 /* Delete existing trunk member ports */ 2968 BCM_IF_ERROR_RETURN 2969 (bcm_xgs3_trunk_destroy(unit, tid, t_info)); 2970 } 2971 } else { 2972 sal_memset(&add_info, 0, sizeof(_esw_trunk_add_info_t)); 2973 2974 add_info.flags = trunk_info->flags; 2975 add_info.num_ports = member_count; 2976 add_info.psc = trunk_info->psc; 2977 add_info.ipmc_psc = trunk_info->ipmc_psc; 2978 add_info.dlf_index = trunk_info->dlf_index; 2979 add_info.mc_index = trunk_info->mc_index; 2980 add_info.ipmc_index = trunk_info->ipmc_index; 2981 2982 BCM_IF_ERROR_RETURN 2983 (_xgs3_trunk_add_info_member_alloc(&add_info, member_count)); 2984 2985 for (i = 0; i < member_count; i++) { 2986 add_info.member_flags[i] = member_array[i].flags; 2987 add_info.tp[i] = member_array[i].gport; 2988 add_info.tm[i] = -1; 2989 } 2990 2991 /* Convert member gport to module and port */ 2992 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 2993 if (chip_info.trunk_fabric_id_min >= 0 && 2994 tid >= chip_info.trunk_fabric_id_min) { 2995 higig_trunk = 1; 2996 } else { 2997 higig_trunk = 0; 2998 } 2999 rv = _bcm_esw_trunk_gport_array_resolve(unit, 3000 higig_trunk, 3001 member_count, 3002 add_info.tp, 3003 add_info.tp, 3004 add_info.tm); 3005 if (BCM_FAILURE(rv)) { 3006 _xgs3_trunk_add_info_member_free(&add_info); 3007 return rv; 3008 } 3009 3010 rv = _bcm_xgs3_trunk_set(unit, tid, &add_info, t_info); 3011 _xgs3_trunk_add_info_member_free(&add_info); 3012 } 3013 3014 return rv; 3015 } 3016 3017 STATIC int 3018 _bcm_xgs3_trunk_fabric_destroy(int unit, 3019 bcm_trunk_t hgtid, 3020 trunk_private_t *t_info) 3021 { 3022 int i, tid; 3023 3024 /* Clear trunk member info */ 3025 tid = hgtid + _BCM_FP_TRUNK_NUM_MAX; 3026 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 3027 MEMBER_INFO(unit, tid).modport[i] = 0; 3028 MEMBER_INFO(unit, tid).member_flags[i] = 0; 3029 } 3030 MEMBER_INFO(unit, tid).num_ports = 0; 3031 3032 if ((SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) && 3033 soc_feature(unit, soc_feature_hg_trunking)) { 3034 uint32 hg_group_entry, hg_cntl_entry; 3035 pbmp_t pbmp, hg_pbmp; 3036 uint32 pword, hgp; 3037 soc_field_t *trunkf, rtagf, bmapf; 3038 bcm_port_t port; 3039 #if defined(BCM_FIREBOLT2_SUPPORT) 3040 soc_field_t sizef; 3041 #endif /* BCM_FIREBOLT2_SUPPORT */ 3042 3043 switch (hgtid) { 3044 case 0: 3045 trunkf = _hg_trunk0f; 3046 rtagf = HIGIG_TRUNK_RTAG0f; 3047 bmapf = HIGIG_TRUNK_BITMAP0f; 3048 #if defined(BCM_FIREBOLT2_SUPPORT) 3049 sizef = HIGIG_TRUNK_SIZE0f; 3050 #endif /* BCM_FIREBOLT2_SUPPORT */ 3051 break; 3052 case 1: 3053 trunkf = _hg_trunk1f; 3054 rtagf = HIGIG_TRUNK_RTAG1f; 3055 bmapf = HIGIG_TRUNK_BITMAP1f; 3056 #if defined(BCM_FIREBOLT2_SUPPORT) 3057 sizef = HIGIG_TRUNK_SIZE1f; 3058 #endif /* BCM_FIREBOLT2_SUPPORT */ 3059 break; 3060 default: 3061 return BCM_E_PARAM; 3062 } 3063 3064 SOC_IF_ERROR_RETURN(READ_HIGIG_TRUNK_CONTROLr(unit, &hg_cntl_entry)); 3065 pword = soc_reg_field_get(unit, HIGIG_TRUNK_CONTROLr, hg_cntl_entry, 3066 bmapf); 3067 SOC_PBMP_CLEAR(pbmp); 3068 SOC_PBMP_CLEAR(hg_pbmp); 3069 SOC_PBMP_WORD_SET(hg_pbmp, 0, pword); 3070 if (SOC_IS_RAVEN(unit)) { 3071 /* Use the bitmap directly for Raven */ 3072 SOC_PBMP_ASSIGN(pbmp, hg_pbmp); 3073 } else { 3074 /* For other FBX, map the read higig bitmap to the physical bitmap */ 3075 soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbmp, &pbmp); 3076 } 3077 soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry, 3078 bmapf, 0); 3079 3080 PBMP_ITER(pbmp, port) { 3081 BCM_IF_ERROR_RETURN( 3082 soc_xgs3_port_to_higig_bitmap(unit, port, &hgp)); 3083 BCM_IF_ERROR_RETURN( 3084 soc_xgs3_higig_bitmap_to_higig_port_num(hgp, &hgp)); 3085 soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry, 3086 _hg_cntl0f[hgp], 0); 3087 soc_reg_field_set(unit, HIGIG_TRUNK_CONTROLr, &hg_cntl_entry, 3088 _hg_cntl1f[hgp], 0); 3089 } 3090 SOC_IF_ERROR_RETURN(WRITE_HIGIG_TRUNK_CONTROLr(unit, hg_cntl_entry)); 3091 3092 SOC_IF_ERROR_RETURN(READ_HIGIG_TRUNK_GROUPr(unit, &hg_group_entry)); 3093 for (i = 0; i < 4; i++) { 3094 soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry, 3095 trunkf[i], 0); 3096 } 3097 #if defined(BCM_FIREBOLT2_SUPPORT) 3098 if (soc_feature(unit, soc_feature_trunk_group_size)) { 3099 soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry, 3100 sizef, 0); 3101 } 3102 #endif /* BCM_FIREBOLT2_SUPPORT */ 3103 soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hg_group_entry, 3104 rtagf, 0); 3105 SOC_IF_ERROR_RETURN(WRITE_HIGIG_TRUNK_GROUPr(unit, hg_group_entry)); 3106 3107 SOC_PBMP_CLEAR(hg_pbmp); 3108 BCM_IF_ERROR_RETURN 3109 (_bcm_xgs3_trunk_swfailover_fabric_set(unit, 3110 hgtid, 3111 0, 3112 hg_pbmp)); 3113 3114 t_info->in_use = FALSE; 3115 return BCM_E_NONE; 3116 } 3117 #if defined(BCM_TRIUMPH2_SUPPORT) 3118 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 3119 SOC_IS_VALKYRIE2(unit)) { 3120 uint64 val64; 3121 pbmp_t old_trunk_pbmp, new_trunk_pbmp, hg_pbm; 3122 3123 SOC_IF_ERROR_RETURN 3124 (READ_HG_TRUNK_BITMAP_64r(unit, hgtid, &val64)); 3125 SOC_PBMP_CLEAR(hg_pbm); 3126 SOC_PBMP_WORD_SET(hg_pbm, 0, 3127 soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r, 3128 val64, HIGIG_TRUNK_BITMAP_LOf)); 3129 SOC_PBMP_WORD_SET(hg_pbm, 1, 3130 soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r, 3131 val64, HIGIG_TRUNK_BITMAP_HIf)); 3132 SOC_PBMP_CLEAR(old_trunk_pbmp); 3133 SOC_PBMP_ASSIGN(old_trunk_pbmp, hg_pbm); 3134 3135 COMPILER_64_ZERO(val64); 3136 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_BITMAP_64r(unit, hgtid, val64)); 3137 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_GROUPr(unit, hgtid, val64)); 3138 3139 SOC_PBMP_CLEAR(new_trunk_pbmp); 3140 BCM_IF_ERROR_RETURN 3141 (_bcm_xgs3_trunk_fabric_port_set(unit, 3142 hgtid, 3143 old_trunk_pbmp, 3144 new_trunk_pbmp)); 3145 3146 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 3147 BCM_IF_ERROR_RETURN 3148 (_bcm_xgs3_trunk_failover_set(unit, hgtid, TRUE, NULL)); 3149 } 3150 3151 BCM_IF_ERROR_RETURN 3152 (_bcm_xgs3_trunk_swfailover_fabric_set(unit, 3153 hgtid, 3154 0, 3155 new_trunk_pbmp)); 3156 3157 t_info->in_use = FALSE; 3158 return BCM_E_NONE; 3159 } 3160 #endif /* BCM_TRIUMPH2_SUPPORT */ 3161 #if defined(BCM_GREYHOUND2_SUPPORT) 3162 if (soc_feature(unit, soc_feature_high_portcount_register)) { 3163 uint64 val64; 3164 uint64 hg_trunk_bmap_f; 3165 pbmp_t old_trunk_pbmp, new_trunk_pbmp, hg_pbm; 3166 3167 SOC_IF_ERROR_RETURN 3168 (READ_HG_TRUNK_BITMAP_LOr(unit, hgtid, &val64)); 3169 hg_trunk_bmap_f = 3170 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_LOr, 3171 val64, HIGIG_TRUNK_BITMAPf); 3172 3173 SOC_PBMP_CLEAR(hg_pbm); 3174 SOC_PBMP_WORD_SET(hg_pbm, 0, COMPILER_64_LO(hg_trunk_bmap_f)); 3175 SOC_PBMP_WORD_SET(hg_pbm, 1, COMPILER_64_HI(hg_trunk_bmap_f)); 3176 3177 SOC_IF_ERROR_RETURN 3178 (READ_HG_TRUNK_BITMAP_HIr(unit, hgtid, &val64)); 3179 hg_trunk_bmap_f = 3180 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_HIr, 3181 val64, HIGIG_TRUNK_BITMAPf); 3182 SOC_PBMP_WORD_SET(hg_pbm, 2, COMPILER_64_LO(hg_trunk_bmap_f)); 3183 3184 SOC_PBMP_CLEAR(old_trunk_pbmp); 3185 SOC_PBMP_ASSIGN(old_trunk_pbmp, hg_pbm); 3186 3187 COMPILER_64_ZERO(val64); 3188 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_BITMAP_LOr(unit, hgtid, val64)); 3189 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_BITMAP_HIr(unit, hgtid, val64)); 3190 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_GROUPr(unit, hgtid, val64)); 3191 3192 SOC_PBMP_CLEAR(new_trunk_pbmp); 3193 BCM_IF_ERROR_RETURN( 3194 _bcm_xgs3_trunk_fabric_port_set(unit, hgtid, 3195 old_trunk_pbmp, new_trunk_pbmp)); 3196 3197 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 3198 BCM_IF_ERROR_RETURN 3199 (_bcm_xgs3_trunk_failover_set(unit, hgtid, TRUE, NULL)); 3200 } 3201 3202 BCM_IF_ERROR_RETURN 3203 (_bcm_xgs3_trunk_swfailover_fabric_set(unit, hgtid, 3204 0, new_trunk_pbmp)); 3205 3206 t_info->in_use = FALSE; 3207 return BCM_E_NONE; 3208 } 3209 #endif /* BCM_GREYHOUND2_SUPPORT */ 3210 #if defined(BCM_BRADLEY_SUPPORT) 3211 if (SOC_IS_HBX(unit) || SOC_IS_TRX(unit)) { 3212 uint32 val; 3213 uint64 val64; 3214 pbmp_t old_trunk_pbmp, new_trunk_pbmp, hg_pbm; 3215 3216 SOC_IF_ERROR_RETURN 3217 (READ_HG_TRUNK_BITMAPr(unit, hgtid, &val)); 3218 SOC_PBMP_CLEAR(hg_pbm); 3219 SOC_PBMP_WORD_SET(hg_pbm, 0, 3220 soc_reg_field_get(unit, HG_TRUNK_BITMAPr, 3221 val, HIGIG_TRUNK_BITMAPf)); 3222 SOC_PBMP_CLEAR(old_trunk_pbmp); 3223 soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbm, &old_trunk_pbmp); 3224 3225 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_BITMAPr(unit, hgtid, 0)); 3226 COMPILER_64_ZERO(val64); 3227 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_GROUPr(unit, hgtid, val64)); 3228 3229 #if defined(BCM_SCORPION_SUPPORT) 3230 if (SOC_IS_SC_CQ(unit)) { 3231 SOC_IF_ERROR_RETURN 3232 (WRITE_HG_TRUNK_GROUP_HIr(unit, hgtid, val64)); 3233 } 3234 #endif 3235 SOC_PBMP_CLEAR(new_trunk_pbmp); 3236 BCM_IF_ERROR_RETURN 3237 (_bcm_xgs3_trunk_fabric_port_set(unit, 3238 hgtid, 3239 old_trunk_pbmp, 3240 new_trunk_pbmp)); 3241 3242 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 3243 BCM_IF_ERROR_RETURN 3244 (_bcm_xgs3_trunk_failover_set(unit, hgtid, TRUE, NULL)); 3245 } 3246 3247 BCM_IF_ERROR_RETURN 3248 (_bcm_xgs3_trunk_swfailover_fabric_set(unit, 3249 hgtid, 3250 0, 3251 new_trunk_pbmp)); 3252 3253 t_info->in_use = FALSE; 3254 return BCM_E_NONE; 3255 } 3256 #endif /* BCM_BRADLEY_SUPPORT */ 3257 3258 3259 return BCM_E_UNAVAIL; 3260 } 3261 3262 /* 3263 * Function: 3264 * bcm_xgs3_trunk_destroy 3265 * Purpose: 3266 * Multiplexed trunking function for XGS3 3267 */ 3268 int 3269 bcm_xgs3_trunk_destroy(int unit, 3270 bcm_trunk_t tid, 3271 trunk_private_t *t_info) 3272 { 3273 bcm_module_t mod; 3274 bcm_port_t port, loc_port; 3275 bcm_gport_t gport; 3276 pbmp_t old_ports, new_ports; 3277 int i; 3278 bcm_trunk_chip_info_t chip_info; 3279 int num_leaving_members = 0; 3280 bcm_gport_t leaving_members[BCM_SWITCH_TRUNK_MAX_PORTCNT]; 3281 soc_mem_t trunk_mem = TRUNK_GROUPm; 3282 3283 if (soc_feature(unit, soc_feature_fastlag)) { 3284 trunk_mem = FAST_TRUNK_GROUPm; 3285 } 3286 3287 SOC_PBMP_CLEAR(new_ports); 3288 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 3289 if (chip_info.trunk_fabric_id_min >= 0 && 3290 tid >= chip_info.trunk_fabric_id_min) { /* fabric trunk */ 3291 tid -= chip_info.trunk_fabric_id_min; 3292 return _bcm_xgs3_trunk_fabric_destroy(unit, tid, t_info); 3293 } 3294 3295 /* front panel trunks */ 3296 3297 SOC_PBMP_CLEAR(old_ports); 3298 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 3299 mod = MEMBER_INFO(unit, tid).modport[i] >> 8; 3300 port = MEMBER_INFO(unit, tid).modport[i] & 0xff; 3301 BCM_GPORT_MODPORT_SET(gport, mod, port); 3302 if (BCM_SUCCESS(bcm_esw_port_local_get(unit, gport, &loc_port))) { 3303 SOC_PBMP_PORT_ADD(old_ports, loc_port); 3304 } 3305 leaving_members[num_leaving_members++] = gport; 3306 BCM_IF_ERROR_RETURN 3307 (_bcm_xgs3_trunk_set_port_property(unit, mod, port, -1)); 3308 } 3309 3310 /* 3311 * Remove ports from the block mask table 3312 */ 3313 if (SOC_PBMP_NOT_NULL(old_ports)) { 3314 SOC_PBMP_CLEAR(new_ports); 3315 /* coverity[divide_by_zero] */ 3316 BCM_IF_ERROR_RETURN( 3317 _bcm_xgs3_trunk_block_mask(unit, old_ports, new_ports, 3318 new_ports, 0, 0)); 3319 } 3320 3321 /* 3322 * Reset table entries to empty state 3323 */ 3324 if (soc_feature(unit, soc_feature_trunk_egress)) { 3325 BCM_IF_ERROR_RETURN( 3326 soc_mem_write(unit, TRUNK_EGR_MASKm, MEM_BLOCK_ALL, tid, 3327 soc_mem_entry_null(unit, TRUNK_EGR_MASKm))); 3328 } 3329 BCM_IF_ERROR_RETURN( 3330 soc_mem_write(unit, TRUNK_BITMAPm, MEM_BLOCK_ALL, tid, 3331 soc_mem_entry_null(unit, TRUNK_BITMAPm))); 3332 BCM_IF_ERROR_RETURN( 3333 soc_mem_write(unit, trunk_mem, MEM_BLOCK_ALL, tid, 3334 soc_mem_entry_null(unit, trunk_mem))); 3335 /* 3336 * Remove ports from failover 3337 */ 3338 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 3339 if (soc_feature(unit, soc_feature_port_lag_failover)) { 3340 BCM_IF_ERROR_RETURN 3341 (_bcm_xgs3_trunk_failover_set(unit, tid, FALSE, NULL)); 3342 } 3343 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 3344 3345 BCM_IF_ERROR_RETURN 3346 (_bcm_xgs3_trunk_swfailover_set(unit, 3347 tid, 3348 0, 3349 0, 3350 (int *)0, 3351 (int *)0, 3352 NULL)); 3353 3354 /* Clear trunk properties from members */ 3355 BCM_IF_ERROR_RETURN(_bcm_xgs3_trunk_property_migrate(unit, 3356 num_leaving_members, leaving_members, 3357 0, NULL, 0, NULL)); 3358 3359 /* Clear trunk member info */ 3360 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 3361 MEMBER_INFO(unit, tid).modport[i] = 0; 3362 MEMBER_INFO(unit, tid).member_flags[i] = 0; 3363 } 3364 MEMBER_INFO(unit, tid).num_ports = 0; 3365 3366 t_info->in_use = FALSE; 3367 return BCM_E_NONE; 3368 } 3369 3370 STATIC int 3371 _bcm_xgs3_trunk_fabric_get(int unit, 3372 bcm_trunk_t hgtid, 3373 _esw_trunk_add_info_t *t_data, 3374 trunk_private_t *t_info) 3375 { 3376 bcm_trunk_t tid; 3377 bcm_module_t modid; 3378 bcm_port_t port; 3379 int i; 3380 3381 tid = hgtid + _BCM_FP_TRUNK_NUM_MAX; 3382 3383 if (t_data->num_ports == 0) { 3384 t_data->num_ports = MEMBER_INFO(unit, tid).num_ports; 3385 } else { 3386 if (MEMBER_INFO(unit, tid).num_ports <= t_data->num_ports) { 3387 t_data->num_ports = MEMBER_INFO(unit, tid).num_ports; 3388 } 3389 3390 if (BCM_FAILURE(bcm_esw_stk_my_modid_get(unit, &modid))) { 3391 modid = 0; 3392 } 3393 3394 for (i = 0; i < t_data->num_ports; i++) { 3395 port = MEMBER_INFO(unit, tid).modport[i] & 0xff; 3396 BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, 3397 BCM_STK_MODMAP_GET, modid, port, 3398 &t_data->tm[i], &t_data->tp[i])); 3399 } 3400 } 3401 3402 return BCM_E_NONE; 3403 } 3404 3405 /* 3406 * Function: 3407 * _bcm_xgs3_trunk_get 3408 * Purpose: 3409 * Multiplexed trunking function for XGS3 3410 */ 3411 STATIC int 3412 _bcm_xgs3_trunk_get(int unit, 3413 bcm_trunk_t tid, 3414 _esw_trunk_add_info_t *t_data, 3415 trunk_private_t *t_info) 3416 { 3417 bcm_module_t mod_out; 3418 bcm_port_t port_out; 3419 int i; 3420 bcm_trunk_chip_info_t chip_info; 3421 3422 t_data->flags = t_info->flags; 3423 t_data->psc = t_info->psc; 3424 t_data->ipmc_psc = t_info->ipmc_psc; 3425 t_data->dlf_index = t_info->dlf_index_used; 3426 t_data->mc_index = t_info->mc_index_used; 3427 t_data->ipmc_index = t_info->ipmc_index_used; 3428 3429 if (!t_info->in_use) { 3430 t_data->num_ports = 0; 3431 return BCM_E_NONE; 3432 } 3433 3434 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 3435 if (chip_info.trunk_fabric_id_min >= 0 && 3436 tid >= chip_info.trunk_fabric_id_min) { /* fabric trunk */ 3437 tid -= chip_info.trunk_fabric_id_min; 3438 return _bcm_xgs3_trunk_fabric_get(unit, tid, t_data, t_info); 3439 } 3440 3441 if (t_data->num_ports == 0) { 3442 t_data->num_ports = MEMBER_INFO(unit, tid).num_ports; 3443 } else { 3444 if (MEMBER_INFO(unit, tid).num_ports <= t_data->num_ports) { 3445 t_data->num_ports = MEMBER_INFO(unit, tid).num_ports; 3446 } 3447 3448 for (i = 0; i < t_data->num_ports; i++) { 3449 BCM_IF_ERROR_RETURN 3450 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 3451 MEMBER_INFO(unit, tid).modport[i] >> 8, 3452 MEMBER_INFO(unit, tid).modport[i] & 0xff, 3453 &mod_out, &port_out)); 3454 t_data->tm[i] = mod_out; 3455 t_data->tp[i] = port_out; 3456 /* Copy member flags */ 3457 t_data->member_flags[i] = MEMBER_INFO(unit, tid).member_flags[i]; 3458 } 3459 } 3460 3461 return BCM_E_NONE; 3462 } 3463 3464 /* 3465 * Function: 3466 * bcm_xgs3_trunk_get 3467 * Purpose: 3468 * Return a trunk information of given trunk ID. 3469 * Parameters: 3470 * unit - (IN) StrataSwitch PCI device unit number (driver internal). 3471 * tid - (IN) Trunk ID. 3472 * trunk_info - (OUT) Place to store returned trunk info. 3473 * member_max - (IN) Size of member_array. 3474 * member_array - (OUT) Array of trunk member structures. 3475 * member_count - (OUT) Number of trunk members returned. 3476 * t_info - (IN) Internal trunk info. 3477 * Returns: 3478 * BCM_E_NONE Success. 3479 * BCM_E_XXX 3480 */ 3481 int 3482 bcm_xgs3_trunk_get(int unit, 3483 bcm_trunk_t tid, 3484 bcm_trunk_info_t *trunk_info, 3485 int member_max, 3486 bcm_trunk_member_t *member_array, 3487 int *member_count, 3488 trunk_private_t *t_info) 3489 { 3490 _esw_trunk_add_info_t add_info; 3491 int i; 3492 int rv = BCM_E_NONE; 3493 bcm_trunk_chip_info_t chip_info; 3494 int higig_trunk; 3495 3496 sal_memset(&add_info, 0, sizeof(_esw_trunk_add_info_t)); 3497 add_info.num_ports = member_max; 3498 if (member_max > 0) { 3499 BCM_IF_ERROR_RETURN 3500 (_xgs3_trunk_add_info_member_alloc(&add_info, member_max)); 3501 } 3502 3503 rv = _bcm_xgs3_trunk_get(unit, tid, &add_info, t_info); 3504 if (BCM_FAILURE(rv)) { 3505 if (member_max > 0) { 3506 _xgs3_trunk_add_info_member_free(&add_info); 3507 } 3508 return rv; 3509 } 3510 3511 trunk_info->flags = add_info.flags; 3512 trunk_info->psc = add_info.psc; 3513 trunk_info->ipmc_psc = add_info.ipmc_psc; 3514 trunk_info->dlf_index = add_info.dlf_index; 3515 trunk_info->mc_index = add_info.mc_index; 3516 trunk_info->ipmc_index = add_info.ipmc_index; 3517 3518 *member_count = add_info.num_ports; 3519 3520 if (member_max > 0) { 3521 if (member_max < *member_count) { 3522 *member_count = member_max; 3523 } 3524 3525 /* Construct member gport */ 3526 rv = bcm_esw_trunk_chip_info_get(unit, &chip_info); 3527 if (BCM_FAILURE(rv)) { 3528 _xgs3_trunk_add_info_member_free(&add_info); 3529 return rv; 3530 } 3531 if (chip_info.trunk_fabric_id_min >= 0 && 3532 tid >= chip_info.trunk_fabric_id_min) { 3533 higig_trunk = 1; 3534 } else { 3535 higig_trunk = 0; 3536 } 3537 rv = _bcm_esw_trunk_gport_construct(unit, higig_trunk, 3538 *member_count, 3539 add_info.tp, add_info.tm, 3540 add_info.tp); 3541 if (BCM_FAILURE(rv)) { 3542 _xgs3_trunk_add_info_member_free(&add_info); 3543 return rv; 3544 } 3545 3546 for (i = 0; i < *member_count; i++) { 3547 bcm_trunk_member_t_init(&member_array[i]); 3548 member_array[i].flags = add_info.member_flags[i]; 3549 member_array[i].gport = add_info.tp[i]; 3550 } 3551 3552 _xgs3_trunk_add_info_member_free(&add_info); 3553 } 3554 3555 return rv; 3556 } 3557 3558 /* 3559 * Function: 3560 * bcm_xgs3_trunk_mcast_join 3561 * Purpose: 3562 * Multiplexed function for XGS3 3563 * Returns: 3564 * BCM_E_NONE - Success 3565 * BCM_E_INTERNAL - Read failure 3566 * BCM_E_XXX - from bcm_mcast_port_get() or bcm_mcast_port_add() 3567 */ 3568 int 3569 bcm_xgs3_trunk_mcast_join(int unit, bcm_trunk_t tid, bcm_vlan_t vid, 3570 sal_mac_addr_t mac, trunk_private_t *t_info) 3571 { 3572 trunk_bitmap_entry_t trunk_bitmap_entry; 3573 bcm_mcast_addr_t mc_addr; 3574 bcm_trunk_chip_info_t chip_info; 3575 3576 /* initialising and setting the mc_addr struct by bcm_mcast_addr_t_init() */ 3577 bcm_mcast_addr_t_init(&mc_addr,mac,vid); 3578 3579 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 3580 if ((tid >= chip_info.trunk_id_min) && (tid <= chip_info.trunk_id_max)) { 3581 /* get the ports in the trunk group */ 3582 SOC_IF_ERROR_RETURN 3583 (soc_mem_read(unit, TRUNK_BITMAPm, MEM_BLOCK_ANY, tid, 3584 &trunk_bitmap_entry)); 3585 soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 3586 TRUNK_BITMAPf, &mc_addr.pbmp); 3587 } else { 3588 return BCM_E_PARAM; 3589 } 3590 3591 /* Add the trunk group's ports to the multicast group. */ 3592 return bcm_esw_mcast_port_add(unit, &mc_addr); 3593 } 3594 3595 int 3596 _bcm_xgs3_trunk_swfailover_init(int unit) 3597 { 3598 if (_xgs3_trunk_swfail[unit] == NULL) { 3599 _xgs3_trunk_swfail[unit] = sal_alloc(sizeof(_xgs3_trunk_swfail_t), 3600 "_xgs3_trunk_swfail"); 3601 if (_xgs3_trunk_swfail[unit] == NULL) { 3602 return BCM_E_MEMORY; 3603 } 3604 } 3605 sal_memset(_xgs3_trunk_swfail[unit], 0, sizeof(_xgs3_trunk_swfail_t)); 3606 return BCM_E_NONE; 3607 } 3608 3609 void 3610 _bcm_xgs3_trunk_swfailover_detach(int unit) 3611 { 3612 if (_xgs3_trunk_swfail[unit] != NULL) { 3613 sal_free(_xgs3_trunk_swfail[unit]); 3614 _xgs3_trunk_swfail[unit] = NULL; 3615 } 3616 } 3617 3618 STATIC int 3619 _bcm_xgs3_trunk_swfailover_set(int unit, 3620 bcm_trunk_t tid, 3621 int rtag, 3622 int nports, 3623 int mods[BCM_XGS3_TRUNK_MAX_PORTCNT], 3624 int ports[BCM_XGS3_TRUNK_MAX_PORTCNT], 3625 uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT]) 3626 { 3627 _xgs3_trunk_swfail_t *swf; 3628 _xgs3_tinfo_t *swft; 3629 bcm_pbmp_t localports; 3630 bcm_port_t port; 3631 bcm_module_t my_modid; 3632 int i; 3633 3634 if (_xgs3_trunk_swfail[unit] == NULL) { 3635 return BCM_E_INIT; 3636 } 3637 3638 BCM_IF_ERROR_RETURN 3639 (bcm_esw_stk_my_modid_get(unit, &my_modid)); 3640 3641 swf = _xgs3_trunk_swfail[unit]; 3642 swft = &swf->tinfo[tid]; 3643 3644 swf->mymodid = my_modid; 3645 swft->rtag = rtag; 3646 swft->num_ports = nports; 3647 BCM_PBMP_CLEAR(localports); 3648 for (i = 0; i < nports; i++) { 3649 swft->modport[i] = (mods[i] << 8) | ports[i]; 3650 swft->member_flags[i] = member_flags[i]; 3651 if (mods[i] == my_modid) { 3652 BCM_PBMP_PORT_ADD(localports, ports[i]); 3653 } 3654 } 3655 PBMP_ALL_ITER(unit, port) { 3656 if (BCM_PBMP_MEMBER(localports, port)) { 3657 swf->trunk[port] = tid + 1; 3658 } else if (swf->trunk[port] == tid + 1) { 3659 swf->trunk[port] = 0; /* remove stale pointers to tid */ 3660 } 3661 } 3662 return BCM_E_NONE; 3663 } 3664 3665 STATIC int 3666 _bcm_xgs3_trunk_swfailover_fabric_set(int unit, 3667 bcm_trunk_t hgtid, 3668 int rtag, 3669 bcm_pbmp_t ports) 3670 { 3671 _xgs3_trunk_swfail_t *swf; 3672 _xgs3_tinfo_t *swft; 3673 bcm_port_t port; 3674 int nports; 3675 3676 if (_xgs3_trunk_swfail[unit] == NULL) { 3677 return BCM_E_INIT; 3678 } 3679 3680 swf = _xgs3_trunk_swfail[unit]; 3681 swft = &swf->tinfo[hgtid + _BCM_FP_TRUNK_NUM_MAX]; 3682 3683 swft->rtag = rtag; 3684 nports = 0; 3685 PBMP_ITER(ports, port) { 3686 swft->modport[nports] = port; 3687 nports += 1; 3688 } 3689 swft->num_ports = nports; 3690 PBMP_ALL_ITER(unit, port) { 3691 if (BCM_PBMP_MEMBER(ports, port)) { 3692 swf->trunk[port] = hgtid + _BCM_FABRIC_TRUNK_SWF_TID_OFFSET; 3693 } else if (swf->trunk[port] == 3694 (hgtid + _BCM_FABRIC_TRUNK_SWF_TID_OFFSET)) { 3695 swf->trunk[port] = 0; /* remove stale pointers to tid */ 3696 } 3697 } 3698 return BCM_E_NONE; 3699 } 3700 3701 #ifdef BCM_TRUNK_FAILOVER_SUPPORT 3702 3703 /* fields from HIGIG_TRUNK_GROUPr */ 3704 static soc_field_t _hg_trunkf[2][4] = { 3705 { 3706 HIGIG_TRUNK_ID0_PORT0f, HIGIG_TRUNK_ID0_PORT1f, 3707 HIGIG_TRUNK_ID0_PORT2f, HIGIG_TRUNK_ID0_PORT3f}, 3708 { 3709 HIGIG_TRUNK_ID1_PORT0f, HIGIG_TRUNK_ID1_PORT1f, 3710 HIGIG_TRUNK_ID1_PORT2f, HIGIG_TRUNK_ID1_PORT3f} 3711 }; 3712 3713 static soc_field_t _hg_trunk_rtagf[2] = { 3714 HIGIG_TRUNK_RTAG0f, HIGIG_TRUNK_RTAG1f 3715 }; 3716 3717 /* 3718 * Re-programs fabric trunk 3719 */ 3720 STATIC void 3721 _bcm_xgs3_trunk_fabric_swfailover_trigger(int unit, 3722 bcm_port_t port, 3723 int hgtid, 3724 _xgs3_trunk_swfail_t *swf) 3725 { 3726 int i, j, k, nmp, p; 3727 _xgs3_tinfo_t *swft; 3728 3729 swft = &swf->tinfo[hgtid + _BCM_FP_TRUNK_NUM_MAX]; 3730 3731 /* update the _xgs3_trunk_swfail entry */ 3732 nmp = swft->num_ports; 3733 for (i = j = 0; i < nmp; i++) { 3734 if (swft->modport[i] != port) { 3735 if (i != j) { 3736 swft->modport[j] = swft->modport[i]; 3737 } 3738 j += 1; 3739 } 3740 } 3741 3742 if (j == nmp) { 3743 return; /* no changes, so no need to write out */ 3744 } 3745 3746 swft->num_ports = nmp = j; 3747 3748 if (SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) { 3749 uint32 hgtrunk; 3750 hgtrunk = 0; 3751 3752 for (k = j = 0; k < 2; k++) { 3753 swft = &swf->tinfo[_BCM_FP_TRUNK_NUM_MAX + k]; 3754 nmp = swft->num_ports; 3755 soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hgtrunk, 3756 _hg_trunk_rtagf[k], swft->rtag); 3757 if (nmp == 0) { 3758 p = 0; 3759 } else { 3760 if (SOC_IS_RAVEN(unit)) { 3761 p = swft->modport[0]; 3762 } else { 3763 if(soc_xgs3_port_to_higig_bitmap(unit, 3764 swft->modport[0], (uint32 *)&p) != BCM_E_NONE) { 3765 return; 3766 } 3767 if(soc_xgs3_higig_bitmap_to_higig_port_num(p, 3768 (uint32 *)&p) != BCM_E_NONE) { 3769 return; 3770 } 3771 } 3772 } 3773 3774 for (i = 0; i < 4; i++) { 3775 soc_reg_field_set(unit, HIGIG_TRUNK_GROUPr, &hgtrunk, 3776 _hg_trunkf[k][i], p); 3777 if (nmp > 1) { 3778 j += 1; 3779 if (j >= nmp) { 3780 j = 0; 3781 } 3782 if (SOC_IS_RAVEN(unit)) { 3783 p = swft->modport[j]; 3784 } else { 3785 if(soc_xgs3_port_to_higig_bitmap(unit, 3786 swft->modport[j], (uint32 *)&p) != BCM_E_NONE) { 3787 return; 3788 } 3789 if(soc_xgs3_higig_bitmap_to_higig_port_num(p, 3790 (uint32 *)&p) != BCM_E_NONE) { 3791 return; 3792 } 3793 } 3794 } 3795 } 3796 } 3797 3798 (void)WRITE_HIGIG_TRUNK_GROUPr(unit, hgtrunk); 3799 } else if (SOC_IS_HB_GW(unit)) { 3800 #if defined(BCM_BRADLEY_SUPPORT) 3801 uint64 hgtrunk; 3802 3803 COMPILER_64_ZERO(hgtrunk); 3804 if (nmp == 0) { 3805 p = 31; /* just drop it */ 3806 } else { 3807 p = swft->modport[0]; 3808 } 3809 for (i = j = 0; i < 8; i++) { 3810 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk, 3811 _hg_trunk[i], p); 3812 if (nmp > 1) { 3813 j += 1; 3814 if (j >= nmp) { 3815 j = 0; 3816 } 3817 p = swft->modport[j]; 3818 } 3819 } 3820 3821 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk, 3822 HIGIG_TRUNK_SIZEf, nmp ? nmp-1 : 0); 3823 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk, 3824 HIGIG_TRUNK_RTAGf, swft->rtag); 3825 (void)WRITE_HG_TRUNK_GROUPr(unit, hgtid, hgtrunk); 3826 #endif /* BCM_BRADLEY_SUPPORT */ 3827 } else if (SOC_IS_SC_CQ(unit)) { 3828 #if defined(BCM_SCORPION_SUPPORT) 3829 uint64 hgtrunk; 3830 3831 3832 COMPILER_64_ZERO(hgtrunk); 3833 if (nmp == 0) { 3834 p = 31; /* just drop it */ 3835 } else { 3836 p = swft->modport[0]; 3837 } 3838 for (i = j = 0; i < 8; i++) { 3839 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk, 3840 _hg_trunk[i], p); 3841 if (nmp > 1) { 3842 j += 1; 3843 if (j >= nmp) { 3844 j = 0; 3845 } 3846 p = swft->modport[j]; 3847 } 3848 } 3849 3850 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk, 3851 HIGIG_TRUNK_SIZEf, nmp ? nmp-1 : 0); 3852 soc_reg64_field32_set(unit, HG_TRUNK_GROUPr, &hgtrunk, 3853 HIGIG_TRUNK_RTAGf, swft->rtag); 3854 (void)WRITE_HG_TRUNK_GROUPr(unit, hgtid, hgtrunk); 3855 #endif /* BCM_SCORPION_SUPPORT */ 3856 } 3857 } 3858 3859 int 3860 _bcm_xgs3_trunk_swfailover_trigger(int unit, 3861 bcm_pbmp_t ports_active, 3862 bcm_pbmp_t ports_status) 3863 { 3864 bcm_port_t port; 3865 int tid; 3866 _xgs3_trunk_swfail_t *swf; 3867 _xgs3_tinfo_t *swft; 3868 soc_mem_t trunk_mem = TRUNK_GROUPm; 3869 3870 if (soc_feature(unit, soc_feature_fastlag)) { 3871 trunk_mem = FAST_TRUNK_GROUPm; 3872 } 3873 3874 swf = _xgs3_trunk_swfail[unit]; 3875 3876 if (swf == NULL) { 3877 return BCM_E_NONE; 3878 } 3879 3880 PBMP_ITER(ports_active, port) { 3881 if (BCM_PBMP_MEMBER(ports_status, port)) { 3882 continue; /* link up */ 3883 } 3884 3885 /* link down */ 3886 tid = swf->trunk[port]; 3887 swf->trunk[port] = 0; 3888 if (tid <= 0) { 3889 continue; /* already removed */ 3890 } 3891 3892 if (tid >= 1 && tid < _BCM_FP_TRUNK_NUM_MAX + 1) { 3893 uint32 tg_entry[SOC_MAX_MEM_WORDS]; 3894 uint16 modport; 3895 int i, j, nmp; 3896 int uc_nmp; 3897 pbmp_t old_trunk_pbmp; 3898 pbmp_t new_trunk_pbmp; 3899 pbmp_t nuc_trunk_pbmp; 3900 trunk_bitmap_entry_t tb_entry; 3901 bcm_module_t mods[BCM_XGS3_TRUNK_MAX_PORTCNT]; 3902 uint16 uc_modport[BCM_XGS3_TRUNK_MAX_PORTCNT]; 3903 int max_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 3904 uint32 my_modid_bmap = 0; 3905 uint32 nuc_member_count = 0; 3906 uint32 nuc_tpbm = 0; 3907 3908 tid = tid - 1; 3909 swft = &swf->tinfo[tid]; 3910 SOC_PBMP_CLEAR(old_trunk_pbmp); 3911 SOC_PBMP_CLEAR(new_trunk_pbmp); 3912 3913 /* update _xgs3_trunk_swfail: remove matching ports, update size */ 3914 modport = (swf->mymodid << 8) | port; 3915 nmp = swft->num_ports; 3916 3917 for (i = j = 0; i < nmp; i++) { 3918 if (swft->modport[i] != modport) { 3919 if (i != j) { 3920 swft->modport[j] = swft->modport[i]; 3921 swft->member_flags[j] = swft->member_flags[i]; 3922 } 3923 j++; 3924 } 3925 if (swf->mymodid == (swft->modport[i] >> 8)) { 3926 SOC_PBMP_PORT_ADD(old_trunk_pbmp, swft->modport[i] & 0xff); 3927 } 3928 } 3929 if (j == nmp) { 3930 continue; /* no changes, so no need to write out */ 3931 } 3932 3933 swft->num_ports = nmp = j; 3934 3935 uc_nmp = 0; 3936 for (i = 0; i < nmp; i++) { 3937 if (swft->member_flags[i] & 3938 BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) { 3939 continue; 3940 } 3941 uc_modport[uc_nmp++] = swft->modport[i]; 3942 } 3943 3944 /* convert _xgs3_trunk_swfail into trunk_group entry */ 3945 if (soc_feature(unit, soc_feature_fastlag)) { 3946 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, swft->rtag); 3947 } else { 3948 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, swft->rtag); 3949 } 3950 #if defined(BCM_BRADLEY_SUPPORT) 3951 if (SOC_IS_HBX(unit)) { 3952 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 3953 uc_nmp ? uc_nmp-1 : 0); 3954 } 3955 #endif /* BCM_BRADLEY_SUPPORT */ 3956 if (uc_nmp == 0) { 3957 for (i = 0; i < max_ports; i++) { 3958 if (soc_feature(unit, soc_feature_fastlag)) { 3959 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, 3960 _xgs_fast_modulef[i], swf->mymodid); 3961 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, 3962 _xgs_fast_portf[i], SOC_PORT_ADDR_MAX(unit)); 3963 } else { 3964 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, 3965 _xgs_modulef[i], swf->mymodid); 3966 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, 3967 _xgs_portf[i], SOC_PORT_ADDR_MAX(unit)); 3968 } 3969 /* The assumption here is that SOC_PORT_ADDR_MAX is an 3970 * invalid port number. Hardware will drop packets destined 3971 * to an invalid port number. 3972 */ 3973 } 3974 } else { 3975 for (i = 0; i < max_ports; i++) { 3976 if (soc_feature(unit, soc_feature_fastlag)) { 3977 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, 3978 _xgs_fast_modulef[i], uc_modport[i%uc_nmp] >> 8); 3979 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, 3980 _xgs_fast_portf[i], uc_modport[i%uc_nmp] & 0xff); 3981 } else { 3982 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, 3983 _xgs_modulef[i], uc_modport[i%uc_nmp] >> 8); 3984 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, 3985 _xgs_portf[i], uc_modport[i%uc_nmp] & 0xff); 3986 } 3987 } 3988 } 3989 3990 /* write out the trunk_group entry */ 3991 (void)soc_mem_write(unit, trunk_mem, MEM_BLOCK_ALL, 3992 tid, &tg_entry); 3993 3994 /* update TRUNK_BITMAP table */ 3995 SOC_PBMP_CLEAR(new_trunk_pbmp); 3996 for (i = 0; i < nmp; i++) { 3997 if ((swft->modport[i] >> 8) == swf->mymodid) { 3998 SOC_PBMP_PORT_ADD(new_trunk_pbmp, swft->modport[i] & 0xff); 3999 } 4000 } 4001 (void)soc_mem_read(unit, TRUNK_BITMAPm, MEM_BLOCK_ANY, tid, 4002 &tb_entry); 4003 soc_mem_pbmp_field_set(unit, TRUNK_BITMAPm, &tb_entry, 4004 TRUNK_BITMAPf, &new_trunk_pbmp); 4005 (void)soc_mem_write(unit, TRUNK_BITMAPm, MEM_BLOCK_ALL, tid, 4006 &tb_entry); 4007 4008 /* update non uc trunk block mask table */ 4009 for (i = 0; i < nmp; i++) { 4010 mods[i] = swft->modport[i] >> 8; 4011 } 4012 BCM_IF_ERROR_RETURN(_bcm_nuc_tpbm_get(unit, nmp, mods, &nuc_tpbm)); 4013 4014 SOC_PBMP_CLEAR(nuc_trunk_pbmp); 4015 for (i= 0; i < nmp; i++) { 4016 if (swf->mymodid == (swft->modport[i] >> 8)) { 4017 /* local port */ 4018 if (nuc_tpbm & (1 << i)) { 4019 /* Eligible for NUC forwarding */ 4020 SOC_PBMP_PORT_ADD(nuc_trunk_pbmp, 4021 swft->modport[i] & 0xff); 4022 my_modid_bmap |= (1 << nuc_member_count); 4023 } 4024 } 4025 4026 if (nuc_tpbm & (1 << i)) { 4027 /* Eligible for NUC forwarding */ 4028 nuc_member_count++; 4029 } 4030 } 4031 4032 BCM_IF_ERROR_RETURN 4033 (_bcm_xgs3_trunk_block_mask(unit, 4034 old_trunk_pbmp, 4035 new_trunk_pbmp, 4036 nuc_trunk_pbmp, 4037 my_modid_bmap, 4038 nuc_member_count)); 4039 } else if ((tid >= _BCM_FABRIC_TRUNK_SWF_TID_OFFSET) && 4040 (tid < (_BCM_FABRIC_TRUNK_NUM_MAX + 4041 _BCM_FABRIC_TRUNK_SWF_TID_OFFSET))) { 4042 /* higig trunk */ 4043 _bcm_xgs3_trunk_fabric_swfailover_trigger(unit, 4044 port, 4045 tid - _BCM_FABRIC_TRUNK_SWF_TID_OFFSET, 4046 swf); 4047 } 4048 } 4049 4050 return BCM_E_NONE; 4051 } 4052 #endif /* BCM_TRUNK_FAILOVER_SUPPORT */ 4053 4054 #ifdef BCM_WARM_BOOT_SUPPORT 4055 /* Set psc argument to trunk group default first, then call this */ 4056 STATIC void 4057 _bcm_xgs3_trunk_rtag_to_psc(int unit, int rtag, int *psc) 4058 { 4059 if (7 == rtag) { 4060 if (soc_feature(unit, 4061 soc_feature_port_flow_hash)) { 4062 *psc = BCM_TRUNK_PSC_PORTFLOW; 4063 } else if (soc_feature(unit, 4064 soc_feature_port_trunk_index)) { 4065 *psc = BCM_TRUNK_PSC_PORTINDEX; 4066 } /* Else, unknown, use default */ 4067 } else if (0 < rtag) { 4068 /* HW and SW values match */ 4069 *psc = rtag; 4070 } else { 4071 /* Use trunk group value as the default */ 4072 } 4073 } 4074 4075 /* 4076 * Handle state recovery for front panel trunks 4077 */ 4078 int 4079 _xgs3_trunk_reinit(int unit, int ngroups_fp, trunk_private_t *trunk_info) 4080 { 4081 int rv = BCM_E_UNAVAIL; 4082 4083 #if defined(BCM_FIREBOLT_SUPPORT) 4084 if (SOC_IS_FBX(unit)) { 4085 bcm_trunk_t tid, tid_get; 4086 trunk_private_t *t_info; 4087 uint32 tg_entry[SOC_MAX_MEM_WORDS]; 4088 bcm_module_t egr_hw_mods[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 }; 4089 bcm_port_t egr_hw_ports[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 }; 4090 uint32 egr_member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT] = { 0 }; 4091 bcm_module_t om[BCM_XGS3_TRUNK_MAX_PORTCNT]; 4092 pbmp_t op[BCM_XGS3_TRUNK_MAX_PORTCNT]; 4093 int max_ports = BCM_SWITCH_TRUNK_MAX_PORTCNT; 4094 source_trunk_map_table_entry_t stm; /* Hw entry buffer. */ 4095 int i, j, num_mod, tgsize, ptype, idx; 4096 int psc, num_egr_ports; 4097 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 4098 _xgs3_hw_tinfo_t *hwft; 4099 int tix, rtag, psc_local; 4100 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 4101 soc_mem_t trunk_mem = TRUNK_GROUPm; 4102 soc_field_t tid_fld = TGIDf; 4103 4104 if (soc_feature(unit, soc_feature_src_tgid_valid)) { 4105 tid_fld = SRC_TGIDf; 4106 } 4107 4108 if (soc_feature(unit, soc_feature_fastlag)) { 4109 trunk_mem = FAST_TRUNK_GROUPm; 4110 } 4111 4112 rv = BCM_E_NONE; 4113 tgsize = soc_mem_entry_words(unit, trunk_mem); 4114 tgsize = WORDS2BYTES(tgsize); 4115 4116 for (tid = 0; tid < ngroups_fp; tid++, trunk_info++) { 4117 SOC_IF_ERROR_RETURN 4118 (soc_mem_read(unit, trunk_mem, MEM_BLOCK_ANY, tid, 4119 &tg_entry)); 4120 if (sal_memcmp(&tg_entry, soc_mem_entry_null(unit, trunk_mem), 4121 tgsize) == 0) { 4122 /* 4123 * Invalid trunk ID 4124 */ 4125 continue; 4126 } 4127 4128 if (MEMBER_INFO(unit, tid).recovered_from_scache) { 4129 for (i = 0, j = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 4130 if (MEMBER_INFO(unit, tid).member_flags[i] & 4131 BCM_TRUNK_MEMBER_EGRESS_DISABLE) { 4132 continue; 4133 } 4134 egr_hw_mods[j] = MEMBER_INFO(unit, tid).modport[i] >> 8; 4135 egr_hw_ports[j] = MEMBER_INFO(unit, tid).modport[i] & 0xff; 4136 egr_member_flags[j] = MEMBER_INFO(unit, tid).member_flags[i]; 4137 j++; 4138 } 4139 num_egr_ports = j; 4140 4141 } else { 4142 /* In level 1 warm boot, not all egress trunk members can be 4143 * recovered from TRUNK_GROUP table, as those members with 4144 * the UNICAST_EGRESS_DISABLE flag set will not be in 4145 * TRUNK_GROUP table. 4146 */ 4147 4148 num_mod = 0; 4149 sal_memset(om, 0, sizeof(om)); 4150 sal_memset(op, 0, sizeof(op)); 4151 4152 for (i = 0; i < max_ports; i++) { 4153 int found = 0; 4154 4155 if (soc_feature(unit, soc_feature_fastlag)) { 4156 egr_hw_mods[i] = soc_FAST_TRUNK_GROUPm_field32_get(unit, 4157 &tg_entry, _xgs_fast_modulef[i]); 4158 egr_hw_ports[i] = soc_FAST_TRUNK_GROUPm_field32_get(unit, 4159 &tg_entry, _xgs_fast_portf[i]); 4160 } else { 4161 egr_hw_mods[i] = soc_TRUNK_GROUPm_field32_get(unit, 4162 &tg_entry, _xgs_modulef[i]); 4163 egr_hw_ports[i] = soc_TRUNK_GROUPm_field32_get(unit, 4164 &tg_entry, _xgs_portf[i]); 4165 } 4166 for (j = 0; j < num_mod; j++) { 4167 if (om[j] == egr_hw_mods[i]) { 4168 SOC_PBMP_PORT_ADD(op[j], egr_hw_ports[i]); 4169 found = 1; 4170 break; 4171 } 4172 } 4173 if (!found) { 4174 SOC_PBMP_PORT_ADD(op[num_mod], egr_hw_ports[i]); 4175 om[num_mod++] = egr_hw_mods[i]; 4176 } 4177 } 4178 4179 num_egr_ports = 0; 4180 for (i = 0; i < num_mod; i++) { 4181 int pbmp_count; 4182 SOC_PBMP_COUNT(op[i], pbmp_count); 4183 num_egr_ports += pbmp_count; 4184 } 4185 4186 for (i = 0; i < num_egr_ports; i++) { 4187 /* Compare values with source trunk map to recreate 4188 * ingress disable flag 4189 */ 4190 #ifdef BCM_TRX_SUPPORT 4191 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 4192 idx = (egr_hw_mods[i] * (SOC_PORT_ADDR_MAX(unit) + 1)) + 4193 egr_hw_ports[i]; 4194 } else 4195 #endif 4196 { 4197 idx = (egr_hw_mods[i] << SOC_TRUNK_BIT_POS(unit)) + 4198 egr_hw_ports[i]; 4199 } 4200 4201 rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, 4202 MEM_BLOCK_ANY, idx, &stm); 4203 if (BCM_SUCCESS(rv)) { 4204 ptype = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 4205 &stm, PORT_TYPEf); 4206 tid_get = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 4207 &stm, tid_fld); 4208 if (ptype != 1 || tid_get != tid) { 4209 egr_member_flags[i] |= 4210 BCM_TRUNK_MEMBER_INGRESS_DISABLE; 4211 } 4212 } 4213 } 4214 4215 MEMBER_INFO(unit, tid).num_ports = num_egr_ports; 4216 for (i = 0; i < num_egr_ports; i++) { 4217 MEMBER_INFO(unit, tid).modport[i] = 4218 (egr_hw_mods[i] << 8) | egr_hw_ports[i]; 4219 MEMBER_INFO(unit, tid).member_flags[i] = 4220 egr_member_flags[i]; 4221 } 4222 } 4223 4224 if (soc_feature(unit, soc_feature_fastlag)) { 4225 psc = soc_FAST_TRUNK_GROUPm_field32_get(unit, &tg_entry, 4226 RTAGf); 4227 } else { 4228 psc = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 4229 RTAGf); 4230 } 4231 if (psc <= 0) { 4232 psc = BCM_TRUNK_PSC_DEFAULT; 4233 } 4234 4235 /* 4236 * Update trunk control state 4237 */ 4238 TRUNK_LOCK(unit); 4239 t_info = trunk_info; 4240 t_info->tid = tid; 4241 t_info->in_use = TRUE; 4242 t_info->psc = psc; 4243 _bcm_xgs3_trunk_rtag_to_psc(unit, psc, &(t_info->psc)); 4244 4245 /* Recover software trunk failover internal state */ 4246 rv = _bcm_xgs3_trunk_swfailover_set(unit, 4247 tid, 4248 psc, 4249 num_egr_ports, 4250 egr_hw_mods, 4251 egr_hw_ports, 4252 egr_member_flags); 4253 4254 /* Recover hardware trunk failover internal state */ 4255 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 4256 if (BCM_SUCCESS(rv) && 4257 soc_feature(unit, soc_feature_port_lag_failover)) { 4258 /* Record trunk info for HW failover */ 4259 hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[tid]); 4260 hwft->num_ports = num_egr_ports; 4261 for (tix = 0; tix < num_egr_ports; tix++) { 4262 hwft->modport[tix] = 4263 (egr_hw_mods[tix] << 8) | egr_hw_ports[tix]; 4264 rv = _bcm_xgs3_trunk_hwfailover_read(unit, 4265 egr_hw_ports[tix], 4266 0, &rtag, 4267 NULL, NULL, NULL); 4268 4269 if (BCM_SUCCESS(rv)) { 4270 psc_local = BCM_TRUNK_PSC_DEFAULT; 4271 _bcm_xgs3_trunk_rtag_to_psc(unit, rtag, 4272 &psc_local); 4273 hwft->psc[tix] = psc_local; 4274 /* Flags already handled */ 4275 } else { 4276 /* Propagate error */ 4277 break; 4278 } 4279 } 4280 } 4281 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 4282 4283 TRUNK_UNLOCK(unit); 4284 } /* for each tid */ 4285 4286 /* Recover source mod port trunk cache and trunk members with 4287 * egress disable flag set. 4288 */ 4289 /* 4290 * For source module ID base indexing supported, 4291 * _bcm_xgs3_trunk_mod_port_map_reinit is called during stacking 4292 * module reinit, since the number of ports in a given module is not known until then. 4293 */ 4294 if (BCM_SUCCESS(rv) && !soc_feature(unit, soc_feature_src_modid_base_index)) { 4295 rv = _xgs3_trunk_mod_port_map_reinit(unit); 4296 } 4297 4298 } 4299 #endif /* BCM_FIREBOLT_SUPPORT */ 4300 4301 return rv; 4302 } 4303 4304 /* 4305 * Handles state recovery for fabric trunks 4306 */ 4307 int 4308 _xgs3_trunk_fabric_reinit(int unit, int min_tid, int max_tid, 4309 trunk_private_t *trunk_info) 4310 { 4311 int rv = BCM_E_NONE; 4312 uint32 hg_cntl_entry; 4313 uint32 hg_group_entry; 4314 pbmp_t hg_pbmp, pbmp; 4315 uint32 higig_bitmap; 4316 bcm_trunk_t tid, hgtid; 4317 trunk_private_t *t_info; 4318 bcm_port_t tp[BCM_XGS3_TRUNK_MAX_PORTCNT] = {0}; 4319 int num_ports; 4320 int psc = 0; 4321 bcm_port_t port; 4322 int i=0; 4323 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 4324 uint64 hg_trunk_group, hg_trunk_group_hi; 4325 _xgs3_hw_tinfo_t *hwft; 4326 int tix, rtag; 4327 #endif 4328 4329 for (tid = min_tid; tid <= max_tid; tid++, trunk_info++) { 4330 4331 hgtid = tid - min_tid; 4332 SOC_PBMP_CLEAR(hg_pbmp); 4333 if (SOC_IS_FB_FX_HX(unit)) { 4334 SOC_IF_ERROR_RETURN 4335 (READ_HIGIG_TRUNK_CONTROLr(unit, &hg_cntl_entry)); 4336 SOC_PBMP_WORD_SET(hg_pbmp, 4337 0, 4338 soc_reg_field_get(unit, 4339 HIGIG_TRUNK_CONTROLr, 4340 hg_cntl_entry, 4341 (tid == min_tid) ? 4342 HIGIG_TRUNK_BITMAP0f : 4343 HIGIG_TRUNK_BITMAP1f)); 4344 } 4345 #if defined(BCM_TRIUMPH2_SUPPORT) 4346 else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 4347 SOC_IS_VALKYRIE2(unit)) { 4348 uint64 val64; 4349 /* Triumph2 / Apollo / Valkyrie2 */ 4350 SOC_IF_ERROR_RETURN 4351 (READ_HG_TRUNK_BITMAP_64r(unit, hgtid, &val64)); 4352 SOC_PBMP_CLEAR(hg_pbmp); 4353 SOC_PBMP_WORD_SET(hg_pbmp, 0, 4354 soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r, 4355 val64, HIGIG_TRUNK_BITMAP_LOf)); 4356 SOC_PBMP_WORD_SET(hg_pbmp, 1, 4357 soc_reg64_field32_get(unit, HG_TRUNK_BITMAP_64r, 4358 val64, HIGIG_TRUNK_BITMAP_HIf)); 4359 } 4360 #endif 4361 #if defined(BCM_GREYHOUND2_SUPPORT) 4362 else if (soc_feature(unit, soc_feature_high_portcount_register)) { 4363 uint64 val64, hg_trunk_bmap_f; 4364 4365 SOC_IF_ERROR_RETURN 4366 (READ_HG_TRUNK_BITMAP_LOr(unit, hgtid, &val64)); 4367 hg_trunk_bmap_f = 4368 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_LOr, 4369 val64, HIGIG_TRUNK_BITMAPf); 4370 SOC_PBMP_CLEAR(hg_pbmp); 4371 SOC_PBMP_WORD_SET(hg_pbmp, 0, COMPILER_64_LO(hg_trunk_bmap_f)); 4372 SOC_PBMP_WORD_SET(hg_pbmp, 1, COMPILER_64_HI(hg_trunk_bmap_f)); 4373 4374 SOC_IF_ERROR_RETURN 4375 (READ_HG_TRUNK_BITMAP_HIr(unit, hgtid, &val64)); 4376 hg_trunk_bmap_f = 4377 soc_reg64_field_get(unit, HG_TRUNK_BITMAP_HIr, 4378 val64, HIGIG_TRUNK_BITMAPf); 4379 SOC_PBMP_WORD_SET(hg_pbmp, 2, COMPILER_64_LO(hg_trunk_bmap_f)); 4380 } 4381 #endif /* BCM_GREYHOUND2_SUPPORT */ 4382 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 4383 else if (SOC_IS_HBX(unit) || SOC_IS_TRX(unit)) { 4384 /* Humv / Bradley / Scorpion / Conqueror / Triumph / Valkyrie */ 4385 SOC_IF_ERROR_RETURN 4386 (READ_HG_TRUNK_BITMAPr(unit, hgtid, &hg_cntl_entry)); 4387 SOC_PBMP_WORD_SET(hg_pbmp, 4388 0, 4389 soc_reg_field_get(unit, 4390 HG_TRUNK_BITMAPr, 4391 hg_cntl_entry, 4392 HIGIG_TRUNK_BITMAPf)); 4393 } 4394 #endif 4395 4396 SOC_PBMP_CLEAR(pbmp); 4397 if (SOC_IS_RAVEN(unit) || SOC_IS_TRIUMPH2(unit) || 4398 SOC_IS_APOLLO(unit) || SOC_IS_VALKYRIE2(unit) || 4399 soc_feature(unit, soc_feature_high_portcount_register)) { 4400 /* Use the bitmap directly for Raven from HIGIG_TRUNK_CONTROL */ 4401 SOC_PBMP_ASSIGN(pbmp, hg_pbmp); 4402 } else { 4403 /* For other FBX, map the read higig bitmap to the physical bitmap */ 4404 soc_xgs3_higig_bitmap_to_bitmap(unit, hg_pbmp, &pbmp); 4405 } 4406 4407 num_ports = 0; 4408 if (SOC_IS_FB_FX_HX(unit)) { 4409 PBMP_ITER(pbmp, port) { 4410 BCM_IF_ERROR_RETURN 4411 (soc_xgs3_port_to_higig_bitmap(unit, port, &higig_bitmap)); 4412 BCM_IF_ERROR_RETURN 4413 (soc_xgs3_higig_bitmap_to_higig_port_num(higig_bitmap, 4414 (uint32 *)&(tp[num_ports]))); 4415 num_ports += 1; 4416 } 4417 } 4418 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 4419 else if (SOC_IS_HBX(unit) || SOC_IS_TRX(unit)) { 4420 int port_limit; 4421 COMPILER_64_ZERO(hg_trunk_group); 4422 COMPILER_64_ZERO(hg_trunk_group_hi); 4423 4424 COMPILER_REFERENCE(hg_trunk_group_hi); 4425 4426 if (SOC_PBMP_NOT_NULL(pbmp)) { 4427 SOC_IF_ERROR_RETURN 4428 (READ_HG_TRUNK_GROUPr(unit, hgtid, &hg_trunk_group)); 4429 if (SOC_REG_FIELD_VALID(unit, 4430 HG_TRUNK_GROUPr, HIGIG_TRUNK_SIZEf)) { /* PR 34459 */ 4431 i = soc_reg64_field32_get(unit, HG_TRUNK_GROUPr, 4432 hg_trunk_group, 4433 HIGIG_TRUNK_SIZEf); 4434 num_ports = i + 1; 4435 } else { 4436 BCM_PBMP_COUNT(pbmp, num_ports); 4437 } 4438 port_limit = num_ports; 4439 #if defined(BCM_SCORPION_SUPPORT) 4440 if (SOC_IS_SC_CQ(unit) && 4441 (port_limit > BCM_SWITCH_TRUNK_MAX_PORTCNT)) { 4442 port_limit = BCM_SWITCH_TRUNK_MAX_PORTCNT; 4443 } 4444 #endif 4445 for (i = 0; i < port_limit; i++) { 4446 tp[i] = 4447 soc_reg64_field32_get(unit, HG_TRUNK_GROUPr, 4448 hg_trunk_group, _hg_trunk[i]); 4449 } 4450 #if defined(BCM_SCORPION_SUPPORT) 4451 if (SOC_IS_SC_CQ(unit) && 4452 (num_ports > BCM_SWITCH_TRUNK_MAX_PORTCNT)) { 4453 SOC_IF_ERROR_RETURN 4454 (READ_HG_TRUNK_GROUP_HIr(unit, hgtid, 4455 &hg_trunk_group_hi)); 4456 for (i = BCM_SWITCH_TRUNK_MAX_PORTCNT; 4457 i < num_ports; i++) { 4458 tp[i] = 4459 soc_reg64_field32_get(unit, HG_TRUNK_GROUP_HIr, 4460 hg_trunk_group_hi, 4461 _hg_trunk_hi[i - BCM_SWITCH_TRUNK_MAX_PORTCNT]); 4462 } 4463 } 4464 #endif 4465 } 4466 } 4467 #endif 4468 4469 /* Recover trunk member info internal state */ 4470 for (i = 0; i < num_ports; i++) { 4471 MEMBER_INFO(unit, (hgtid + _BCM_FP_TRUNK_NUM_MAX)).modport[i] = tp[i]; 4472 } 4473 MEMBER_INFO(unit, (hgtid + _BCM_FP_TRUNK_NUM_MAX)).num_ports = num_ports; 4474 4475 if (num_ports == 0) { 4476 continue; 4477 } 4478 4479 if (SOC_IS_FB_FX_HX(unit)) { 4480 SOC_IF_ERROR_RETURN 4481 (READ_HIGIG_TRUNK_GROUPr(unit, &hg_group_entry)); 4482 4483 psc = soc_reg_field_get(unit, 4484 HIGIG_TRUNK_GROUPr, 4485 hg_group_entry, 4486 (tid == min_tid) ? \ 4487 HIGIG_TRUNK_RTAG0f : \ 4488 HIGIG_TRUNK_RTAG1f); 4489 } 4490 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT) 4491 else { 4492 /* Humv / Bradley / Scorpion / Conqueror / Triumph / Valkyrie */ 4493 psc = soc_reg64_field32_get(unit, 4494 HG_TRUNK_GROUPr, 4495 hg_trunk_group, 4496 HIGIG_TRUNK_RTAGf); 4497 } 4498 #endif 4499 /* 4500 * Update trunk control state 4501 */ 4502 TRUNK_LOCK(unit); 4503 t_info = trunk_info; 4504 t_info->tid = tid; 4505 t_info->psc = psc; 4506 t_info->in_use = TRUE; 4507 rv = _bcm_xgs3_trunk_swfailover_fabric_set(unit, hgtid, 4508 psc, pbmp); 4509 TRUNK_UNLOCK(unit); 4510 4511 if (BCM_FAILURE(rv)) { 4512 break; 4513 } 4514 4515 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 4516 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 4517 /* Record trunk info for HW failover */ 4518 hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[hgtid + 4519 _BCM_FP_TRUNK_NUM_MAX]); 4520 hwft->num_ports = num_ports; 4521 for (tix = 0; tix < num_ports; tix++) { 4522 hwft->modport[tix] = tp[tix]; 4523 rv = _bcm_xgs3_trunk_hwfailover_hg_read(unit, 4524 tp[tix], 4525 0, &rtag, NULL, NULL, NULL); 4526 4527 if (BCM_SUCCESS(rv)) { 4528 TRUNK_LOCK(unit); 4529 if (7 == rtag) { 4530 if (soc_feature(unit, soc_feature_port_flow_hash)) { 4531 hwft->psc[tix] = BCM_TRUNK_PSC_PORTFLOW; 4532 } else if (soc_feature(unit, 4533 soc_feature_port_trunk_index)) { 4534 hwft->psc[tix] = BCM_TRUNK_PSC_PORTINDEX; 4535 } /* Else, unknown */ 4536 } else if (0 != rtag) { 4537 /* HW and SW values match */ 4538 hwft->psc[tix] = rtag; 4539 } else { 4540 /* Use trunk group value as the default */ 4541 hwft->psc[tix] = psc; 4542 } 4543 /* Flags already handled */ 4544 TRUNK_UNLOCK(unit); 4545 } 4546 } 4547 } 4548 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 4549 } 4550 4551 return rv; 4552 } 4553 4554 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 4555 void 4556 _bcm_xgs3_hw_failover_flags_set(int unit, bcm_trunk_t tid, 4557 int port_index, int hg_trunk, uint8 flags) 4558 { 4559 int tid_ix; 4560 4561 tid_ix = tid + (hg_trunk ? _BCM_FP_TRUNK_NUM_MAX : 0); 4562 4563 TRUNK_LOCK(unit); 4564 _xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix].flags[port_index] = flags; 4565 TRUNK_UNLOCK(unit); 4566 4567 return; 4568 } 4569 4570 uint8 4571 _bcm_xgs3_hw_failover_flags_get(int unit, bcm_trunk_t tid, 4572 int port_index, int hg_trunk) 4573 { 4574 int tid_ix; 4575 uint8 flags; 4576 4577 tid_ix = tid + (hg_trunk ? _BCM_FP_TRUNK_NUM_MAX : 0); 4578 4579 TRUNK_LOCK(unit); 4580 flags = _xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix].flags[port_index]; 4581 TRUNK_UNLOCK(unit); 4582 4583 return flags; 4584 } 4585 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 4586 4587 void 4588 _bcm_xgs3_trunk_member_info_set(int unit, bcm_trunk_t tid, 4589 uint8 num_ports, 4590 uint16 modport[BCM_XGS3_TRUNK_MAX_PORTCNT], 4591 uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT]) 4592 { 4593 int i; 4594 4595 MEMBER_INFO(unit, tid).num_ports = num_ports; 4596 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 4597 MEMBER_INFO(unit, tid).modport[i] = modport[i]; 4598 MEMBER_INFO(unit, tid).member_flags[i] = member_flags[i]; 4599 } 4600 MEMBER_INFO(unit, tid).recovered_from_scache = 1; 4601 4602 return; 4603 } 4604 4605 void 4606 _bcm_xgs3_trunk_member_info_get(int unit, bcm_trunk_t tid, 4607 uint8 *num_ports, 4608 uint16 modport[BCM_XGS3_TRUNK_MAX_PORTCNT], 4609 uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT]) 4610 { 4611 int i; 4612 4613 *num_ports = MEMBER_INFO(unit, tid).num_ports; 4614 for (i = 0; i < BCM_XGS3_TRUNK_MAX_PORTCNT; i++) { 4615 modport[i] = MEMBER_INFO(unit, tid).modport[i]; 4616 member_flags[i] = MEMBER_INFO(unit, tid).member_flags[i]; 4617 } 4618 4619 return; 4620 } 4621 #endif /* BCM_WARM_BOOT_SUPPORT */ 4622 4623 #ifndef BCM_SW_STATE_DUMP_DISABLE 4624 /* 4625 * Function: 4626 * _bcm_xgs3_trunk_sw_dump 4627 * Purpose: 4628 * Displays trunk information maintained by software. 4629 * Parameters: 4630 * unit - Device unit number 4631 * tid - Trunk id 4632 * Returns: 4633 * None 4634 */ 4635 void 4636 _bcm_xgs3_trunk_sw_dump(int unit) 4637 { 4638 int rv, i, j, tid_ix, tid_min = -1, tid_max; 4639 bcm_trunk_chip_info_t chip_info; 4640 _xgs3_trunk_swfail_t *swf; 4641 _xgs3_tinfo_t *swft; 4642 4643 swf = _xgs3_trunk_swfail[unit]; 4644 4645 rv = bcm_esw_trunk_chip_info_get(unit, &chip_info); 4646 if (BCM_FAILURE(rv)) { 4647 LOG_CLI((BSL_META_U(unit, 4648 "Unable to retrieve unit %d chip info %d\n"), 4649 unit, rv)); 4650 } 4651 4652 if (chip_info.trunk_id_min < 0) { 4653 if (chip_info.trunk_fabric_id_min < 0) { 4654 /* No trunks! Abort */ 4655 LOG_CLI((BSL_META_U(unit, 4656 "No trunk groups on unit %d\n"), unit)); 4657 return; 4658 } else { 4659 tid_min = chip_info.trunk_fabric_id_min; 4660 tid_max = chip_info.trunk_fabric_id_max; 4661 } 4662 } else { 4663 tid_min = chip_info.trunk_id_min; 4664 if (chip_info.trunk_fabric_id_min < 0) { 4665 tid_max = chip_info.trunk_id_max; 4666 } else { 4667 tid_max = chip_info.trunk_fabric_id_max; 4668 } 4669 } 4670 4671 if (NULL != swf) { 4672 LOG_CLI((BSL_META_U(unit, 4673 "Software failover parameters:\n"))); 4674 LOG_CLI((BSL_META_U(unit, 4675 " Local modid: %d\n"), swf->mymodid)); 4676 LOG_CLI((BSL_META_U(unit, 4677 " Port: Trunk\n"))); 4678 for (j = 0; j < SOC_MAX_NUM_PORTS; j++) { 4679 if (0 != swf->trunk[j]) { 4680 LOG_CLI((BSL_META_U(unit, 4681 " %d: %d\n"), 4682 j, swf->trunk[j])); 4683 } 4684 } 4685 LOG_CLI((BSL_META_U(unit, 4686 " Trunk SW failover parameters\n"))); 4687 for (i = tid_min; i <= tid_max; i++) { 4688 if (i >= chip_info.trunk_fabric_id_min) { 4689 tid_ix = (i - chip_info.trunk_fabric_id_min) + 4690 _BCM_FP_TRUNK_NUM_MAX; 4691 } else { 4692 tid_ix = i; 4693 } 4694 4695 swft = &swf->tinfo[tid_ix]; 4696 if (0 != swft->num_ports) { 4697 LOG_CLI((BSL_META_U(unit, 4698 " Trunk %d, index %d\n"), i, tid_ix)); 4699 LOG_CLI((BSL_META_U(unit, 4700 " RTAG value %d\n"), swft->rtag)); 4701 LOG_CLI((BSL_META_U(unit, 4702 " Port count %d\n"), swft->num_ports)); 4703 for (j = 0; j < swft->num_ports; j++) { 4704 LOG_CLI((BSL_META_U(unit, 4705 " ModPort 0x%04x\n"), swft->modport[j])); 4706 } 4707 } 4708 } 4709 } else { 4710 LOG_CLI((BSL_META_U(unit, 4711 "SW trunk failover not initialized on unit %d\n"), 4712 unit)); 4713 } 4714 4715 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 4716 if (soc_feature(unit, soc_feature_port_lag_failover) || 4717 soc_feature(unit, soc_feature_hg_trunk_failover)) { 4718 _xgs3_hw_tinfo_t *hwft; 4719 4720 if (NULL == _xgs3_trunk_hwfail[unit]) { 4721 LOG_CLI((BSL_META_U(unit, 4722 "HW trunk failover not initialized on unit %d\n"), 4723 unit)); 4724 return; 4725 } 4726 4727 LOG_CLI((BSL_META_U(unit, 4728 " Trunk HW failover parameters\n"))); 4729 for (i = tid_min; i <= tid_max; i++) { 4730 if (i >= chip_info.trunk_fabric_id_min) { 4731 tid_ix = (i - chip_info.trunk_fabric_id_min) + 4732 _BCM_FP_TRUNK_NUM_MAX; 4733 } else { 4734 tid_ix = i; 4735 } 4736 4737 hwft = &(_xgs3_trunk_hwfail[unit]->hw_tinfo[tid_ix]); 4738 if (0 != hwft->num_ports) { 4739 LOG_CLI((BSL_META_U(unit, 4740 " Trunk %d, index %d\n"), i, tid_ix)); 4741 LOG_CLI((BSL_META_U(unit, 4742 " Port count %d\n"), hwft->num_ports)); 4743 for (j = 0; j < hwft->num_ports; j++) { 4744 LOG_CLI((BSL_META_U(unit, 4745 " PSC value %d\n"), hwft->psc[j])); 4746 LOG_CLI((BSL_META_U(unit, 4747 " Flags 0x%08x\n"), hwft->flags[j])); 4748 LOG_CLI((BSL_META_U(unit, 4749 " ModPort 0x%04x\n"), hwft->modport[j])); 4750 } 4751 } 4752 } 4753 } 4754 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 4755 4756 if (NULL != _xgs3_trunk_member_info[unit]) { 4757 LOG_CLI((BSL_META_U(unit, 4758 "Trunk membership info:\n"))); 4759 for (i = tid_min; i <= tid_max; i++) { 4760 if (i >= chip_info.trunk_fabric_id_min) { 4761 tid_ix = (i - chip_info.trunk_fabric_id_min) + 4762 _BCM_FP_TRUNK_NUM_MAX; 4763 } else { 4764 tid_ix = i; 4765 } 4766 4767 if (0 != MEMBER_INFO(unit, tid_ix).num_ports) { 4768 LOG_CLI((BSL_META_U(unit, 4769 " Trunk %d, index %d\n"), i, tid_ix)); 4770 LOG_CLI((BSL_META_U(unit, 4771 " Port count %d\n"), 4772 MEMBER_INFO(unit, tid_ix).num_ports)); 4773 for (j = 0; j < MEMBER_INFO(unit, tid_ix).num_ports; j++) { 4774 LOG_CLI((BSL_META_U(unit, 4775 " ModPort 0x%04x\n"), 4776 MEMBER_INFO(unit, tid_ix).modport[j])); 4777 LOG_CLI((BSL_META_U(unit, 4778 " Member flags 0x%x\n"), 4779 MEMBER_INFO(unit, tid_ix).member_flags[j])); 4780 } 4781 } 4782 } 4783 } else { 4784 LOG_CLI((BSL_META_U(unit, 4785 "Trunk membership info not initialized on unit %d\n"), 4786 unit)); 4787 } 4788 4789 return; 4790 } 4791 #endif /* BCM_SW_STATE_DUMP_DISABLE */