trunk.c (286552B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: trunk.c 8 * Purpose: BCM level APIs for trunking (a.k.a. Port Aggregation) 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/drv.h> 14 #include <soc/scache.h> 15 #if defined(BCM_BRADLEY_SUPPORT) 16 #include <soc/bradley.h> 17 #include <soc/firebolt.h> 18 #endif /* BCM_BRADLEY_SUPPORT */ 19 20 #include <bcm/error.h> 21 #include <bcm/mirror.h> 22 #include <bcm/trunk.h> 23 24 #include <bcm_int/api_xlate_port.h> 25 #include <bcm_int/common/lock.h> 26 #include <bcm_int/common/multicast.h> 27 #include <bcm_int/esw/mbcm.h> 28 #include <bcm_int/esw/trunk.h> 29 #include <bcm_int/esw/port.h> 30 #include <bcm_int/esw/mirror.h> 31 #include <bcm_int/esw/firebolt.h> 32 #include <bcm_int/esw/stack.h> 33 #include <bcm_int/esw/switch.h> 34 #include <bcm_int/esw/trident.h> 35 #include <bcm_int/esw/trident2.h> 36 #ifdef BCM_KATANA2_SUPPORT 37 #include <bcm_int/esw/katana2.h> 38 #endif /* BCM_KATANA2_SUPPORT */ 39 #ifdef BCM_TOMAHAWK3_SUPPORT 40 #include <soc/tomahawk3.h> 41 #endif /* BCM_TOMAHAWK3_SUPPORT */ 42 #ifdef BCM_HGPROXY_COE_SUPPORT 43 #include <bcm_int/esw/xgs5.h> 44 #endif /* BCM_HGPROXY_COE_SUPPORT */ 45 #if defined(BCM_SABER2_SUPPORT) 46 #include <soc/saber2.h> 47 #endif /* BCM_SABER2_SUPPORT */ 48 49 #include <bcm_int/esw_dispatch.h> 50 #include <bcm_int/esw/switch.h> 51 52 #ifdef BCM_WARM_BOOT_SUPPORT 53 #include <bcm/types.h> 54 #endif /* BCM_WARM_BOOT_SUPPORT */ 55 56 57 typedef struct trunk_cntl_s { 58 int ngroups_fp; /* number of (front panel) trunk groups */ 59 int nports_fp; /* max ports per trunk group */ 60 int ngroups_hg; /* number of fabric trunk groups */ 61 int nports_hg; /* max ports per fabric trunk group */ 62 #ifdef BCM_APACHE_SUPPORT 63 int ngroups_rr_fp; /* number of fp trunks supporting Round Robin Load balancing */ 64 SHR_BITDCL *fp_rr_lag_bmp; /* FP RoundRobin Lag usage bitmap */ 65 #endif /* BCM_APACHE_SUPPORT */ 66 trunk_private_t *t_info; 67 sal_mutex_t lock; /* Trunk module lock. */ 68 #ifdef BCM_WARM_BOOT_SUPPORT 69 SHR_BITDCL *trunk_bmp_ptr; /* Warm Boot trunk use bitmap */ 70 int trunk_bmp_alloc; /* WB trunk use allocation */ 71 uint8 *fp_hwf_flags; /* WB FP - HW failover flags record */ 72 int fp_hwf_alloc; /* WB FP - HW failover allocation */ 73 uint8 *hg_hwf_flags; /* WB HG - HW failover flags record */ 74 int hg_hwf_alloc; /* WB HG - HW failover allocation */ 75 #endif /* BCM_WARM_BOOT_SUPPORT */ 76 } trunk_cntl_t; 77 78 /* 79 * One trunk control entry for each SOC device containing trunk book keeping 80 * info for that device. 81 */ 82 static trunk_cntl_t bcm_trunk_control[BCM_MAX_NUM_UNITS]; 83 84 #define TRUNK_CNTL(unit) bcm_trunk_control[unit] 85 #define TRUNK_INFO(unit, tid) bcm_trunk_control[unit].t_info[tid] 86 87 /* 88 * Cause a routine to return BCM_E_INIT if trunking subsystem is not 89 * initialized. 90 */ 91 92 #define TRUNK_INIT(unit) \ 93 if ( (TRUNK_CNTL(unit).ngroups_fp <= 0) && \ 94 (TRUNK_CNTL(unit).ngroups_hg <= 0) ) { return BCM_E_INIT; } 95 96 #define TRUNK_NUM_GROUPS(unit) \ 97 (TRUNK_CNTL(unit).ngroups_fp + TRUNK_CNTL(unit).ngroups_hg) 98 99 /* 100 * Make sure TID is within valid range. 101 */ 102 103 #define TRUNK_CHECK(unit, tid) \ 104 if ((tid) < 0 || (tid) >= TRUNK_NUM_GROUPS(unit)) \ 105 { return BCM_E_PARAM; } 106 107 #define TRUNK_FP_TID(unit, tid) \ 108 ( ((tid) >= 0) && ((tid) < TRUNK_CNTL(unit).ngroups_fp) ) 109 110 #define TRUNK_FABRIC_TID(unit, tid) \ 111 ( ((tid) >= TRUNK_CNTL(unit).ngroups_fp) && \ 112 ((tid) < TRUNK_NUM_GROUPS(unit)) ) 113 114 /* 115 * Function: 116 * _bcm_esw_trunk_gport_construct 117 * Purpose: 118 * Converts ports and modules given in t_data structure into gports 119 * Parameters: 120 * unit - StrataSwitch PCI device unit number (driver internal). 121 * fabric_trunk - trunk is a fabric trunk 122 * count - number of failover gports in list 123 * port_list - (IN) list of port numbers 124 * modid_list - (IN) list of module ids 125 * port_array - (OUT) list of gports to return 126 * 127 * Note: 128 * port_list and port_array may be the same list. This updates 129 * the list in place. 130 */ 131 int 132 _bcm_esw_trunk_gport_construct(int unit, int fabric_trunk, int count, 133 bcm_port_t *port_list, 134 bcm_module_t *modid_list, 135 bcm_gport_t *port_array) 136 { 137 bcm_gport_t gport; 138 int i, mod_is_local; 139 _bcm_gport_dest_t dest; 140 bcm_module_t base_modid; 141 bcm_port_t local_port; 142 #if defined(BCM_KATANA2_SUPPORT) 143 int local_subport = 0, pp_port = 0; 144 #endif 145 146 _bcm_gport_dest_t_init(&dest); 147 148 for (i = 0; i < count; i++) { 149 gport = 0; 150 /* Stacking ports should be encoded as devport */ 151 if (fabric_trunk) { 152 /* Error checking during set functions should guarantee that 153 * stack ports iff fabric trunks */ 154 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 155 BCM_IF_ERROR_RETURN 156 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, modid_list[i], 157 port_list[i], &dest.modid, &dest.port)); 158 BCM_IF_ERROR_RETURN( 159 _bcm_esw_gport_construct(unit, &dest, &gport)); 160 } else { 161 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 162 dest.modid = modid_list[i]; 163 dest.port = port_list[i]; 164 #if defined(BCM_KATANA2_SUPPORT) 165 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_is_local_coe_subport(unit, 166 dest.modid, dest.port, &local_subport)); 167 if (local_subport) { 168 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, 169 dest.modid, dest.port, &pp_port)); 170 171 /* construct LinkPHY/SubportPkttag subport gport */ 172 _BCM_KT2_SUBPORT_PORT_ID_SET(gport, pp_port); 173 if (BCM_PBMP_MEMBER( 174 SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) { 175 _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, 176 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 177 } else if (BCM_PBMP_MEMBER( 178 SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) { 179 _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, 180 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 181 } else { 182 return BCM_E_PARAM; 183 } 184 } else 185 #endif 186 { 187 #ifdef BCM_HGPROXY_COE_SUPPORT 188 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 189 _bcm_xgs5_subport_coe_mod_port_local( 190 unit, dest.modid, dest.port)) { 191 } else 192 #endif 193 { 194 BCM_IF_ERROR_RETURN 195 (_bcm_esw_modid_is_local(unit, modid_list[i], 196 &mod_is_local)); 197 if (mod_is_local) { 198 BCM_IF_ERROR_RETURN 199 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 200 modid_list[i], port_list[i], 201 &base_modid, &local_port)); 202 if (IS_ST_PORT(unit, local_port)) { 203 dest.gport_type = _SHR_GPORT_TYPE_DEVPORT; 204 dest.modid = base_modid; 205 dest.port = local_port; 206 } 207 } 208 } 209 BCM_IF_ERROR_RETURN( 210 _bcm_esw_gport_construct(unit, &dest, &gport)); 211 } 212 } 213 port_array[i] = gport; 214 } 215 216 return BCM_E_NONE; 217 } 218 219 /* 220 * Function: 221 * _bcm_esw_trunk_gport_array_resolve 222 * Purpose: 223 * Converts gports list into ports and modules 224 * Parameters: 225 * unit - StrataSwitch PCI device unit number (driver internal). 226 * fabric_trunk - trunk is a fabric trunk 227 * count - number of failover gports in list 228 * port_array - (IN) list of gports 229 * port_list - (OUT) list of port numbers to return 230 * modid_list - (OUT) list of module ids to return 231 * 232 * Note: 233 * port_list and port_array may be the same list. This updates 234 * the list in place. 235 */ 236 int 237 _bcm_esw_trunk_gport_array_resolve(int unit, int fabric_trunk, int count, 238 bcm_gport_t *port_array, 239 bcm_port_t *port_list, 240 bcm_module_t *modid_list) 241 242 { 243 bcm_port_t port; 244 bcm_module_t modid, local_modid; 245 bcm_trunk_t tgid; 246 int i, id, rv; 247 248 rv = bcm_esw_stk_my_modid_get(unit, &local_modid); 249 if (BCM_FAILURE(rv) && !SOC_IS_XGS_FABRIC(unit) ) { 250 return (rv); 251 } 252 253 for (i = 0; i < count; i++) { 254 if (BCM_GPORT_IS_SET(port_array[i])) { 255 if (fabric_trunk) { 256 /* Must be local */ 257 BCM_IF_ERROR_RETURN 258 (bcm_esw_port_local_get(unit, port_array[i], &port)); 259 #if defined(BCM_HGPROXY_COE_SUPPORT) 260 /*Cascaded port*/ 261 if (IS_SUBTAG_PORT(unit, port) 262 && soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 263 BCM_IF_ERROR_RETURN 264 (_bcm_esw_gport_resolve(unit, port_array[i], 265 &modid, &port, &tgid, &id)); 266 port_list[i] = port; 267 modid_list[i] = modid; 268 } else 269 #endif 270 { 271 port_list[i] = port; 272 modid_list[i] = -1; 273 } 274 } else { 275 BCM_IF_ERROR_RETURN 276 (_bcm_esw_gport_resolve(unit, port_array[i], 277 &modid, &port, &tgid, &id)); 278 279 #if defined(BCM_HGPROXY_COE_SUPPORT) 280 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 281 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port_array[i])) { 282 id = -1; 283 } else 284 #endif 285 286 #if defined(BCM_KATANA2_SUPPORT) 287 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, 288 port_array[i])) { 289 id = -1; 290 } 291 #endif 292 if ((-1 != tgid) || (-1 != id)) { 293 return BCM_E_PARAM; 294 } 295 port_list[i] = port; 296 modid_list[i] = modid; 297 } 298 } else { 299 if (fabric_trunk) { 300 if (SOC_PORT_VALID(unit, port_array[i])) { 301 port_list[i] = port_array[i]; 302 modid_list[i] = -1; 303 } else { 304 return BCM_E_PORT; 305 } 306 } else { 307 PORT_DUALMODID_VALID(unit, port_array[i]); 308 if (port_array != port_list) { 309 port_list[i] = port_array[i]; 310 modid_list[i] = local_modid; 311 } 312 } 313 } 314 } 315 316 return BCM_E_NONE; 317 } 318 319 /* 320 * Function: 321 * _bcm_esw_trunk_port_property_get 322 * Purpose: 323 * Determines whether a system port is part of a trunk 324 * Parameters: 325 * unit - StrataSwitch PCI device unit number (driver internal). 326 * modid - Module id. 327 * port - Port number. 328 * tid - (OUT) Trunk ID if trunk member. 329 * Notes: 330 * Currently used only by RX module, gport support not required. 331 */ 332 int 333 _bcm_esw_trunk_port_property_get(int unit, 334 bcm_module_t modid, 335 bcm_port_t port, 336 int *tid) 337 { 338 #if defined(BCM_TRIDENT_SUPPORT) 339 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 340 return _bcm_trident_trunk_get_port_property(unit, modid, port, tid); 341 } 342 #if defined(BCM_TOMAHAWK3_SUPPORT) 343 if (SOC_IS_TOMAHAWK3(unit)) { 344 return _bcm_th3_trunk_get_port_property(unit, port, tid); 345 } 346 #endif 347 #endif 348 #if defined(BCM_FIREBOLT_SUPPORT) 349 if (SOC_IS_XGS_SWITCH(unit)) { 350 return _bcm_xgs3_trunk_get_port_property(unit, modid, port, tid); 351 } 352 #endif 353 return BCM_E_UNAVAIL; 354 } 355 356 /* 357 * Function: 358 * _bcm_esw_trunk_active_member_get 359 * Purpose: 360 * Returns active port information for a given trunk. 361 * Returns only the members on which EGRESS_DISABLE is not set. 362 * Parameters: 363 * unit - StrataSwitch PCI device unit number (driver internal). 364 * tid - Trunk ID. 365 * trunk_info - (OUT) Place to store returned trunk info. 366 * member_max - (IN) Size of member_array. 367 * active_member_array - (OUT) Place to store returned active trunk 368 * members. 369 * active_member_count - (OUT) Place to store returned number of active 370 * trunk members. 371 * Returns: 372 * BCM_E_NONE Success. 373 * BCM_E_XXX 374 */ 375 int 376 _bcm_esw_trunk_active_member_get(int unit, bcm_trunk_t tid, 377 bcm_trunk_info_t *trunk_info, 378 int member_max, 379 bcm_trunk_member_t *active_member_array, 380 int *active_member_count) 381 { 382 int rv = BCM_E_NONE; 383 int member_count; 384 bcm_trunk_member_t member_array[BCM_SWITCH_TRUNK_MAX_PORTCNT]; 385 int filled_count = 0; 386 387 if ((member_max > 0) && (NULL == active_member_array)) { 388 return BCM_E_PARAM; 389 } 390 391 if ((member_max > 0) && (NULL == active_member_count)) { 392 return BCM_E_PARAM; 393 } 394 395 BCM_IF_ERROR_RETURN 396 (bcm_esw_trunk_get(unit, tid, NULL, BCM_SWITCH_TRUNK_MAX_PORTCNT, 397 member_array, &member_count)); 398 399 if (0 < member_count) { 400 int i; 401 if (active_member_array != NULL) { 402 sal_memset(active_member_array, 0, 403 sizeof(bcm_trunk_member_t) * member_max); 404 } 405 406 *active_member_count = 0; 407 408 /* Get only the active member ports */ 409 for (i = 0; i < member_count; i++) { 410 if (!(member_array[i].flags & BCM_TRUNK_MEMBER_EGRESS_DISABLE)) { 411 if ( (active_member_array != NULL) && (member_max > 0) ) { 412 sal_memcpy(&active_member_array[*active_member_count], 413 &member_array[i], sizeof(member_array[i])); 414 filled_count++; 415 } 416 (*active_member_count)++; 417 418 if ( (member_max > 0) && (filled_count == member_max) ) { 419 break; 420 } 421 } 422 } 423 } 424 425 return rv; 426 } 427 428 /* 429 * Function: 430 * _bcm_esw_trunk_rtag_get 431 * Purpose: 432 * Retrieve the RTAG HW value of a trunk 433 * Parameters: 434 * unit - StrataSwitch PCI device unit number (driver internal). 435 * tid - Trunk ID. 436 * rtag - (OUT) HW RTAG value for trunk. 437 * Notes: 438 * Currently used by mirror module 439 */ 440 int 441 _bcm_esw_trunk_rtag_get(int unit, bcm_trunk_t tid, int *rtag) 442 443 { 444 trunk_private_t *t_info; 445 446 if (NULL == rtag) { 447 return BCM_E_PARAM; 448 } 449 450 TRUNK_CHECK(unit, tid); 451 452 t_info = &TRUNK_INFO(unit, tid); 453 454 if (t_info->tid == BCM_TRUNK_INVALID) { 455 return BCM_E_NOT_FOUND; 456 } 457 458 *rtag = t_info->rtag; 459 return BCM_E_NONE; 460 } 461 462 /* 463 * Function: 464 * bcm_trunk_deinit 465 * Purpose: 466 * Release allocated trunk data structures. 467 * Parameters: 468 * unit - StrataSwitch PCI device unit number (driver internal). 469 * Returns: 470 * BCM_E_NONE Success. 471 * BCM_E_XXX 472 */ 473 void 474 _bcm_esw_trunk_deinit(int unit) 475 { 476 #if defined(BCM_XGS3_SWITCH_SUPPORT) 477 if (SOC_IS_XGS3_SWITCH(unit)) { 478 #if defined(BCM_TRIDENT_SUPPORT) 479 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 480 _bcm_trident_trunk_deinit(unit); 481 } else 482 #endif /* BCM_TRIDENT_SUPPORT */ 483 { 484 _bcm_xgs3_trunk_member_detach(unit); 485 _bcm_xgs3_trunk_swfailover_detach(unit); 486 _bcm_xgs3_trunk_mod_port_map_deinit(unit); 487 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 488 _bcm_xgs3_trunk_hwfailover_detach(unit); 489 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 490 } 491 492 #ifdef BCM_APACHE_SUPPORT 493 if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) { 494 if (NULL != TRUNK_CNTL(unit).fp_rr_lag_bmp) { 495 sal_free(TRUNK_CNTL(unit).fp_rr_lag_bmp); 496 TRUNK_CNTL(unit).fp_rr_lag_bmp = NULL; 497 } 498 } 499 #endif /* BCM_APACHE_SUPPORT */ 500 501 #ifdef BCM_WARM_BOOT_SUPPORT 502 if (NULL != TRUNK_CNTL(unit).trunk_bmp_ptr) { 503 sal_free(TRUNK_CNTL(unit).trunk_bmp_ptr); 504 TRUNK_CNTL(unit).trunk_bmp_ptr = NULL; 505 } 506 if (NULL != TRUNK_CNTL(unit).fp_hwf_flags) { 507 sal_free(TRUNK_CNTL(unit).fp_hwf_flags); 508 TRUNK_CNTL(unit).fp_hwf_flags = NULL; 509 } 510 if (NULL != TRUNK_CNTL(unit).hg_hwf_flags) { 511 sal_free(TRUNK_CNTL(unit).hg_hwf_flags); 512 TRUNK_CNTL(unit).hg_hwf_flags = NULL; 513 } 514 #endif /* BCM_WARM_BOOT_SUPPORT */ 515 516 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 517 if (soc_feature(unit, soc_feature_vp_lag)) { 518 bcm_td2_vp_lag_deinit(unit); 519 } 520 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 521 522 } 523 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 524 } 525 526 #ifdef BCM_WARM_BOOT_SUPPORT 527 528 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 529 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 530 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 531 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 532 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 533 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 534 #define BCM_WB_VERSION_1_6 SOC_SCACHE_VERSION(1,6) 535 /*add dlf_index to scache*/ 536 #define BCM_WB_VERSION_1_7 SOC_SCACHE_VERSION(1,7) 537 /* Add bcm_trident_trunk_mbr_zero_rsvd to scache. */ 538 #define BCM_WB_VERSION_1_8 SOC_SCACHE_VERSION(1,8) 539 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_8 540 541 542 #endif /* BCM_WARM_BOOT_SUPPORT */ 543 544 STATIC int 545 _bcm_esw_trunk_hwmem_clear(int unit, soc_mem_t mem) 546 { 547 uint8 *mbuf; 548 int rv, size; 549 550 size = SOC_MEM_TABLE_BYTES(unit, mem); 551 mbuf = soc_cm_salloc(unit, size, "trunk_memory"); 552 if (mbuf == NULL) { 553 return BCM_E_MEMORY; 554 } 555 556 sal_memset(mbuf, 0, size); 557 558 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ANY, 559 soc_mem_index_min(unit, mem), 560 soc_mem_index_max(unit, mem), mbuf); 561 soc_cm_sfree(unit, mbuf); 562 563 return rv; 564 } 565 566 /* 567 * Function: 568 * bcm_trunk_init 569 * Purpose: 570 * Initializes the trunk tables to empty (no trunks configured) 571 * Parameters: 572 * unit - StrataSwitch PCI device unit number (driver internal). 573 * Returns: 574 * BCM_E_NONE Success. 575 * BCM_E_XXX 576 */ 577 578 int 579 bcm_esw_trunk_init(int unit) 580 { 581 #ifdef BCM_XGS_SWITCH_SUPPORT 582 uint16 dev_id; 583 uint8 rev_id; 584 #endif 585 trunk_private_t *t_info; 586 bcm_trunk_t tid; 587 bcm_pbmp_t all_pbmp; 588 soc_mem_t trunk_mem = TRUNK_GROUPm; 589 590 #ifdef BCM_TOMAHAWK3_SUPPORT 591 soc_info_t *si; 592 source_trunk_map_table_entry_t stm_ent; 593 int stm_entry_per_pipe; 594 int pipe; 595 #endif 596 597 int rv = BCM_E_NONE; 598 599 COMPILER_REFERENCE(t_info); 600 COMPILER_REFERENCE(tid); 601 COMPILER_REFERENCE(all_pbmp); 602 603 if (soc_feature(unit, soc_feature_fastlag)) { 604 trunk_mem = FAST_TRUNK_GROUPm; 605 } 606 607 /* Create protection mutex. */ 608 if (NULL == TRUNK_CNTL(unit).lock) { 609 TRUNK_CNTL(unit).lock = sal_mutex_create("Trunk module mutex"); 610 if(NULL == TRUNK_CNTL(unit).lock) { 611 return BCM_E_MEMORY; 612 } 613 } 614 615 TRUNK_LOCK(unit); 616 617 BCM_PBMP_CLEAR(all_pbmp); 618 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 619 620 TRUNK_CNTL(unit).ngroups_fp = 0; 621 TRUNK_CNTL(unit).nports_fp = 0; 622 TRUNK_CNTL(unit).ngroups_hg = 0; 623 TRUNK_CNTL(unit).nports_hg = 0; 624 625 #ifdef BCM_XGS_SWITCH_SUPPORT 626 if (SOC_IS_XGS_SWITCH(unit)) { 627 #ifdef BCM_WARM_BOOT_SUPPORT 628 #ifdef BCM_XGS3_SWITCH_SUPPORT 629 int ngroups_fp_max; 630 soc_scache_handle_t scache_handle; 631 uint32 trunk_scache_size; 632 uint8 *trunk_scache; 633 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 634 int trunk_fp_hwf_flags_alloc_size; 635 int trunk_hg_hwf_flags_alloc_size; 636 637 COMPILER_REFERENCE(trunk_fp_hwf_flags_alloc_size); 638 COMPILER_REFERENCE(trunk_hg_hwf_flags_alloc_size);; 639 640 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 641 642 COMPILER_REFERENCE(ngroups_fp_max); 643 COMPILER_REFERENCE(scache_handle); 644 COMPILER_REFERENCE(trunk_scache_size); 645 COMPILER_REFERENCE(trunk_scache); 646 647 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 648 #endif /* BCM_WARM_BOOT_SUPPORT */ 649 650 if (SOC_IS_SHADOW(unit)) { 651 TRUNK_UNLOCK(unit); 652 return BCM_E_UNAVAIL; 653 } 654 #ifdef BCM_TOMAHAWK3_SUPPORT 655 if (SOC_IS_TOMAHAWK3(unit)) { 656 TRUNK_CNTL(unit).ngroups_fp = 657 soc_mem_index_count(unit, FAST_TRUNK_PORTS_1m); 658 659 /* No HiGig support in TH3 */ 660 TRUNK_CNTL(unit).ngroups_hg = 0; 661 } else 662 #endif 663 #if defined(BCM_SABER2_SUPPORT) 664 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) { 665 TRUNK_CNTL(unit).ngroups_fp = SABER2_5626X_NGROUPS_FP; 666 } else 667 #endif /* BCM_SABER2_SUPPORT */ 668 { 669 TRUNK_CNTL(unit).ngroups_fp = soc_mem_index_count(unit, trunk_mem); 670 } 671 672 #ifdef BCM_WARM_BOOT_SUPPORT 673 #ifdef BCM_XGS3_SWITCH_SUPPORT 674 /* Record maximum HW size */ 675 ngroups_fp_max = TRUNK_CNTL(unit).ngroups_fp; 676 #endif /* BCM_WARM_BOOT_SUPPORT */ 677 #endif 678 679 #ifdef BCM_TOMAHAWK3_SUPPORT 680 if (SOC_IS_TOMAHAWK3(unit)) { 681 TRUNK_CNTL(unit).nports_fp = 1 << soc_mem_field_length(unit, 682 FAST_TRUNK_SIZEm, TG_SIZEf); 683 684 /* No HiGig support in TH3 */ 685 TRUNK_CNTL(unit).nports_hg = 0; 686 } else 687 #endif 688 if (soc_mem_field_valid(unit, trunk_mem, TG_SIZEf)) { 689 soc_cm_get_id(unit, &dev_id, &rev_id); 690 #if defined(BCM_SABER2_SUPPORT) 691 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) { 692 TRUNK_CNTL(unit).nports_fp = SABER2_5626X_NPORTS_FP; 693 } else 694 #endif /* BCM_SABER2_SUPPORT */ 695 if ((dev_id == BCM56830_DEVICE_ID) 696 || (dev_id == BCM56838_DEVICE_ID) 697 || (dev_id == BCM56831_DEVICE_ID) 698 || (dev_id == BCM56834_DEVICE_ID)) { 699 TRUNK_CNTL(unit).nports_fp = 16; 700 } else if (dev_id == BCM56835_DEVICE_ID) { 701 TRUNK_CNTL(unit).nports_fp = 32; 702 } else { 703 TRUNK_CNTL(unit).nports_fp = 1 << soc_mem_field_length(unit, 704 trunk_mem, TG_SIZEf); 705 } 706 } else { 707 TRUNK_CNTL(unit).nports_fp = 8; 708 } 709 710 if (!SOC_WARM_BOOT(unit) && !SOC_HW_RESET(unit)) { 711 #ifdef BCM_TOMAHAWK3_SUPPORT 712 if (SOC_IS_TOMAHAWK3(unit)) { 713 /* Tomahawk 3's Fast LAG ports are split into two memories, 714 * 32 in each, for a total of 64 possible ports per LAG */ 715 rv = _bcm_esw_trunk_hwmem_clear(unit, FAST_TRUNK_PORTS_1m); 716 if (BCM_FAILURE(rv)) { 717 TRUNK_UNLOCK(unit); 718 return BCM_E_INTERNAL; 719 } 720 rv = _bcm_esw_trunk_hwmem_clear(unit, FAST_TRUNK_PORTS_2m); 721 if (BCM_FAILURE(rv)) { 722 TRUNK_UNLOCK(unit); 723 return BCM_E_INTERNAL; 724 } 725 rv = _bcm_esw_trunk_hwmem_clear(unit, FAST_TRUNK_SIZEm); 726 if (BCM_FAILURE(rv)) { 727 TRUNK_UNLOCK(unit); 728 return BCM_E_INTERNAL; 729 } 730 } else 731 #endif 732 { 733 rv = _bcm_esw_trunk_hwmem_clear(unit, trunk_mem); 734 if (BCM_FAILURE(rv)) { 735 TRUNK_UNLOCK(unit); 736 return BCM_E_INTERNAL; 737 } 738 } 739 740 rv = _bcm_esw_trunk_hwmem_clear(unit, TRUNK_BITMAPm); 741 if (BCM_FAILURE(rv)) { 742 TRUNK_UNLOCK(unit); 743 return BCM_E_INTERNAL; 744 } 745 746 if (soc_feature(unit, soc_feature_trunk_egress)) { 747 rv = _bcm_esw_trunk_hwmem_clear(unit, TRUNK_EGR_MASKm); 748 if (BCM_FAILURE(rv)) { 749 TRUNK_UNLOCK(unit); 750 return BCM_E_INTERNAL; 751 } 752 } 753 } 754 755 #if defined(BCM_XGS3_SWITCH_SUPPORT) 756 if (SOC_IS_XGS3_SWITCH(unit)) { 757 uint64 config64, oconfig64; 758 soc_reg_t reg; 759 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 760 soc_reg_t hg_trunk_bmap; 761 #if defined(BCM_GREYHOUND2_SUPPORT) 762 soc_reg_t hg_trunk_bmap_hi = INVALIDr; 763 #endif /* BCM_GREYHOUND2_SUPPORT */ 764 #endif 765 766 if (SOC_WARM_BOOT(unit)) { 767 768 if (SOC_IS_FBX(unit)) { 769 770 #if defined(BCM_TRX_SUPPORT) 771 reg = SOC_IS_TRX(unit) ? ING_CONFIG_64r : ING_CONFIGr; 772 #else /* BCM_TRX_SUPPORT */ 773 reg = ING_CONFIGr; 774 #endif /* BCM_TRX_SUPPORT */ 775 rv = soc_reg_get(unit, reg, REG_PORT_ANY, 0, &config64); 776 if (SOC_FAILURE(rv)) { 777 TRUNK_UNLOCK(unit); 778 return rv; 779 } 780 781 #if defined(BCM_SABER2_SUPPORT) 782 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) { 783 TRUNK_CNTL(unit).ngroups_hg = 784 SABER2_5626X_NGROUPS_HG; 785 TRUNK_CNTL(unit).nports_hg = 786 SABER2_5626X_NPORTS_HG; 787 } else 788 #endif /* BCM_SABER2_SUPPORT */ 789 #if defined(BCM_HAWKEYE_SUPPORT) 790 if (SOC_IS_HAWKEYE(unit)) { 791 TRUNK_CNTL(unit).ngroups_fp = 8; 792 } else 793 #endif 794 /* TD3 only supports trunks 128 mode and not trunks 32 mode. 795 * The field to distinguish is hence not present */ 796 if (!SOC_IS_TRIDENT3X(unit) && !(SOC_IS_TOMAHAWK3(unit))) { 797 if (!soc_reg64_field32_get(unit, reg, config64, 798 TRUNKS128f)) { 799 TRUNK_CNTL(unit).ngroups_fp = 32; 800 } 801 } 802 803 if (SOC_IS_XGS3_FABRIC(unit)) { 804 TRUNK_CNTL(unit).ngroups_fp = 0; 805 TRUNK_CNTL(unit).nports_fp = 0; 806 } 807 #if defined(BCM_HAWKEYE_SUPPORT) 808 if (SOC_IS_HAWKEYE(unit)) { 809 TRUNK_CNTL(unit).ngroups_hg = 0; 810 TRUNK_CNTL(unit).nports_hg = 0; 811 } else 812 #endif 813 if (SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) { 814 TRUNK_CNTL(unit).ngroups_hg = 2; 815 TRUNK_CNTL(unit).nports_hg = 4; 816 } 817 818 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 819 else if (SOC_IS_HB_GW(unit) || SOC_IS_TRX(unit)) { 820 if (soc_mem_is_valid(unit, HG_TRUNK_BITMAPm)) { 821 822 #if defined(BCM_SABER2_SUPPORT) 823 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) { 824 TRUNK_CNTL(unit).ngroups_hg = 825 SABER2_5626X_NGROUPS_HG; 826 } else 827 #endif /* BCM_SABER2_SUPPORT */ 828 { 829 TRUNK_CNTL(unit).ngroups_hg = 830 soc_mem_index_count(unit, HG_TRUNK_BITMAPm); 831 } 832 #if defined(BCM_METROLITE_SUPPORT) 833 if (soc_feature(unit, soc_feature_hg_trunk_groups_max_2)) { 834 TRUNK_CNTL(unit).ngroups_hg = 2; 835 } 836 if (soc_feature(unit, soc_feature_hg_trunk_group_members_max_4)) { 837 TRUNK_CNTL(unit).nports_hg = 4; 838 } 839 #endif /* BCM_METROLITE_SUPPORT */ 840 } else { 841 #if defined(BCM_TRIUMPH2_SUPPORT) 842 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 843 SOC_IS_VALKYRIE2(unit)) { 844 hg_trunk_bmap = HG_TRUNK_BITMAP_64r; 845 } else 846 #endif /* BCM_TRIUMPH2_SUPPORT */ 847 #if defined(BCM_GREYHOUND2_SUPPORT) 848 if (SOC_IS_GREYHOUND2(unit)) { 849 hg_trunk_bmap = HG_TRUNK_BITMAP_LOr; 850 hg_trunk_bmap_hi = HG_TRUNK_BITMAP_HIr; 851 } else 852 #endif /* BCM_GREYHOUND2_SUPPORT */ 853 { 854 hg_trunk_bmap = HG_TRUNK_BITMAPr; 855 } 856 #if defined(BCM_TOMAHAWK3_SUPPORT) 857 /* TH3 doesn't support HG. ngroups_hg was set to 0 858 * above 859 */ 860 if (!SOC_IS_TOMAHAWK3(unit)) 861 #endif 862 { 863 TRUNK_CNTL(unit).ngroups_hg = 864 SOC_REG_NUMELS(unit, hg_trunk_bmap); 865 } 866 } 867 868 #if defined(BCM_HURRICANE3_SUPPORT) 869 if (SOC_IS_HURRICANE3(unit)) { 870 soc_cm_get_id(unit, &dev_id, &rev_id); 871 if ((dev_id == BCM56163_DEVICE_ID) || 872 (dev_id == BCM56164_DEVICE_ID) || 873 (dev_id == BCM56166_DEVICE_ID)) { /* Hurricane3Lite */ 874 TRUNK_CNTL(unit).ngroups_hg = 2; 875 } 876 } 877 #endif /* BCM_HURRICANE3_SUPPORT */ 878 879 #if defined(BCM_TRIDENT_SUPPORT) 880 if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, 881 TG_SIZEf)) { 882 soc_cm_get_id(unit, &dev_id, &rev_id); 883 #if defined(BCM_SABER2_SUPPORT) 884 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) { 885 TRUNK_CNTL(unit).nports_hg = 886 SABER2_5626X_NPORTS_HG; 887 } else 888 #endif /* BCM_SABER2_SUPPORT */ 889 if ((dev_id == BCM56838_DEVICE_ID) 890 || (dev_id == BCM56831_DEVICE_ID)) { 891 TRUNK_CNTL(unit).nports_hg = 16; 892 } else if (dev_id == BCM56835_DEVICE_ID) { 893 TRUNK_CNTL(unit).nports_hg = 32; 894 } else { 895 #if defined(BCM_METROLITE_SUPPORT) 896 if (soc_feature(unit, soc_feature_hg_trunk_group_members_max_4)) { 897 TRUNK_CNTL(unit).nports_hg = 4; 898 } else 899 #endif /* BCM_METROLITE_SUPPORT */ 900 TRUNK_CNTL(unit).nports_hg = 901 1 << soc_mem_field_length(unit, 902 HG_TRUNK_GROUPm, TG_SIZEf); 903 } 904 } else 905 #endif /* BCM_TRIDENT_SUPPORT */ 906 #if defined(BCM_SCORPION_SUPPORT) 907 if (SOC_IS_SC_CQ(unit)) { 908 TRUNK_CNTL(unit).nports_hg = 16; 909 } else 910 #endif /* BCM_SCORPION_SUPPORT */ 911 #if defined(BCM_HURRICANE3_SUPPORT) 912 if (soc_feature 913 (unit, 914 soc_feature_hg_trunk_group_members_max_4)) { 915 TRUNK_CNTL(unit).nports_hg = 4; 916 } else 917 #endif /* BCM_HURRICANE3_SUPPORT */ 918 { 919 #if defined(BCM_TOMAHAWK3_SUPPORT) 920 if (!SOC_IS_TOMAHAWK3(unit)) 921 #endif 922 { 923 TRUNK_CNTL(unit).nports_hg = 8; 924 } 925 } 926 } 927 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRX_SUPPORT */ 928 } 929 930 } else { 931 int trunk128; 932 int stm_index; 933 int size; 934 int min_idx, max_idx, cnt_idx; 935 source_trunk_map_table_entry_t *ent; 936 uint8 *mbuf; 937 soc_field_t tgid_fld = TGIDf; 938 939 trunk128 = soc_property_get(unit, spn_TRUNK_EXTEND, 1); 940 941 /* For Raptor and devices that support only the extended trunk 942 * mode, TRUNKS128 field should alwyas be programmed to 1 */ 943 if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || 944 soc_feature(unit, soc_feature_trunk_extended_only)) { 945 trunk128 = 1; 946 } 947 948 if (!trunk128) { 949 if (SOC_IS_HAWKEYE(unit)){ 950 TRUNK_CNTL(unit).ngroups_fp = 8; 951 } else { 952 TRUNK_CNTL(unit).ngroups_fp = 32; 953 } 954 } 955 956 if (SOC_IS_XGS3_FABRIC(unit)) { 957 TRUNK_CNTL(unit).ngroups_fp = 0; 958 TRUNK_CNTL(unit).nports_fp = 0; 959 } 960 961 #if defined(BCM_SABER2_SUPPORT) 962 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) { 963 TRUNK_CNTL(unit).ngroups_hg = 964 SABER2_5626X_NGROUPS_HG; 965 TRUNK_CNTL(unit).nports_hg = 966 SABER2_5626X_NPORTS_HG; 967 } 968 #endif /* BCM_SABER2_SUPPORT */ 969 /* Reset SOURCE_TRUNK_MAP table */ 970 min_idx = soc_mem_index_min(unit, SOURCE_TRUNK_MAP_TABLEm); 971 max_idx = soc_mem_index_max(unit, SOURCE_TRUNK_MAP_TABLEm); 972 cnt_idx = soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm); 973 974 size = SOC_MEM_TABLE_BYTES(unit, SOURCE_TRUNK_MAP_TABLEm); 975 mbuf = soc_cm_salloc(unit, size, "source_trunk_map"); 976 if (NULL == mbuf) { 977 TRUNK_UNLOCK(unit); 978 return BCM_E_MEMORY; 979 } 980 981 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 982 983 /* Tomahawk 3's memory is ADDR_SPLIT, so it cannot do soc_mem_read_range or 984 * soc_mem_write_range 985 */ 986 #ifdef BCM_TOMAHAWK3_SUPPORT 987 /* Clear port type, which describes whether a normal port is 988 * being used or a trunk port, and trunk group id (TGID) 989 */ 990 if (SOC_IS_TOMAHAWK3(unit)) { 991 si = &SOC_INFO(unit); 992 stm_entry_per_pipe = cnt_idx / _TH3_PIPES_PER_DEV; 993 for (stm_index = 0; stm_index < cnt_idx; stm_index++) { 994 pipe = stm_index / stm_entry_per_pipe; 995 996 /* Skip the memory if the pipe is not active */ 997 if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 998 continue; 999 } 1000 1001 rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, 1002 MEM_BLOCK_ANY, stm_index, &stm_ent); 1003 if (BCM_FAILURE(rv)) { 1004 soc_cm_sfree(unit, mbuf); 1005 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 1006 TRUNK_UNLOCK(unit); 1007 return rv; 1008 } 1009 /* clear the PORT_TYPEf and TGIDf fields */ 1010 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set 1011 (unit, &stm_ent, PORT_TYPEf, 0); 1012 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set 1013 (unit, &stm_ent, TGIDf, 0); 1014 1015 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, 1016 MEM_BLOCK_ALL, stm_index, &stm_ent); 1017 if (BCM_FAILURE(rv)) { 1018 soc_cm_sfree(unit, mbuf); 1019 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 1020 TRUNK_UNLOCK(unit); 1021 return rv; 1022 } 1023 1024 } 1025 } else 1026 #endif 1027 { 1028 rv = soc_mem_read_range(unit, SOURCE_TRUNK_MAP_TABLEm, 1029 MEM_BLOCK_ANY, min_idx, max_idx, mbuf); 1030 if (BCM_FAILURE(rv)) { 1031 soc_cm_sfree(unit, mbuf); 1032 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 1033 TRUNK_UNLOCK(unit); 1034 return rv; 1035 } 1036 if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, 1037 SRC_TGIDf)) { 1038 tgid_fld = SRC_TGIDf; 1039 } 1040 for (stm_index = 0; stm_index < cnt_idx; stm_index++) { 1041 ent = soc_mem_table_idx_to_pointer(unit, 1042 SOURCE_TRUNK_MAP_TABLEm, 1043 source_trunk_map_table_entry_t *, 1044 mbuf, stm_index); 1045 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set 1046 (unit, ent, PORT_TYPEf, 0); 1047 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set 1048 (unit, ent, tgid_fld, 0); 1049 } 1050 rv = soc_mem_write_range(unit, SOURCE_TRUNK_MAP_TABLEm, 1051 MEM_BLOCK_ANY, min_idx, max_idx, 1052 mbuf); 1053 } 1054 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 1055 soc_cm_sfree(unit, mbuf); 1056 if (BCM_FAILURE(rv)) { 1057 TRUNK_UNLOCK(unit); 1058 return rv; 1059 } 1060 1061 if (SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) { 1062 #if defined(BCM_TRX_SUPPORT) 1063 reg = SOC_IS_TRX(unit) ? ING_CONFIG_64r : ING_CONFIGr; 1064 #else /* BCM_TRX_SUPPORT */ 1065 reg = ING_CONFIGr; 1066 #endif /* BCM_TRX_SUPPORT */ 1067 if (SOC_REG_FIELD_VALID(unit, reg, TRUNKS128f)) { 1068 rv = soc_reg_get(unit, reg, REG_PORT_ANY, 0, &config64); 1069 if (SOC_FAILURE(rv)) { 1070 TRUNK_UNLOCK(unit); 1071 return rv; 1072 } 1073 oconfig64 = config64; 1074 soc_reg64_field32_set(unit, reg, &config64, TRUNKS128f, 1075 trunk128 ? 1 : 0); 1076 if (COMPILER_64_NE(config64, oconfig64)) { 1077 rv = soc_reg_set(unit, reg, REG_PORT_ANY, 0, config64); 1078 if (SOC_FAILURE(rv)) { 1079 TRUNK_UNLOCK(unit); 1080 return rv; 1081 } 1082 } 1083 } 1084 1085 rv = soc_mem_clear(unit, NONUCAST_TRUNK_BLOCK_MASKm, 1086 MEM_BLOCK_ALL, 0); 1087 1088 if (SOC_FAILURE(rv)) { 1089 TRUNK_UNLOCK(unit); 1090 return rv; 1091 } 1092 1093 #if defined(BCM_TRIUMPH3_SUPPORT) 1094 if (soc_feature(unit, soc_feature_axp)) { 1095 if (soc_mem_is_valid(unit, AXP_WTX_TRUNK_GROUP_BITMAPm)) { 1096 rv = soc_mem_clear(unit, AXP_WTX_TRUNK_GROUP_BITMAPm, 1097 MEM_BLOCK_ALL, 0); 1098 if (SOC_FAILURE(rv)) { 1099 TRUNK_UNLOCK(unit); 1100 return rv; 1101 } 1102 } 1103 if (soc_mem_is_valid(unit, AXP_WTX_TRUNK_BLOCK_MASKm)) { 1104 rv = soc_mem_clear(unit, AXP_WTX_TRUNK_BLOCK_MASKm, 1105 MEM_BLOCK_ALL, 0); 1106 if (SOC_FAILURE(rv)) { 1107 TRUNK_UNLOCK(unit); 1108 return rv; 1109 } 1110 } 1111 } 1112 #endif /* BCM_TRIUMPH3_SUPPORT */ 1113 1114 if (soc_mem_is_valid(unit, TRUNK_MEMBERm)) { 1115 rv = soc_mem_clear(unit, TRUNK_MEMBERm, MEM_BLOCK_ALL, 0); 1116 if (SOC_FAILURE(rv)) { 1117 TRUNK_UNLOCK(unit); 1118 return rv; 1119 } 1120 } 1121 1122 if (soc_feature(unit, soc_feature_hg_trunking)) { 1123 if (soc_mem_is_valid(unit, HIGIG_TRUNK_CONTROLm)) { 1124 higig_trunk_control_entry_t entry; 1125 rv = soc_mem_read(unit, HIGIG_TRUNK_CONTROLm, 1126 MEM_BLOCK_ANY, 0, &entry); 1127 if (SOC_FAILURE(rv)) { 1128 TRUNK_UNLOCK(unit); 1129 return rv; 1130 } 1131 #if defined(BCM_KATANA2_SUPPORT) 1132 if (soc_feature(unit, soc_feature_linkphy_coe) || 1133 soc_feature(unit, soc_feature_subtag_coe)) { 1134 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 1135 } 1136 if (SOC_IS_KATANA2(unit) && 1137 soc_feature(unit, soc_feature_flex_port)) { 1138 rv = _bcm_kt2_flexio_pbmp_update(unit, 1139 &all_pbmp); 1140 if (SOC_FAILURE(rv)) { 1141 TRUNK_UNLOCK(unit); 1142 return rv; 1143 } 1144 } 1145 #endif 1146 soc_mem_pbmp_field_set(unit, HIGIG_TRUNK_CONTROLm, 1147 &entry, ACTIVE_PORT_BITMAPf, &all_pbmp); 1148 rv = soc_mem_write(unit, HIGIG_TRUNK_CONTROLm, 1149 MEM_BLOCK_ALL, 0, &entry); 1150 if (SOC_FAILURE(rv)) { 1151 TRUNK_UNLOCK(unit); 1152 return rv; 1153 } 1154 } else { 1155 uint64 val, hg_cntl_entry; 1156 soc_reg_t hg_trunk_reg; 1157 #if defined(BCM_GREYHOUND2_SUPPORT) 1158 soc_reg_t hg_trunk_reg_hi = INVALIDr; 1159 #endif /* BCM_GREYHOUND2_SUPPORT */ 1160 1161 COMPILER_REFERENCE(val); 1162 1163 #if defined(BCM_TRIUMPH2_SUPPORT) 1164 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1165 SOC_IS_VALKYRIE2(unit)) { 1166 hg_trunk_reg = HIGIG_TRUNK_CONTROL_64r; 1167 } else 1168 #endif /* BCM_TRIUMPH2_SUPPORT */ 1169 #if defined(BCM_GREYHOUND2_SUPPORT) 1170 if (SOC_IS_GREYHOUND2(unit)) { 1171 hg_trunk_reg = HIGIG_TRUNK_CONTROL_LOr; 1172 hg_trunk_reg_hi = HIGIG_TRUNK_CONTROL_HIr; 1173 } else 1174 #endif /* BCM_GREYHOUND2_SUPPORT */ 1175 { 1176 hg_trunk_reg = HIGIG_TRUNK_CONTROLr; 1177 } 1178 1179 rv = soc_reg_get(unit, hg_trunk_reg, 1180 REG_PORT_ANY, 0, 1181 &hg_cntl_entry); 1182 if (SOC_FAILURE(rv)) { 1183 TRUNK_UNLOCK(unit); 1184 return rv; 1185 } 1186 val = soc_reg64_field_get(unit, hg_trunk_reg, 1187 hg_cntl_entry, 1188 ACTIVE_PORT_BITMAPf); 1189 COMPILER_64_ZERO(hg_cntl_entry); 1190 soc_reg64_field_set(unit, hg_trunk_reg, 1191 &hg_cntl_entry, 1192 ACTIVE_PORT_BITMAPf, val); 1193 rv = soc_reg_set(unit, hg_trunk_reg, 1194 REG_PORT_ANY, 0, 1195 hg_cntl_entry); 1196 if (SOC_FAILURE(rv)) { 1197 TRUNK_UNLOCK(unit); 1198 return rv; 1199 } 1200 #if defined(BCM_GREYHOUND2_SUPPORT) 1201 if (SOC_IS_GREYHOUND2(unit)) { 1202 rv = soc_reg_get(unit, hg_trunk_reg_hi, 1203 REG_PORT_ANY, 0, 1204 &hg_cntl_entry); 1205 if (SOC_FAILURE(rv)) { 1206 TRUNK_UNLOCK(unit); 1207 return rv; 1208 } 1209 val = soc_reg64_field_get(unit, 1210 hg_trunk_reg_hi, 1211 hg_cntl_entry, 1212 ACTIVE_PORT_BITMAPf); 1213 COMPILER_64_ZERO(hg_cntl_entry); 1214 soc_reg64_field_set(unit, hg_trunk_reg_hi, 1215 &hg_cntl_entry, 1216 ACTIVE_PORT_BITMAPf, val); 1217 rv = soc_reg_set(unit, hg_trunk_reg_hi, 1218 REG_PORT_ANY, 0, 1219 hg_cntl_entry); 1220 if (SOC_FAILURE(rv)) { 1221 TRUNK_UNLOCK(unit); 1222 return rv; 1223 } 1224 } 1225 #endif /* BCM_GREYHOUND2_SUPPORT */ 1226 } 1227 } 1228 1229 if (SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) { 1230 if (soc_feature(unit, soc_feature_hg_trunking)) { 1231 TRUNK_CNTL(unit).ngroups_hg = 2; 1232 TRUNK_CNTL(unit).nports_hg = 4; 1233 rv = WRITE_HIGIG_TRUNK_GROUPr(unit, 0); 1234 if (SOC_FAILURE(rv)) { 1235 TRUNK_UNLOCK(unit); 1236 return rv; 1237 } 1238 } 1239 } 1240 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 1241 else if ((SOC_IS_HB_GW(unit) || SOC_IS_TRX(unit)) 1242 && !SOC_IS_TOMAHAWK3(unit)) { 1243 uint64 val64; 1244 1245 #if defined(BCM_TRIDENT_SUPPORT) 1246 if (soc_mem_is_valid(unit, HG_TRUNK_BITMAPm) && 1247 soc_mem_is_valid(unit, HG_TRUNK_GROUPm) && 1248 soc_mem_is_valid(unit, HG_TRUNK_MEMBERm)) { 1249 1250 #if defined(BCM_SABER2_SUPPORT) 1251 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit)) { 1252 TRUNK_CNTL(unit).ngroups_hg = 1253 SABER2_5626X_NGROUPS_HG; 1254 TRUNK_CNTL(unit).nports_hg = 1255 SABER2_5626X_NPORTS_HG; 1256 } else 1257 #endif /* BCM_SABER2_SUPPORT */ 1258 { 1259 TRUNK_CNTL(unit).ngroups_hg = 1260 soc_mem_index_count(unit, HG_TRUNK_BITMAPm); 1261 TRUNK_CNTL(unit).nports_hg = 1262 1 << soc_mem_field_length(unit, HG_TRUNK_GROUPm, 1263 TG_SIZEf); 1264 } 1265 1266 #if defined(BCM_METROLITE_SUPPORT) 1267 if (soc_feature(unit, soc_feature_hg_trunk_groups_max_2)) { 1268 TRUNK_CNTL(unit).ngroups_hg = 2; 1269 } 1270 if (soc_feature(unit, soc_feature_hg_trunk_group_members_max_4)) { 1271 TRUNK_CNTL(unit).nports_hg = 4; 1272 } 1273 #endif /* BCM_METROLITE_SUPPORT */ 1274 1275 rv = soc_mem_clear(unit, HG_TRUNK_BITMAPm, 1276 MEM_BLOCK_ALL, TRUE); 1277 if (SOC_FAILURE(rv)) { 1278 TRUNK_UNLOCK(unit); 1279 return rv; 1280 } 1281 rv = soc_mem_clear(unit, HG_TRUNK_GROUPm, 1282 MEM_BLOCK_ALL, TRUE); 1283 if (SOC_FAILURE(rv)) { 1284 TRUNK_UNLOCK(unit); 1285 return rv; 1286 } 1287 rv = soc_mem_clear(unit, HG_TRUNK_MEMBERm, 1288 MEM_BLOCK_ALL, TRUE); 1289 1290 if (SOC_FAILURE(rv)) { 1291 TRUNK_UNLOCK(unit); 1292 return rv; 1293 } 1294 } else 1295 #endif /* BCM_TRIDENT_SUPPORT */ 1296 { 1297 1298 #if defined(BCM_TRIUMPH2_SUPPORT) 1299 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1300 SOC_IS_VALKYRIE2(unit)) { 1301 hg_trunk_bmap = HG_TRUNK_BITMAP_64r; 1302 } else 1303 #endif /* BCM_TRIUMPH2_SUPPORT */ 1304 #if defined(BCM_GREYHOUND2_SUPPORT) 1305 if (SOC_IS_GREYHOUND2(unit)) { 1306 hg_trunk_bmap = HG_TRUNK_BITMAP_LOr; 1307 hg_trunk_bmap_hi = HG_TRUNK_BITMAP_HIr; 1308 } else 1309 #endif /* BCM_GREYHOUND2_SUPPORT */ 1310 { 1311 hg_trunk_bmap = HG_TRUNK_BITMAPr; 1312 } 1313 1314 TRUNK_CNTL(unit).ngroups_hg = 1315 SOC_REG_NUMELS(unit, hg_trunk_bmap); 1316 1317 #if defined(BCM_HURRICANE3_SUPPORT) 1318 if (SOC_IS_HURRICANE3(unit)) { 1319 soc_cm_get_id(unit, &dev_id, &rev_id); 1320 if ((dev_id == BCM56163_DEVICE_ID) || 1321 (dev_id == BCM56164_DEVICE_ID) || 1322 (dev_id == BCM56166_DEVICE_ID)) { /* Hurricane3Lite */ 1323 TRUNK_CNTL(unit).ngroups_hg = 2; 1324 } 1325 } 1326 #endif /* BCM_HURRICANE3_SUPPORT */ 1327 1328 #if defined(BCM_SCORPION_SUPPORT) 1329 if (SOC_IS_SC_CQ(unit)) { 1330 TRUNK_CNTL(unit).nports_hg = 16; 1331 } else 1332 #endif /* BCM_SCORPION_SUPPORT */ 1333 #if defined(BCM_HURRICANE3_SUPPORT) 1334 if (soc_feature 1335 (unit, 1336 soc_feature_hg_trunk_group_members_max_4)) { 1337 TRUNK_CNTL(unit).nports_hg = 4; 1338 } else 1339 #endif /* BCM_HURRICANE3_SUPPORT */ 1340 { 1341 TRUNK_CNTL(unit).nports_hg = 8; 1342 } 1343 1344 COMPILER_64_ZERO(val64); 1345 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) { 1346 #if defined(BCM_GREYHOUND2_SUPPORT) 1347 if (SOC_IS_GREYHOUND2(unit)) { 1348 rv = soc_reg_set(unit, hg_trunk_bmap_hi, 1349 REG_PORT_ANY, tid, val64); 1350 if (SOC_FAILURE(rv)) { 1351 TRUNK_UNLOCK(unit); 1352 return rv; 1353 } 1354 } 1355 #endif /* BCM_GREYHOUND2_SUPPORT */ 1356 rv = soc_reg_set(unit, hg_trunk_bmap, REG_PORT_ANY, 1357 tid, val64); 1358 if (SOC_FAILURE(rv)) { 1359 TRUNK_UNLOCK(unit); 1360 return rv; 1361 } 1362 1363 rv = WRITE_HG_TRUNK_GROUPr(unit, tid, val64); 1364 if (SOC_FAILURE(rv)) { 1365 TRUNK_UNLOCK(unit); 1366 return rv; 1367 } 1368 } 1369 } 1370 } 1371 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 1372 } 1373 } 1374 #ifdef BCM_TOMAHAWK3_SUPPORT 1375 if (SOC_IS_TOMAHAWK3(unit)) { 1376 rv = _bcm_th3_trunk_init(unit); 1377 if (BCM_FAILURE(rv)) { 1378 TRUNK_UNLOCK(unit); 1379 return rv; 1380 } 1381 } else 1382 #endif 1383 #ifdef BCM_TRIDENT_SUPPORT 1384 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 1385 rv = _bcm_trident_trunk_init(unit); 1386 if (BCM_FAILURE(rv)) { 1387 TRUNK_UNLOCK(unit); 1388 return rv; 1389 } 1390 } else 1391 #endif /* BCM_TRIDENT_SUPPORT */ 1392 { 1393 rv = _bcm_xgs3_trunk_member_init(unit); 1394 if (BCM_FAILURE(rv)) { 1395 TRUNK_UNLOCK(unit); 1396 _bcm_esw_trunk_deinit(unit); 1397 return rv; 1398 } 1399 rv = _bcm_xgs3_trunk_swfailover_init(unit); 1400 if (BCM_FAILURE(rv)) { 1401 TRUNK_UNLOCK(unit); 1402 _bcm_esw_trunk_deinit(unit); 1403 return rv; 1404 } 1405 rv = _bcm_xgs3_trunk_mod_port_map_init(unit); 1406 if (BCM_FAILURE(rv)) { 1407 TRUNK_UNLOCK(unit); 1408 _bcm_esw_trunk_deinit(unit); 1409 return rv; 1410 } 1411 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 1412 if (soc_feature(unit, soc_feature_hg_trunk_failover) || 1413 soc_feature(unit, soc_feature_port_lag_failover)) { 1414 rv = _bcm_xgs3_trunk_hwfailover_init(unit); 1415 if (BCM_FAILURE(rv)) { 1416 TRUNK_UNLOCK(unit); 1417 _bcm_esw_trunk_deinit(unit); 1418 return rv; 1419 } 1420 } 1421 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 1422 } 1423 1424 #ifdef BCM_APACHE_SUPPORT 1425 if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) { 1426 int num_groups_rr_fp = 2; 1427 TRUNK_CNTL(unit).ngroups_rr_fp = num_groups_rr_fp; 1428 1429 if (NULL == TRUNK_CNTL(unit).fp_rr_lag_bmp) { 1430 TRUNK_CNTL(unit).fp_rr_lag_bmp = 1431 sal_alloc(SHR_BITALLOCSIZE(num_groups_rr_fp), "fp rr lags used bitmap"); 1432 if (NULL == TRUNK_CNTL(unit).fp_rr_lag_bmp) { 1433 TRUNK_UNLOCK(unit); 1434 _bcm_esw_trunk_deinit(unit); 1435 return BCM_E_MEMORY; 1436 } 1437 } 1438 sal_memset(TRUNK_CNTL(unit).fp_rr_lag_bmp, 0, SHR_BITALLOCSIZE(num_groups_rr_fp)); 1439 } 1440 #endif /* BCM_APACHE_SUPPORT */ 1441 1442 #ifdef BCM_WARM_BOOT_SUPPORT 1443 TRUNK_CNTL(unit).trunk_bmp_alloc = 1444 SHR_BITALLOCSIZE(ngroups_fp_max + 1445 TRUNK_CNTL(unit).ngroups_hg); 1446 1447 /* Num FP trunks, num fabric trunks, bitmap of defined trunks */ 1448 trunk_scache_size = sizeof(uint32) + sizeof(uint32) + 1449 TRUNK_CNTL(unit).trunk_bmp_alloc; 1450 1451 if (NULL == TRUNK_CNTL(unit).trunk_bmp_ptr) { 1452 TRUNK_CNTL(unit).trunk_bmp_ptr = 1453 sal_alloc( TRUNK_CNTL(unit).trunk_bmp_alloc, "trunk used bitmap"); 1454 if (NULL == TRUNK_CNTL(unit).trunk_bmp_ptr) { 1455 _bcm_esw_trunk_deinit(unit); 1456 TRUNK_UNLOCK(unit); 1457 return BCM_E_MEMORY; 1458 } 1459 } 1460 1461 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 1462 trunk_fp_hwf_flags_alloc_size = 0; 1463 trunk_hg_hwf_flags_alloc_size = 0; 1464 if (soc_feature(unit, soc_feature_port_lag_failover)) { 1465 /* FP trunk failover flags */ 1466 #if defined(BCM_TRIDENT_SUPPORT) 1467 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 1468 /* For Trident, ngproups_fp_max = 1024, nports_fp = 256, 1469 * while the maximum number of front-panel trunk ports is 1470 * limited by the number of entries in 1471 * SOURCE_TRUNK_MAP_TABLE, which is 4096. To efficiently 1472 * utilize scache space, for each trunk group, 1 byte of 1473 * BCM_TRUNK_FLAG_xxx flags, 2 bytes of trunk size, and 1474 * trunk-size bytes of hardware failover flags are stored. 1475 */ 1476 trunk_fp_hwf_flags_alloc_size += 1477 (ngroups_fp_max * 3 + 1478 soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm)) * 1479 sizeof(uint8); 1480 } else 1481 #if defined(BCM_TOMAHAWK3_SUPPORT) 1482 if (SOC_IS_TOMAHAWK3(unit)) { 1483 /* 1484 * For TH3, soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm) 1485 * evaluates to 160 1486 */ 1487 trunk_fp_hwf_flags_alloc_size += 1488 (ngroups_fp_max * 3 + 1489 soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm)) * 1490 sizeof(uint8); 1491 } else 1492 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1493 #endif /* BCM_TRIDENT_SUPPORT */ 1494 { 1495 trunk_fp_hwf_flags_alloc_size += 1496 (ngroups_fp_max * (TRUNK_CNTL(unit).nports_fp + 1)) * 1497 sizeof(uint8); 1498 } 1499 } 1500 1501 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 1502 /* HG trunk failover flags */ 1503 trunk_hg_hwf_flags_alloc_size += 1504 (TRUNK_CNTL(unit).ngroups_hg * 1505 (TRUNK_CNTL(unit).nports_hg + 1)) * 1506 sizeof(uint8); 1507 } 1508 1509 if (0 != trunk_fp_hwf_flags_alloc_size) { 1510 if (NULL == TRUNK_CNTL(unit).fp_hwf_flags) { 1511 TRUNK_CNTL(unit).fp_hwf_flags = 1512 sal_alloc(trunk_fp_hwf_flags_alloc_size, "trunk fp hwf flags"); 1513 } 1514 if (NULL == TRUNK_CNTL(unit).fp_hwf_flags) { 1515 _bcm_esw_trunk_deinit(unit); 1516 return BCM_E_MEMORY; 1517 } 1518 TRUNK_CNTL(unit).fp_hwf_alloc = 1519 trunk_fp_hwf_flags_alloc_size; 1520 trunk_scache_size += trunk_fp_hwf_flags_alloc_size; 1521 } 1522 1523 if (0 != trunk_hg_hwf_flags_alloc_size) { 1524 if (NULL == TRUNK_CNTL(unit).hg_hwf_flags) { 1525 TRUNK_CNTL(unit).hg_hwf_flags = 1526 sal_alloc(trunk_hg_hwf_flags_alloc_size, "trunk hg hwf flags"); 1527 } 1528 if (NULL == TRUNK_CNTL(unit).hg_hwf_flags) { 1529 _bcm_esw_trunk_deinit(unit); 1530 return BCM_E_MEMORY; 1531 } 1532 TRUNK_CNTL(unit).hg_hwf_alloc = 1533 trunk_hg_hwf_flags_alloc_size; 1534 trunk_scache_size += trunk_hg_hwf_flags_alloc_size; 1535 } 1536 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 1537 1538 /* Allocate scache space for BCM_TRUNK_FLAG_IPMC_CLEAVE flag */ 1539 trunk_scache_size += (ngroups_fp_max * sizeof(uint8)); 1540 1541 /* Allocate scache space for ipmc_psc */ 1542 trunk_scache_size += (ngroups_fp_max * sizeof(int)); 1543 1544 /*allocate scache space for dlf_index */ 1545 trunk_scache_size += (ngroups_fp_max * sizeof(int)); 1546 1547 1548 /* Allocate scache space to store trunk membership */ 1549 #if defined(BCM_TRIDENT_SUPPORT) 1550 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 1551 /* For each front-panel trunk group, store the following info: 1552 * - 2 bytes containing the number of members, which can be 1553 * up to 256. 1554 * - 2 bytes per member, containing the module and port IDs. 1555 * - 1 byte per member, containing member flags. 1556 * 1557 * Trident can support up to 1k trunk groups. It's not 1558 * necessary to allocate space for 256 members per trunk group, 1559 * since the maximum number of members Trident can support is 1560 * limited by the TRUNK_MEMBER table. 1561 */ 1562 trunk_scache_size += (ngroups_fp_max * 2 + 1563 soc_mem_index_count(unit, TRUNK_MEMBERm) * 3) * 1564 sizeof(uint8); 1565 } else 1566 #if defined(BCM_TOMAHAWK3_SUPPORT) 1567 if (SOC_IS_TOMAHAWK3(unit)) { 1568 /* For each front-panel trunk group, store the following info: 1569 * - 2 byte containing the number of members, which can be 1570 * up to 64. 1571 * - 1 bytes per member, containing the port IDs. Mod Id is 0 always. 1572 * - 1 byte per member, containing member flags. 1573 */ 1574 trunk_scache_size += (ngroups_fp_max * 2 + 1575 soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm) * 2) * 1576 sizeof(uint8); 1577 } else 1578 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1579 #endif /* BCM_TRIDENT_SUPPORT */ 1580 { 1581 /* For each front-panel trunk group, store the following info: 1582 * - 1 byte containing the number of members. 1583 * - 2 bytes per member, containing the module and port IDs. 1584 * - 1 byte per member, containing member flags. 1585 */ 1586 trunk_scache_size += 1587 (ngroups_fp_max * (1 + 3 * TRUNK_CNTL(unit).nports_fp)) 1588 * sizeof(uint8); 1589 } 1590 1591 /* Allocate scache space for Higig dynamic load balancing info */ 1592 #ifdef BCM_TRIDENT_SUPPORT 1593 if (soc_feature(unit, soc_feature_hg_dlb) && 1594 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 1595 int hg_dlb_scache_size; 1596 rv = bcm_trident_hg_dlb_wb_alloc_size_get(unit, 1597 &hg_dlb_scache_size); 1598 if (SOC_FAILURE(rv)) { 1599 TRUNK_UNLOCK(unit); 1600 return rv; 1601 } 1602 trunk_scache_size += hg_dlb_scache_size; 1603 } 1604 #endif /* BCM_TRIDENT_SUPPORT */ 1605 1606 /* Allocate scache space for LAG dynamic load balancing info */ 1607 #ifdef BCM_TRIUMPH3_SUPPORT 1608 if (soc_feature(unit, soc_feature_lag_dlb) && 1609 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 1610 int lag_dlb_scache_size; 1611 rv = bcm_tr3_lag_dlb_wb_alloc_size_get(unit, 1612 &lag_dlb_scache_size); 1613 if (SOC_FAILURE(rv)) { 1614 TRUNK_UNLOCK(unit); 1615 return rv; 1616 } 1617 trunk_scache_size += lag_dlb_scache_size; 1618 } 1619 #endif /* BCM_TRIUMPH3_SUPPORT */ 1620 1621 #ifdef BCM_TOMAHAWK2_SUPPORT 1622 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 1623 int hgt_lag_dlb_scache_size; 1624 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_wb_alloc_size_get(unit, 1625 &hgt_lag_dlb_scache_size)); 1626 trunk_scache_size += hgt_lag_dlb_scache_size; 1627 } 1628 #endif /* BCM_TOMAHAWK2_SUPPORT */ 1629 1630 /* Allocate scache space for psc */ 1631 #if defined(BCM_TRIDENT_SUPPORT) 1632 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 1633 trunk_scache_size += (ngroups_fp_max * sizeof(int)); 1634 } 1635 #endif /* BCM_TRIDENT_SUPPORT */ 1636 1637 /* 1638 * Allocate scache space for saving TRUNK_MEMBER table property. 1639 */ 1640 #if defined(BCM_TRIDENT_SUPPORT) 1641 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 1642 trunk_scache_size += (sizeof(int)); 1643 } 1644 #endif /* BCM_TRIDENT_SUPPORT */ 1645 1646 /* Limited scache mode unsupported */ 1647 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 1648 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRUNK, 0); 1649 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 1650 (0 == SOC_WARM_BOOT(unit)), 1651 trunk_scache_size, 1652 &trunk_scache, 1653 BCM_WB_DEFAULT_VERSION, NULL); 1654 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1655 TRUNK_UNLOCK(unit); 1656 _bcm_esw_trunk_deinit(unit); 1657 return rv; 1658 } 1659 } 1660 #endif /* BCM_WARM_BOOT_SUPPORT */ 1661 } 1662 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1663 } 1664 #endif /* BCM_XGS_SWITCH_SUPPORT */ 1665 1666 #ifdef BCM_XGS12_FABRIC_SUPPORT 1667 if (SOC_IS_XGS12_FABRIC(unit)) { 1668 bcm_port_t port; 1669 1670 TRUNK_CNTL(unit).ngroups_hg = SOC_REG_NUMELS(unit, ING_HGTRUNKr); 1671 TRUNK_CNTL(unit).nports_hg = 8; 1672 1673 if (!SOC_WARM_BOOT(unit)) { 1674 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) { 1675 PBMP_PORT_ITER(unit, port) { 1676 rv = WRITE_ING_HGTRUNKr(unit, port, tid, 0); 1677 if (SOC_FAILURE(rv)) { 1678 TRUNK_UNLOCK(unit); 1679 return rv; 1680 } 1681 } 1682 } 1683 } 1684 } 1685 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 1686 1687 if (TRUNK_CNTL(unit).t_info != NULL) { 1688 sal_free(TRUNK_CNTL(unit).t_info); 1689 TRUNK_CNTL(unit).t_info = NULL; 1690 1691 } 1692 1693 if (TRUNK_NUM_GROUPS(unit) > 0) { 1694 TRUNK_CNTL(unit).t_info = 1695 sal_alloc(TRUNK_NUM_GROUPS(unit) * sizeof(trunk_private_t), 1696 "trunk_priv"); 1697 if (NULL == TRUNK_CNTL(unit).t_info) { 1698 TRUNK_UNLOCK(unit); 1699 _bcm_esw_trunk_deinit(unit); 1700 return (BCM_E_MEMORY); 1701 } 1702 1703 t_info = TRUNK_CNTL(unit).t_info; 1704 1705 /* Clear the state for Cold or Warm Boot. 1706 * Warm Boot will update below. */ 1707 for (tid = 0; tid < TRUNK_NUM_GROUPS(unit); tid++) { 1708 t_info->tid = BCM_TRUNK_INVALID; 1709 t_info->in_use = FALSE; 1710 #ifdef BCM_TOMAHAWK3_SUPPORT 1711 if (SOC_IS_TOMAHAWK3(unit)) { 1712 t_info->psc = BCM_TRUNK_PSC_PORTFLOW; 1713 } else 1714 #endif 1715 { 1716 t_info->psc = BCM_TRUNK_PSC_DEFAULT; 1717 } 1718 t_info->ipmc_psc = 0; 1719 t_info->rtag = 0; 1720 t_info->flags = 0; 1721 t_info->dlf_index_spec = -1; 1722 t_info->dlf_index_used = -1; 1723 t_info->dlf_port_used = 0; 1724 t_info->mc_index_spec = -1; 1725 t_info->mc_index_used = -1; 1726 t_info->mc_port_used = 0; 1727 t_info->ipmc_index_spec = -1; 1728 t_info->ipmc_index_used = -1; 1729 t_info->ipmc_port_used = 0; 1730 t_info->dynamic_size = 0; 1731 t_info->dynamic_age = 0; 1732 t_info->dynamic_load_exponent = 0; 1733 t_info->dynamic_expected_load_exponent = 0; 1734 t_info++; 1735 } 1736 } 1737 1738 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 1739 if (soc_feature(unit, soc_feature_vp_lag)) { 1740 rv = bcm_td2_vp_lag_init(unit); 1741 if (BCM_FAILURE(rv)) { 1742 TRUNK_UNLOCK(unit); 1743 return rv; 1744 } 1745 1746 } 1747 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 1748 1749 #if defined(BCM_XGS_FABRIC_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT) 1750 if (SOC_WARM_BOOT(unit)) { 1751 if (/*!SOC_IS_TOMAHAWK3(unit)*/ 1) { 1752 rv = _bcm_trunk_reinit(unit); 1753 if (BCM_FAILURE(rv)) { 1754 TRUNK_UNLOCK(unit); 1755 return rv; 1756 } 1757 } 1758 1759 } 1760 #endif 1761 1762 TRUNK_UNLOCK(unit); 1763 1764 return BCM_E_NONE; 1765 } 1766 1767 1768 /* 1769 * Function: 1770 * bcm_trunk_detach 1771 * Purpose: 1772 * Cleans up the trunk tables. 1773 * Parameters: 1774 * unit - StrataSwitch PCI device unit number (driver internal). 1775 * Returns: 1776 * BCM_E_NONE Success. 1777 * BCM_E_XXX 1778 */ 1779 1780 int 1781 bcm_esw_trunk_detach(int unit) 1782 { 1783 /* Return if trunk was not initialized. */ 1784 if (NULL == TRUNK_CNTL(unit).t_info) { 1785 return (BCM_E_NONE); 1786 } 1787 1788 sal_free(TRUNK_CNTL(unit).t_info); 1789 /* Destroy protection mutex. */ 1790 if (NULL != TRUNK_CNTL(unit).lock) { 1791 sal_mutex_destroy(TRUNK_CNTL(unit).lock); 1792 TRUNK_CNTL(unit).lock = NULL; 1793 } 1794 _bcm_esw_trunk_deinit(unit); 1795 sal_memset(&TRUNK_CNTL(unit), 0, sizeof(trunk_cntl_t)); 1796 1797 return BCM_E_NONE; 1798 } 1799 1800 /* 1801 * Function: 1802 * _bcm_esw_trunk_chip_info_vp_resource_get 1803 * Purpose: 1804 * Get the VP related information. 1805 * Be called internally for forward compatibility. 1806 * Parameters: 1807 * unit - StrataSwitch PCI device unit number. 1808 * vp_id_min - Minimum virtual port trunk ID number. 1809 * vp_id_max - Maximum virtual port trunk ID number. 1810 * vp_ports_max - Maximum number of virtual ports per virtual 1811 * port trunk group. 1812 * Returns: 1813 * BCM_E_NONE Success. 1814 * Notes: 1815 * None. 1816 */ 1817 int 1818 _bcm_esw_trunk_chip_info_vp_resource_get(int unit, int *vp_id_min, 1819 int *vp_id_max, int *vp_ports_max) 1820 { 1821 /* Initialize the VP LAG information */ 1822 if (vp_id_min != NULL) { 1823 *vp_id_min = -1; 1824 } 1825 1826 if (vp_id_max != NULL) { 1827 *vp_id_max = -1; 1828 } 1829 1830 if (vp_ports_max != NULL) { 1831 *vp_ports_max = 0; 1832 } 1833 1834 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 1835 if (soc_feature(unit, soc_feature_vp_lag)) { 1836 int ngroups_vp_lag = 0, nports_vp_lag = 0; 1837 1838 BCM_IF_ERROR_RETURN(bcm_td2_vp_lag_info_get(unit, &ngroups_vp_lag, 1839 &nports_vp_lag)); 1840 if (ngroups_vp_lag > 0) { 1841 1842 if (vp_id_min != NULL) { 1843 *vp_id_min = TRUNK_CNTL(unit).ngroups_fp + 1844 TRUNK_CNTL(unit).ngroups_hg; 1845 } 1846 1847 if (vp_id_max != NULL) { 1848 *vp_id_max = TRUNK_CNTL(unit).ngroups_fp + 1849 TRUNK_CNTL(unit).ngroups_hg + ngroups_vp_lag - 1; 1850 } 1851 1852 if (vp_ports_max != NULL) { 1853 *vp_ports_max = nports_vp_lag; 1854 } 1855 } 1856 } 1857 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 1858 1859 return BCM_E_NONE; 1860 } 1861 1862 /* 1863 * Function: 1864 * _bcm_esw_trunk_id_is_vp_lag 1865 * Purpose: 1866 * Determine if trunk ID is a VP LAG. 1867 * Parameters: 1868 * unit - SOC unit number 1869 * tid - Trunk ID 1870 * tid_is_vp_lag - (OUT) Indicates if trun ID is a VP LAG 1871 * Returns: 1872 * BCM_E_xxx 1873 */ 1874 int 1875 _bcm_esw_trunk_id_is_vp_lag(int unit, bcm_trunk_t tid, int *tid_is_vp_lag) 1876 { 1877 int vp_id_min = -1, vp_id_max = -1; 1878 1879 if (tid < 0) { 1880 return BCM_E_PARAM; 1881 } 1882 1883 BCM_IF_ERROR_RETURN( 1884 _bcm_esw_trunk_chip_info_vp_resource_get(unit, &vp_id_min, 1885 &vp_id_max, NULL)); 1886 1887 if (tid >= vp_id_min && tid <= vp_id_max) { 1888 *tid_is_vp_lag = TRUE; 1889 } else { 1890 *tid_is_vp_lag = FALSE; 1891 } 1892 1893 return BCM_E_NONE; 1894 } 1895 1896 /* 1897 * Function: 1898 * _bcm_esw_trunk_tid_to_vp_lag_vp 1899 * Purpose: 1900 * Convert trunk ID to the VP value representing VP LAG. 1901 * Parameters: 1902 * unit - SOC unit number 1903 * tid - Trunk ID 1904 * vp_lag_vp - (OUT) VP value 1905 * Returns: 1906 * BCM_E_xxx 1907 */ 1908 int 1909 _bcm_esw_trunk_tid_to_vp_lag_vp(int unit, bcm_trunk_t tid, int *vp_lag_vp) 1910 { 1911 int tid_is_vp_lag; 1912 1913 BCM_IF_ERROR_RETURN(_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 1914 1915 if (tid_is_vp_lag) { 1916 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 1917 if (soc_feature(unit, soc_feature_vp_lag)) { 1918 return bcm_td2_tid_to_vp_lag_vp(unit, tid, vp_lag_vp); 1919 } else 1920 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 1921 { 1922 return BCM_E_PARAM; 1923 } 1924 } else { 1925 return BCM_E_PARAM; 1926 } 1927 } 1928 1929 /* 1930 * Function: 1931 * _bcm_esw_trunk_vp_lag_vp_to_tid 1932 * Purpose: 1933 * Convert the VP value representing a VP LAG to trunk ID. 1934 * Parameters: 1935 * unit - SOC unit number 1936 * vp_lag_vp - VP value 1937 * tid - (OUT) Trunk ID 1938 * Returns: 1939 * BCM_E_xxx 1940 */ 1941 int 1942 _bcm_esw_trunk_vp_lag_vp_to_tid(int unit, int vp_lag_vp, bcm_trunk_t *tid) 1943 { 1944 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 1945 if (soc_feature(unit, soc_feature_vp_lag)) { 1946 return bcm_td2_vp_lag_vp_to_tid(unit, vp_lag_vp, tid); 1947 } 1948 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 1949 1950 return BCM_E_UNAVAIL; 1951 } 1952 1953 /* 1954 * Function: 1955 * _bcm_trunk_create_id 1956 * Purpose: 1957 * Create the software data structure for the specified trunk ID. 1958 * This function does not update any hardware tables, 1959 * must call bcm_trunk_set() to finish trunk setting. 1960 * Parameters: 1961 * unit - StrataSwitch PCI device unit number (driver internal). 1962 * tid - The trunk ID. 1963 * Returns: 1964 * BCM_E_NONE - Success. 1965 * BCM_E_INIT - trunking software not initialized 1966 * BCM_E_EXISTS - TID already used 1967 * BCM_E_BADID - TID out of range 1968 */ 1969 STATIC int 1970 _bcm_esw_trunk_create_id(int unit, bcm_trunk_t tid) 1971 { 1972 trunk_private_t *t_info; 1973 int rv; 1974 1975 TRUNK_CHECK(unit, tid); 1976 1977 TRUNK_LOCK(unit); 1978 1979 t_info = &TRUNK_INFO(unit, tid); 1980 1981 if (t_info->tid == BCM_TRUNK_INVALID) { 1982 t_info->tid = tid; 1983 #ifdef BCM_TOMAHAWK3_SUPPORT 1984 if (SOC_IS_TOMAHAWK3(unit)) { 1985 t_info->psc = BCM_TRUNK_PSC_PORTFLOW; 1986 } else 1987 #endif 1988 { 1989 t_info->psc = BCM_TRUNK_PSC_DEFAULT; 1990 } 1991 t_info->in_use = FALSE; 1992 #ifdef BCM_APACHE_SUPPORT 1993 t_info->rr_lag_select = -1; 1994 #endif /* BCM_APACHE_SUPPORT */ 1995 rv = BCM_E_NONE; 1996 } else { 1997 rv = BCM_E_EXISTS; 1998 } 1999 2000 #ifdef BCM_WARM_BOOT_SUPPORT 2001 SOC_CONTROL_LOCK(unit); 2002 SOC_CONTROL(unit)->scache_dirty = 1; 2003 SOC_CONTROL_UNLOCK(unit); 2004 #endif 2005 2006 TRUNK_UNLOCK(unit); 2007 2008 return rv; 2009 } 2010 2011 /* 2012 * Function: 2013 * bcm_trunk_vplag_get 2014 * Purpose: 2015 * GET VPLAG port Id for VPLAG trunk. 2016 * Parameters: 2017 * unit - (IN) StrataSwitch PCI device unit number (driver internal). 2018 * tid - (IN) The trunk ID. 2019 * vplag_port_id - (OUT) VPLAG Port Id 2020 * Returns: 2021 * BCM_E_NONE - Success. 2022 * BCM_E_PARAM - Incorrect LAG Id 2023 * BCM_E_NOT_FOUND - LAG Id not used 2024 */ 2025 int 2026 bcm_esw_trunk_vplag_get(int unit, bcm_trunk_t tid, bcm_gport_t *vplag_port_id) 2027 { 2028 int rv = BCM_E_NONE; 2029 2030 if (!soc_feature(unit, soc_feature_vp_lag)) { 2031 return BCM_E_UNAVAIL; 2032 2033 } else { 2034 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 2035 int vp_id; 2036 rv = bcm_td2_tid_to_vp_lag_vp(unit, tid, &vp_id); 2037 if (BCM_SUCCESS(rv)) { 2038 BCM_GPORT_VPLAG_PORT_ID_SET(*vplag_port_id, vp_id); 2039 } 2040 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 2041 } 2042 2043 return rv; 2044 } 2045 2046 /* 2047 * Function: 2048 * bcm_trunk_vplag_create 2049 * Purpose: 2050 * Create VPLAG trunk. 2051 * Parameters: 2052 * unit - (IN) StrataSwitch PCI device unit number (driver internal). 2053 * flags - (IN) Flags. 2054 * tid - (IN/OUT) The trunk ID. 2055 * vplag_port_id - (IN/OUT) VPLAG Port Id 2056 * Returns: 2057 * BCM_E_NONE - Success. 2058 * BCM_E_FULL - run out of TIDs 2059 */ 2060 int 2061 bcm_esw_trunk_with_vplag_create(int unit, uint32 flags, bcm_trunk_t *tid, 2062 bcm_gport_t *vplag_port_id) 2063 { 2064 int rv = BCM_E_NONE; 2065 2066 TRUNK_INIT(unit); 2067 2068 if (NULL == tid) { 2069 return BCM_E_PARAM; 2070 } 2071 2072 if (!soc_feature(unit, soc_feature_vp_lag)) { 2073 return BCM_E_UNAVAIL; 2074 } 2075 2076 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 2077 if (flags & BCM_TRUNK_FLAG_WITH_ID) { 2078 int tid_is_vp_lag = 0; 2079 BCM_IF_ERROR_RETURN 2080 (_bcm_esw_trunk_id_is_vp_lag(unit, *tid, &tid_is_vp_lag)); 2081 2082 if (!(tid_is_vp_lag)) { 2083 return BCM_E_PARAM; 2084 } 2085 } 2086 2087 VPLAG_LOCK(unit); 2088 rv = bcm_td2_vp_lag_create(unit, flags, tid, vplag_port_id); 2089 VPLAG_UNLOCK(unit); 2090 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 2091 2092 return rv; 2093 } 2094 2095 /* 2096 * Function: 2097 * bcm_trunk_create 2098 * Purpose: 2099 * Create the software data structure for a trunk ID. 2100 * This function does not update any hardware tables, 2101 * must call bcm_trunk_set() to finish trunk setting. 2102 * Parameters: 2103 * unit - StrataSwitch PCI device unit number (driver internal). 2104 * flags - Flags. 2105 * tid - (Out), The trunk ID. 2106 * Returns: 2107 * BCM_E_NONE - Success. 2108 * BCM_E_FULL - run out of TIDs 2109 */ 2110 2111 int 2112 bcm_esw_trunk_create(int unit, uint32 flags, bcm_trunk_t *tid) 2113 { 2114 trunk_private_t *t_info; 2115 int rv, i; 2116 bcm_trunk_t max_tid; 2117 int tid_is_vp_lag = 0; 2118 2119 TRUNK_INIT(unit); 2120 2121 if (NULL == tid) { 2122 return BCM_E_PARAM; 2123 } 2124 2125 if (flags & BCM_TRUNK_FLAG_WITH_ID) { 2126 BCM_IF_ERROR_RETURN 2127 (_bcm_esw_trunk_id_is_vp_lag(unit, *tid, &tid_is_vp_lag)); 2128 } 2129 2130 if (tid_is_vp_lag || (flags & BCM_TRUNK_FLAG_VP)) { 2131 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 2132 if (soc_feature(unit, soc_feature_vp_lag)) { 2133 VPLAG_LOCK(unit); 2134 rv = bcm_td2_vp_lag_create(unit, flags, tid, NULL); 2135 VPLAG_UNLOCK(unit); 2136 return rv; 2137 } else 2138 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 2139 { 2140 return BCM_E_PARAM; 2141 } 2142 } 2143 2144 if (flags & BCM_TRUNK_FLAG_WITH_ID) { 2145 return _bcm_esw_trunk_create_id(unit, *tid); 2146 } 2147 2148 TRUNK_LOCK(unit); 2149 2150 rv = BCM_E_FULL; 2151 2152 t_info = TRUNK_CNTL(unit).t_info; 2153 2154 if (NULL == t_info) { 2155 return BCM_E_PARAM; 2156 } 2157 2158 if (TRUNK_CNTL(unit).ngroups_fp == 0) { 2159 max_tid = TRUNK_CNTL(unit).ngroups_hg - 1; 2160 } 2161 else { 2162 max_tid = TRUNK_CNTL(unit).ngroups_fp - 1; 2163 } 2164 2165 for (i = 0; i <= max_tid; i++) { 2166 if (t_info->tid == BCM_TRUNK_INVALID) { 2167 t_info->tid = i; 2168 t_info->in_use = FALSE; 2169 #ifdef BCM_TOMAHAWK3_SUPPORT 2170 if (SOC_IS_TOMAHAWK3(unit)) { 2171 t_info->psc = BCM_TRUNK_PSC_PORTFLOW; 2172 } else 2173 #endif 2174 { 2175 t_info->psc = BCM_TRUNK_PSC_DEFAULT; 2176 } 2177 *tid = i; 2178 rv = BCM_E_NONE; 2179 break; 2180 } 2181 t_info++; 2182 } 2183 2184 #ifdef BCM_WARM_BOOT_SUPPORT 2185 SOC_CONTROL_LOCK(unit); 2186 SOC_CONTROL(unit)->scache_dirty = 1; 2187 SOC_CONTROL_UNLOCK(unit); 2188 #endif 2189 2190 TRUNK_UNLOCK(unit); 2191 2192 return rv; 2193 } 2194 2195 /* 2196 * Function: 2197 * _bcm_trunk_id_validate 2198 * Purpose: 2199 * Service routine to validate validity of trunk id. 2200 * Parameters: 2201 * unit - StrataSwitch PCI device unit number (driver internal). 2202 * tid - The trunk ID. 2203 * Returns: 2204 * BCM_E_NONE - Success. 2205 * BCM_E_INIT - trunking software not initialized 2206 * BCM_E_BADID - TID out of range 2207 */ 2208 int 2209 _bcm_trunk_id_validate(int unit, bcm_trunk_t tid) 2210 { 2211 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 2212 if (soc_feature(unit, soc_feature_vp_lag)) { 2213 int tid_is_vp_lag; 2214 2215 BCM_IF_ERROR_RETURN 2216 (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 2217 if (tid_is_vp_lag) { 2218 return BCM_E_NONE; 2219 } 2220 } 2221 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 2222 2223 TRUNK_CHECK(unit, tid); 2224 2225 return (BCM_E_NONE); 2226 } 2227 2228 2229 /* 2230 * Function: 2231 * bcm_trunk_psc_get 2232 * Purpose: 2233 * Get the trunk selection criteria. 2234 * Parameters: 2235 * unit - StrataSwitch PCI device unit number (driver internal). 2236 * tid - The trunk ID to be used. 2237 * psc - (OUT) Identify the trunk selection criteria. 2238 * Returns: 2239 * BCM_E_NONE Success. 2240 * BCM_E_XXX 2241 */ 2242 2243 int 2244 bcm_esw_trunk_psc_get(int unit, bcm_trunk_t tid, int *psc) 2245 { 2246 trunk_private_t *t_info; 2247 int rv; 2248 2249 TRUNK_INIT(unit); 2250 TRUNK_CHECK(unit, tid); 2251 2252 t_info = &TRUNK_INFO(unit, tid); 2253 2254 if (t_info->tid == BCM_TRUNK_INVALID) { 2255 *psc = 0; 2256 rv = BCM_E_NOT_FOUND; 2257 } else { 2258 *psc = t_info->psc; 2259 rv = BCM_E_NONE; 2260 } 2261 2262 return rv; 2263 } 2264 2265 /* 2266 * Function: 2267 * bcm_trunk_chip_info_get 2268 * Purpose: 2269 * Get the trunk information. 2270 * Parameters: 2271 * unit - StrataSwitch PCI device unit number (driver internal). 2272 * t_info - (OUT) Identify the trunk selection criteria. 2273 * Returns: 2274 * BCM_E_NONE Success. 2275 * Notes: 2276 * None. 2277 */ 2278 2279 int 2280 bcm_esw_trunk_chip_info_get(int unit, bcm_trunk_chip_info_t *ta_info) 2281 { 2282 TRUNK_INIT(unit); 2283 2284 ta_info->trunk_group_count = TRUNK_CNTL(unit).ngroups_fp; 2285 2286 if (TRUNK_CNTL(unit).ngroups_fp > 0) { 2287 ta_info->trunk_id_min = 0; 2288 ta_info->trunk_id_max = TRUNK_CNTL(unit).ngroups_fp - 1; 2289 } 2290 else { 2291 ta_info->trunk_id_min = -1; 2292 ta_info->trunk_id_max = -1; 2293 } 2294 ta_info->trunk_ports_max = TRUNK_CNTL(unit).nports_fp; 2295 2296 if (TRUNK_CNTL(unit).ngroups_hg > 0) { 2297 ta_info->trunk_fabric_id_min = TRUNK_CNTL(unit).ngroups_fp; 2298 ta_info->trunk_fabric_id_max = 2299 TRUNK_CNTL(unit).ngroups_fp + TRUNK_CNTL(unit).ngroups_hg - 1; 2300 } 2301 else { 2302 ta_info->trunk_fabric_id_min = -1; 2303 ta_info->trunk_fabric_id_max = -1; 2304 } 2305 ta_info->trunk_fabric_ports_max = TRUNK_CNTL(unit).nports_hg; 2306 2307 ta_info->vp_id_min = -1; 2308 ta_info->vp_id_max = -1; 2309 ta_info->vp_ports_max = 0; 2310 2311 BCM_IF_ERROR_RETURN( 2312 _bcm_esw_trunk_chip_info_vp_resource_get(unit, &(ta_info->vp_id_min), 2313 &(ta_info->vp_id_max), 2314 &(ta_info->vp_ports_max))); 2315 /* Get available VP LAG resource ONLY for API return */ 2316 if (soc_feature(unit, soc_feature_reserve_vp_lag_resource_index_zero)) { 2317 /* 2318 * Since entry 0 of VP LAG releated resource (such as EGR_VPLAG_GROUP, 2319 * EGR_VPLAG_MEMBER table) are reserved, so the maximum number 2320 * of VP LAGs which are capable of performing VP LAG resolution should 2321 * be decreased by 1, and the initial tunnel id of VG LAG usage should 2322 * be increased by 1. 2323 */ 2324 if (ta_info->vp_id_max > ta_info->vp_id_min) { 2325 ta_info->vp_id_min += 1; 2326 } else { 2327 /* Reset the vp resource */ 2328 ta_info->vp_id_min = -1; 2329 ta_info->vp_id_max = -1; 2330 ta_info->vp_ports_max = 0; 2331 } 2332 } 2333 2334 return BCM_E_NONE; 2335 } 2336 2337 /* 2338 * Function: 2339 * _bcm_esw_trunk_member_compar 2340 * Purpose: 2341 * Internal utility routine for sorting on trunk member gport. 2342 * Parameters: 2343 * a - Pointer to trunk member. 2344 * b - Pointer to trunk member. 2345 * Returns: 2346 * -1 - a is less than b. 2347 * 0 - a equals b. 2348 * 1 - a is more than b. 2349 */ 2350 2351 STATIC int 2352 _bcm_esw_trunk_member_compar(void *a, void *b) 2353 { 2354 bcm_trunk_member_t *d1 = a; 2355 bcm_trunk_member_t *d2 = b; 2356 2357 return (d1->gport < d2->gport ? -1 : 2358 d1->gport > d2->gport ? 1 : 0); 2359 } 2360 2361 /* 2362 * Function: 2363 * bcm_esw_trunk_sort 2364 * Purpose: 2365 * Sort members in a trunk group. 2366 * Parameters: 2367 * member_count - Number of trunk members. 2368 * member_array - Array of trunk members. 2369 * Returns: 2370 * BCM_E_XXX 2371 */ 2372 2373 STATIC int 2374 _bcm_esw_trunk_sort(int member_count, bcm_trunk_member_t **member_array) 2375 { 2376 if (member_count > 0) { 2377 if (NULL == *member_array) { 2378 return BCM_E_PARAM; 2379 } 2380 } else { 2381 return BCM_E_NONE; 2382 } 2383 2384 /* Sort members in the accending order */ 2385 _shr_sort(*member_array, member_count, sizeof (bcm_trunk_member_t), _bcm_esw_trunk_member_compar); 2386 2387 return BCM_E_NONE; 2388 } 2389 2390 /* 2391 * Function: 2392 * _bcm_esw_trunk_modify 2393 * Purpose: 2394 * Set, add, or delete members to/from a trunk group. 2395 * Parameters: 2396 * unit - StrataSwitch PCI device unit number (driver internal). 2397 * tid - The trunk ID to be affected. 2398 * trunk_info - Information on the trunk group. 2399 * member_count - Number of trunk members. 2400 * member_array - Array of trunk members. 2401 * op - Type of operation: TRUNK_MEMBER_OP_SET, ADD, or DELETE. 2402 * member - The member to add or delete. 2403 * Returns: 2404 * BCM_E_XXX 2405 */ 2406 STATIC int 2407 _bcm_esw_trunk_modify(int unit, bcm_trunk_t tid, 2408 bcm_trunk_info_t *trunk_info, int member_count, 2409 bcm_trunk_member_t *member_array, int op, 2410 bcm_trunk_member_t *member) 2411 { 2412 int rv; 2413 trunk_private_t *t_info; 2414 bcm_trunk_info_t local_trunk_info; 2415 int tid_is_vp_lag; 2416 bcm_module_t modid; 2417 bcm_port_t port; 2418 bcm_trunk_t tgid; 2419 int id; 2420 int i; 2421 2422 TRUNK_INIT(unit); 2423 2424 BCM_IF_ERROR_RETURN 2425 (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 2426 if (tid_is_vp_lag) { 2427 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 2428 if (soc_feature(unit, soc_feature_vp_lag)) { 2429 VPLAG_LOCK(unit); 2430 rv = bcm_td2_vp_lag_set(unit, tid, trunk_info, member_count, 2431 member_array); 2432 VPLAG_UNLOCK(unit); 2433 return rv; 2434 } else 2435 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 2436 { 2437 return BCM_E_PARAM; 2438 } 2439 } 2440 2441 TRUNK_CHECK(unit, tid); 2442 2443 t_info = &TRUNK_INFO(unit, tid); 2444 2445 if (t_info->tid == BCM_TRUNK_INVALID) { 2446 return BCM_E_NOT_FOUND; 2447 } 2448 2449 if (NULL == trunk_info) { 2450 return BCM_E_PARAM; 2451 } 2452 2453 if (member_count > 0) { 2454 if (NULL == member_array) { 2455 return BCM_E_PARAM; 2456 } 2457 } else { 2458 if (NULL != member_array) { 2459 return BCM_E_PARAM; 2460 } 2461 } 2462 2463 /* Sort trunk members */ 2464 if ((trunk_info->flags & BCM_TRUNK_FLAG_MEMBER_SORT)) { 2465 for (i = 0; i < member_count; i++) { 2466 BCM_IF_ERROR_RETURN 2467 (_bcm_esw_gport_resolve(unit, member_array[i].gport, 2468 &modid, &port, &tgid, &id)); 2469 SOC_GPORT_MODPORT_SET(member_array[i].gport, modid, port); 2470 } 2471 rv = _bcm_esw_trunk_sort(member_count, &member_array); 2472 if (BCM_FAILURE(rv)) { 2473 return rv; 2474 } 2475 } 2476 2477 /* Check number of ports in trunk group */ 2478 if ((TRUNK_FP_TID(unit, tid) && 2479 (member_count > TRUNK_CNTL(unit).nports_fp)) || 2480 (TRUNK_FABRIC_TID(unit, tid) && 2481 (member_count > TRUNK_CNTL(unit).nports_hg))) { 2482 return BCM_E_PARAM; 2483 } 2484 2485 #if defined (BCM_APACHE_SUPPORT) 2486 if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) { 2487 int rr_lag_sel; 2488 soc_reg_t rr_counter_reg[] = {RR_COUNTER_1r, RR_COUNTER_2r}; 2489 2490 if ((t_info->psc != trunk_info->psc) && 2491 (trunk_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN)) { 2492 /* If PSC is changed to RR Lag, reserve RR_LAG_SELECT */ 2493 2494 for (rr_lag_sel = 0; rr_lag_sel < TRUNK_CNTL(unit).ngroups_rr_fp; rr_lag_sel++) { 2495 if (!SHR_BITGET(TRUNK_CNTL(unit).fp_rr_lag_bmp, rr_lag_sel)) { 2496 t_info->rr_lag_select = rr_lag_sel; 2497 break; 2498 } 2499 } 2500 if (rr_lag_sel == TRUNK_CNTL(unit).ngroups_rr_fp) { 2501 return BCM_E_RESOURCE; 2502 } 2503 SHR_BITSET(TRUNK_CNTL(unit).fp_rr_lag_bmp, rr_lag_sel); 2504 soc_reg32_set(unit, rr_counter_reg[rr_lag_sel], REG_PORT_ANY, 0, 0); 2505 2506 } else if ((t_info->psc != trunk_info->psc) && 2507 (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN)) { 2508 /* If PSC is changed from RR Lag, unreserve RR_LAG_SELECT */ 2509 2510 rr_lag_sel = t_info->rr_lag_select; 2511 t_info->rr_lag_select = -1; 2512 SHR_BITCLR(TRUNK_CNTL(unit).fp_rr_lag_bmp, rr_lag_sel); 2513 soc_reg32_set(unit, rr_counter_reg[rr_lag_sel], REG_PORT_ANY, 0, 0); 2514 } 2515 } 2516 #endif /* BCM_APACHE_SUPPORT */ 2517 2518 bcm_trunk_info_t_init(&local_trunk_info); 2519 sal_memcpy(&local_trunk_info, trunk_info, sizeof(bcm_trunk_info_t)); 2520 2521 TRUNK_LOCK(unit); 2522 2523 rv = mbcm_driver[unit]->mbcm_trunk_modify(unit, tid, &local_trunk_info, 2524 member_count, member_array, t_info, op, member); 2525 if (BCM_SUCCESS(rv)) { 2526 t_info->flags = trunk_info->flags; 2527 t_info->psc = trunk_info->psc; 2528 t_info->ipmc_psc = trunk_info->ipmc_psc; 2529 if (member_count > 0) { 2530 t_info->in_use = TRUE; 2531 } 2532 } 2533 2534 TRUNK_UNLOCK(unit); 2535 2536 #if defined(BCM_XGS3_SWITCH_SUPPORT) 2537 /* reconcile Mirror to Port programming with trunk member ports. */ 2538 if (SOC_IS_XGS3_SWITCH(unit) && BCM_SUCCESS(rv) 2539 && !SOC_IS_TOMAHAWK3(unit)) { 2540 rv = _bcm_xgs3_mirror_trunk_update(unit, tid); 2541 } 2542 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 2543 2544 return rv; 2545 } 2546 2547 /* 2548 * Function: 2549 * _bcm_esw_trunk_set 2550 * Purpose: 2551 * Adds ports to a trunk group. 2552 * Parameters: 2553 * unit - StrataSwitch PCI device unit number (driver internal). 2554 * tid - The trunk ID to be affected. 2555 * trunk_info - Information on the trunk group. 2556 * member_count - Number of trunk members. 2557 * member_array - Array of trunk members. 2558 * Returns: 2559 * BCM_E_NONE Success. 2560 * BCM_E_XXX 2561 * Notes: 2562 helper function callable by both bcm_esw_trunk_set() 2563 * and bcm_esw_trunk_psc_set() 2564 */ 2565 STATIC int 2566 _bcm_esw_trunk_set(int unit, bcm_trunk_t tid, bcm_trunk_info_t *trunk_info, 2567 int member_count, bcm_trunk_member_t *member_array) 2568 { 2569 int rv = BCM_E_NONE; 2570 2571 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 2572 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 2573 int index, i = 0, count = 0, status; 2574 bcm_trunk_member_t *temp_member_array; 2575 2576 temp_member_array = sal_alloc( 2577 sizeof(bcm_trunk_member_t) * member_count, "TR3 trunk WAR"); 2578 if (temp_member_array == NULL) { 2579 return BCM_E_MEMORY; 2580 } 2581 for (index = 0; index < member_count; index++) { 2582 status = 1; 2583 SOC_LINKSCAN_MODPORT_MAP_LOCK(unit); 2584 rv = _bcm_td_stk_modport_map_member_link_handler(unit, 2585 member_array[index].gport, tid, 0, &status); 2586 SOC_LINKSCAN_MODPORT_MAP_UNLOCK(unit); 2587 if (BCM_FAILURE(rv)) { 2588 sal_free(temp_member_array); 2589 return (rv); 2590 } 2591 if (status == 0) { 2592 count++; 2593 } else { 2594 temp_member_array[i] = member_array[index]; 2595 i++; 2596 } 2597 } 2598 if ((count != 0) && (count != member_count)) { 2599 rv = _bcm_esw_trunk_modify(unit, tid, trunk_info, 2600 member_count - count, 2601 temp_member_array, 2602 TRUNK_MEMBER_OP_SET, NULL); 2603 } else { 2604 rv = _bcm_esw_trunk_modify(unit, tid, trunk_info, 2605 member_count, 2606 member_array, 2607 TRUNK_MEMBER_OP_SET, NULL); 2608 } 2609 sal_free(temp_member_array); 2610 } else 2611 #endif /* #(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) */ 2612 { 2613 rv = _bcm_esw_trunk_modify(unit, tid, trunk_info, 2614 member_count, 2615 member_array, 2616 TRUNK_MEMBER_OP_SET, NULL); 2617 } 2618 return rv; 2619 } 2620 2621 #ifdef BCM_TOMAHAWK3_SUPPORT 2622 /* 2623 * Function: 2624 * _bcm_th3_trunk_psc_validate 2625 * Purpose: 2626 * Set the trunk selection criteria. 2627 * Parameters: 2628 * unit - StrataSwitch PCI device unit number (driver internal). 2629 * tid - The trunk ID to be affected. 2630 * psc - Identify the trunk selection criteria. 2631 * Returns: 2632 * BCM_E_NONE Success. 2633 * BCM_E_XXX 2634 * Notes: th3 helper function callable by both bcm_esw_trunk_set() 2635 * and bcm_esw_trunk_psc_set() for th3 2636 */ 2637 STATIC int 2638 _bcm_th3_trunk_psc_validate(int unit, bcm_trunk_t tid, int psc) 2639 2640 { 2641 trunk_private_t *t_info; 2642 2643 TRUNK_INIT(unit); 2644 TRUNK_CHECK(unit, tid); 2645 2646 t_info = &TRUNK_INFO(unit, tid); 2647 2648 if ((psc == 0) || (t_info->psc == psc)) { 2649 return BCM_E_NONE; 2650 } 2651 2652 /* If the new psc is one of the dynamic load balancing modes, but the old 2653 * psc is not, then return BCM_E_PARAM, since dynamic_size and dynamic_age 2654 * parameters are not available when calling bcm_trunk_set. 2655 */ 2656 if (!((psc == BCM_TRUNK_PSC_PORTFLOW) || 2657 (psc == BCM_TRUNK_PSC_RANDOMIZED))) { 2658 return BCM_E_UNAVAIL; 2659 } 2660 return BCM_E_NONE; 2661 } 2662 #endif 2663 2664 /* 2665 * Function: 2666 * bcm_trunk_psc_set 2667 * Purpose: 2668 * Set the trunk selection criteria. 2669 * Parameters: 2670 * unit - StrataSwitch PCI device unit number (driver internal). 2671 * tid - The trunk ID to be affected. 2672 * psc - Identify the trunk selection criteria. 2673 * Returns: 2674 * BCM_E_NONE Success. 2675 * BCM_E_XXX 2676 */ 2677 2678 int 2679 bcm_esw_trunk_psc_set(int unit, bcm_trunk_t tid, int psc) 2680 { 2681 trunk_private_t *t_info; 2682 bcm_trunk_info_t trunk_info; 2683 bcm_trunk_member_t *member_array = NULL; 2684 int member_count = 0, unused_count; 2685 int rv = BCM_E_NONE; 2686 2687 TRUNK_INIT(unit); 2688 TRUNK_CHECK(unit, tid); 2689 2690 t_info = &TRUNK_INFO(unit, tid); 2691 2692 if (t_info->tid == BCM_TRUNK_INVALID) { 2693 return BCM_E_NOT_FOUND; 2694 } 2695 if (psc <= 0) { 2696 if (!SOC_IS_TOMAHAWK3(unit)) { 2697 psc = BCM_TRUNK_PSC_DEFAULT; 2698 } else { 2699 psc = BCM_TRUNK_PSC_PORTFLOW; 2700 } 2701 } 2702 if (t_info->psc == psc) { 2703 return BCM_E_NONE; 2704 } 2705 /* upto above is common for Legacy and TH3 */ 2706 #ifdef BCM_TOMAHAWK3_SUPPORT 2707 if (SOC_IS_TOMAHAWK3(unit)) { 2708 rv = _bcm_th3_trunk_psc_validate(unit, tid, psc); 2709 if (BCM_FAILURE(rv)) { 2710 return rv; 2711 } 2712 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, tid, &trunk_info, 0, NULL, 2713 &member_count)); 2714 } else 2715 #endif 2716 { 2717 if (!t_info->in_use) { 2718 t_info->psc = psc; 2719 return BCM_E_NONE; 2720 } 2721 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, tid, &trunk_info, 0, NULL, 2722 &member_count)); 2723 2724 /* If the new psc is one of the dynamic load balancing modes, but the old 2725 * psc is not, then return BCM_E_PARAM, since dynamic_size and dynamic_age 2726 * parameters are not available when calling bcm_trunk_set. 2727 */ 2728 if ((psc == BCM_TRUNK_PSC_DYNAMIC) || 2729 (psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) || 2730 (psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) { 2731 if ((trunk_info.psc != BCM_TRUNK_PSC_DYNAMIC) && 2732 (trunk_info.psc != BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) && 2733 (trunk_info.psc != BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) { 2734 return BCM_E_PARAM; 2735 } 2736 } 2737 2738 /* If the new psc is the resilient hashing mode, but the old 2739 * psc is not, then return BCM_E_PARAM, since the dynamic_size 2740 * parameter is not available when calling bcm_trunk_set. 2741 */ 2742 if (psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 2743 if (trunk_info.psc != BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 2744 return BCM_E_PARAM; 2745 } 2746 } 2747 } 2748 2749 if (member_count > 0) { 2750 member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count, 2751 "trunk member array"); 2752 if (NULL == member_array) { 2753 return BCM_E_MEMORY; 2754 } 2755 rv = bcm_esw_trunk_get(unit, tid, &trunk_info, member_count, 2756 member_array, &unused_count); 2757 if (BCM_FAILURE(rv)) { 2758 sal_free(member_array); 2759 return rv; 2760 } 2761 } 2762 trunk_info.psc = psc; 2763 trunk_info.flags = 0; /* Don't change failover config */ 2764 rv = _bcm_esw_trunk_set(unit, tid, &trunk_info, member_count, member_array); 2765 if (NULL != member_array) { 2766 sal_free(member_array); 2767 } 2768 return rv; 2769 } 2770 2771 /* 2772 * Function: 2773 * bcm_trunk_set 2774 * Purpose: 2775 * Adds ports to a trunk group. 2776 * Parameters: 2777 * unit - StrataSwitch PCI device unit number (driver internal). 2778 * tid - The trunk ID to be affected. 2779 * trunk_info - Information on the trunk group. 2780 * member_count - Number of trunk members. 2781 * member_array - Array of trunk members. 2782 * Returns: 2783 * BCM_E_NONE Success. 2784 * BCM_E_XXX 2785 * Notes: 2786 * The existing ports in the trunk group will be replaced with new ones. 2787 */ 2788 int 2789 bcm_esw_trunk_set(int unit, bcm_trunk_t tid, bcm_trunk_info_t *trunk_info, 2790 int member_count, bcm_trunk_member_t *member_array) 2791 { 2792 int rv; 2793 #ifdef BCM_TOMAHAWK3_SUPPORT 2794 if (SOC_IS_TOMAHAWK3(unit)) { 2795 if (trunk_info->psc < 0) { 2796 trunk_info->psc = BCM_TRUNK_PSC_PORTFLOW; 2797 } 2798 rv = _bcm_th3_trunk_psc_validate(unit, tid, trunk_info->psc); 2799 if (BCM_FAILURE(rv)) { 2800 return rv; 2801 } 2802 } 2803 #endif 2804 rv = _bcm_esw_trunk_set(unit, tid, trunk_info, 2805 member_count, member_array); 2806 return rv; 2807 } 2808 2809 /* 2810 * Function: 2811 * bcm_esw_trunk_destroy 2812 * Purpose: 2813 * Removes a trunk group. 2814 * Parameters: 2815 * unit - StrataSwitch PCI device unit number (driver internal). 2816 * tid - Trunk Id. 2817 * Returns: 2818 * BCM_E_NONE Success. 2819 * BCM_E_XXX 2820 */ 2821 2822 int 2823 bcm_esw_trunk_destroy(int unit, bcm_trunk_t tid) 2824 { 2825 trunk_private_t *t_info; 2826 int rv = BCM_E_NONE; 2827 int tid_is_vp_lag; 2828 bcm_trunk_chip_info_t chip_info; 2829 2830 TRUNK_INIT(unit); 2831 2832 BCM_IF_ERROR_RETURN 2833 (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 2834 if (tid_is_vp_lag) { 2835 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 2836 if (soc_feature(unit, soc_feature_vp_lag)) { 2837 VPLAG_LOCK(unit); 2838 rv = bcm_td2_vp_lag_destroy(unit, tid); 2839 VPLAG_UNLOCK(unit); 2840 return rv; 2841 } else 2842 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 2843 { 2844 return BCM_E_PARAM; 2845 } 2846 } 2847 2848 TRUNK_CHECK(unit, tid); 2849 2850 t_info = &TRUNK_INFO(unit, tid); 2851 2852 if (t_info->tid == BCM_TRUNK_INVALID) { 2853 return (BCM_E_NOT_FOUND); 2854 } 2855 2856 TRUNK_LOCK(unit); 2857 2858 if (t_info->in_use) { 2859 rv = mbcm_driver[unit]->mbcm_trunk_destroy(unit, tid, t_info); 2860 } else { 2861 /* Trunk ID is valid but there are no members. 2862 * Need to clear resilient hashing state in hardware. 2863 */ 2864 rv = bcm_esw_trunk_chip_info_get(unit, &chip_info); 2865 if (BCM_FAILURE(rv)) { 2866 TRUNK_UNLOCK(unit); 2867 return rv; 2868 } 2869 if (chip_info.trunk_fabric_id_min >= 0 && 2870 tid >= chip_info.trunk_fabric_id_min) { 2871 #ifdef BCM_TRIDENT2_SUPPORT 2872 int hgtid; 2873 hgtid = tid - chip_info.trunk_fabric_id_min; 2874 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 2875 /* Clear Higig resilient hashing configuration */ 2876 rv = bcm_td2_hg_rh_free_resource(unit, hgtid); 2877 } 2878 #endif /* BCM_TRIDENT2_SUPPORT */ 2879 } else { 2880 #ifdef BCM_TRIDENT2_SUPPORT 2881 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 2882 /* Clear LAG resilient hashing configuration */ 2883 rv = bcm_td2_lag_rh_free_resource(unit, tid); 2884 } 2885 #endif /* BCM_TRIDENT2_SUPPORT */ 2886 } 2887 if (BCM_FAILURE(rv)) { 2888 TRUNK_UNLOCK(unit); 2889 return rv; 2890 } 2891 } 2892 2893 #ifdef BCM_APACHE_SUPPORT 2894 if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) { 2895 if (t_info->rr_lag_select != -1) { 2896 SHR_BITCLR(TRUNK_CNTL(unit).fp_rr_lag_bmp, t_info->rr_lag_select); 2897 t_info->rr_lag_select = -1; 2898 } 2899 } 2900 #endif /* BCM_APACHE_SUPPORT */ 2901 2902 t_info->tid = BCM_TRUNK_INVALID; 2903 t_info->in_use = FALSE; 2904 t_info->psc = BCM_TRUNK_PSC_DEFAULT; 2905 t_info->ipmc_psc = 0; 2906 t_info->rtag = 0; 2907 t_info->flags = 0; 2908 t_info->dlf_index_spec = -1; 2909 t_info->dlf_index_used = -1; 2910 t_info->dlf_port_used = 0; 2911 t_info->mc_index_spec = -1; 2912 t_info->mc_index_used = -1; 2913 t_info->mc_port_used = 0; 2914 t_info->ipmc_index_spec = -1; 2915 t_info->ipmc_index_used = -1; 2916 t_info->ipmc_port_used = 0; 2917 t_info->dynamic_size = 0; 2918 t_info->dynamic_age = 0; 2919 t_info->dynamic_load_exponent = 0; 2920 t_info->dynamic_expected_load_exponent = 0; 2921 2922 #ifdef BCM_WARM_BOOT_SUPPORT 2923 SOC_CONTROL_LOCK(unit); 2924 SOC_CONTROL(unit)->scache_dirty = 1; 2925 SOC_CONTROL_UNLOCK(unit); 2926 #endif 2927 2928 TRUNK_UNLOCK(unit); 2929 2930 return rv; 2931 } 2932 2933 /* 2934 * Function: 2935 * _bcm_esw_trunk_match_multi_get 2936 * Purpose: 2937 * Get all the matches for an existing tid. 2938 * Parameters: 2939 * unit - (IN) Unit number. 2940 * tid - (IN) Trunk Id 2941 * size - (IN) Number of elements in match array 2942 * match_array - (OUT) Match array 2943 * count - (OUT) Match count 2944 * Returns: 2945 * BCM_X_XXX 2946 */ 2947 int 2948 _bcm_esw_trunk_match_multi_get( 2949 int unit, 2950 bcm_trunk_t tid, 2951 int size, 2952 bcm_port_match_info_t *match_array, 2953 int *count) 2954 { 2955 int tid_is_vp_lag; 2956 int rv = BCM_E_UNAVAIL; 2957 2958 TRUNK_INIT(unit); 2959 2960 BCM_IF_ERROR_RETURN 2961 (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 2962 if (tid_is_vp_lag) { 2963 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 2964 if (soc_feature(unit, soc_feature_vp_lag)) { 2965 VPLAG_LOCK(unit); 2966 rv = _bcm_td2_vp_lag_match_multi_get(unit, tid, size, 2967 match_array, count); 2968 VPLAG_UNLOCK(unit); 2969 return rv; 2970 } else 2971 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 2972 { 2973 return BCM_E_PARAM; 2974 } 2975 } 2976 return rv; 2977 } 2978 2979 /* 2980 * Function: 2981 * bcm_esw_trunk_get 2982 * Purpose: 2983 * Return a port information of given trunk ID. 2984 * Parameters: 2985 * unit - StrataSwitch PCI device unit number (driver internal). 2986 * tid - Trunk ID. 2987 * trunk_info - (OUT) Place to store returned trunk info. 2988 * member_max - (IN) Size of member_array. 2989 * member_array - (OUT) Place to store returned trunk members. 2990 * member_count - (OUT) Place to store returned number of trunk members. 2991 * Returns: 2992 * BCM_E_NONE Success. 2993 * BCM_E_XXX 2994 */ 2995 int 2996 bcm_esw_trunk_get(int unit, bcm_trunk_t tid, bcm_trunk_info_t *trunk_info, 2997 int member_max, bcm_trunk_member_t *member_array, int *member_count) 2998 { 2999 trunk_private_t *t_info; 3000 int rv; 3001 bcm_trunk_info_t local_trunk_info; 3002 int local_member_count; 3003 int tid_is_vp_lag; 3004 3005 TRUNK_INIT(unit); 3006 3007 BCM_IF_ERROR_RETURN 3008 (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 3009 if (tid_is_vp_lag) { 3010 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 3011 if (soc_feature(unit, soc_feature_vp_lag)) { 3012 VPLAG_LOCK(unit); 3013 rv = bcm_td2_vp_lag_get(unit, tid, trunk_info, member_max, 3014 member_array, member_count); 3015 VPLAG_UNLOCK(unit); 3016 return rv; 3017 } else 3018 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 3019 { 3020 return BCM_E_PARAM; 3021 } 3022 } 3023 3024 TRUNK_CHECK(unit, tid); 3025 3026 t_info = &TRUNK_INFO(unit, tid); 3027 3028 if (t_info->tid == BCM_TRUNK_INVALID) { 3029 return (BCM_E_NOT_FOUND); 3030 } 3031 3032 if ((member_max > 0) && (NULL == member_array)) { 3033 return BCM_E_PARAM; 3034 } 3035 3036 if ((member_max > 0) && (NULL == member_count)) { 3037 return BCM_E_PARAM; 3038 } 3039 3040 bcm_trunk_info_t_init(&local_trunk_info); 3041 3042 TRUNK_LOCK(unit); 3043 rv = mbcm_driver[unit]->mbcm_trunk_get(unit, tid, &local_trunk_info, 3044 member_max, member_array, &local_member_count, t_info); 3045 TRUNK_UNLOCK(unit); 3046 3047 if (NULL != trunk_info) { 3048 *trunk_info = local_trunk_info; 3049 } 3050 if (NULL != member_count) { 3051 *member_count = local_member_count; 3052 } 3053 3054 return rv; 3055 } 3056 3057 /* 3058 * Function: 3059 * bcm_trunk_mcast_join 3060 * Purpose: 3061 * Add the trunk group to existing MAC multicast entry. 3062 * Parameters: 3063 * unit - StrataSwitch PCI device unit number (driver internal). 3064 * tid - Trunk Id. 3065 * vid - Vlan ID. 3066 * mac - MAC address. 3067 * Returns: 3068 * BCM_E_XXX 3069 * Notes: 3070 * Applications have to remove the MAC multicast entry and re-add in with 3071 * new port bitmap to remove the trunk group from MAC multicast entry. 3072 */ 3073 3074 int 3075 bcm_esw_trunk_mcast_join(int unit, bcm_trunk_t tid, bcm_vlan_t vid, sal_mac_addr_t mac) 3076 { 3077 trunk_private_t *t_info; 3078 int rv; 3079 3080 TRUNK_INIT(unit); 3081 TRUNK_CHECK(unit, tid); 3082 3083 t_info = &TRUNK_INFO(unit, tid); 3084 if (t_info->tid == BCM_TRUNK_INVALID) { 3085 return (BCM_E_NOT_FOUND); 3086 } 3087 3088 if (!t_info->in_use) { 3089 return (BCM_E_NONE); 3090 } 3091 3092 TRUNK_LOCK(unit); 3093 rv = mbcm_driver[unit]->mbcm_trunk_mcast_join(unit, tid, vid, mac, t_info); 3094 TRUNK_UNLOCK(unit); 3095 3096 return rv; 3097 } 3098 3099 /* 3100 * Function: 3101 * bcm_trunk_bitmap_expand 3102 * Purpose: 3103 * Given a port bitmap, if any of the ports are in a trunk, 3104 * add all of the ports of that trunk to the bitmap. 3105 * Parameters: 3106 * unit - StrataSwitch PCI device unit number (driver internal). 3107 * pbmp_ptr - Input/output port bitmap 3108 * Returns: 3109 * BCM_E_NONE Success. 3110 * BCM_E_INTERNAL Chip access failure. 3111 * Notes: 3112 * Port bitmaps in the vtable and ptable must contain only one of 3113 * the trunk ports when multiple ports are aggregated in a trunk. 3114 * This is so DLF flooding, etc. goes out only one trunk port. 3115 */ 3116 3117 int 3118 bcm_esw_trunk_bitmap_expand(int unit, pbmp_t *pbmp_ptr) 3119 { 3120 int rv = BCM_E_NONE; 3121 bcm_trunk_t tid; 3122 pbmp_t tports, tpbm; 3123 3124 TRUNK_LOCK(unit); 3125 3126 #ifdef BCM_XGS_SWITCH_SUPPORT 3127 if (SOC_IS_XGS_SWITCH(unit)) { 3128 pbmp_t hg_pbmp, nonhg_pbmp; 3129 int hg_trunk = FALSE; 3130 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRX_SUPPORT) || \ 3131 defined(BCM_BRADLEY_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 3132 soc_reg_t hg_trunk_bmap; 3133 #endif 3134 pbmp_t in_pbm; 3135 int trident_trunk_arch = FALSE; 3136 3137 SOC_PBMP_ASSIGN(in_pbm, *pbmp_ptr); 3138 3139 #ifdef BCM_TRIUMPH2_SUPPORT 3140 hg_trunk_bmap = (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 3141 SOC_IS_VALKYRIE2(unit)) ? HG_TRUNK_BITMAP_64r : 3142 HG_TRUNK_BITMAPr; 3143 #else 3144 3145 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 3146 hg_trunk_bmap = HG_TRUNK_BITMAPr; 3147 #endif 3148 #endif 3149 #ifdef BCM_GREYHOUND2_SUPPORT 3150 if (SOC_IS_GREYHOUND2(unit)) { 3151 hg_trunk_bmap = HG_TRUNK_BITMAP_LOr; 3152 } 3153 #endif /* BCM_GREYHOUND2_SUPPORT */ 3154 3155 SOC_PBMP_ASSIGN(hg_pbmp, PBMP_ST_ALL(unit)); 3156 SOC_PBMP_NEGATE(nonhg_pbmp, hg_pbmp); 3157 SOC_PBMP_AND(hg_pbmp, *pbmp_ptr); 3158 SOC_PBMP_AND(nonhg_pbmp, *pbmp_ptr); 3159 if (SOC_PBMP_NOT_NULL(hg_pbmp) && SOC_PBMP_NOT_NULL(nonhg_pbmp)) { 3160 TRUNK_UNLOCK(unit); 3161 return BCM_E_PARAM; 3162 } else if (SOC_PBMP_NOT_NULL(hg_pbmp)) { 3163 hg_trunk = TRUE; 3164 } 3165 3166 if (hg_trunk && SOC_IS_FBX(unit)) { 3167 uint32 val; 3168 3169 if ((SOC_IS_FB_FX_HX(unit) || SOC_IS_RAVEN(unit)) && 3170 soc_feature(unit, soc_feature_hg_trunking)) { 3171 rv = READ_HIGIG_TRUNK_CONTROLr(unit, &val); 3172 if (rv >= 0) { 3173 SOC_PBMP_CLEAR(tports); 3174 SOC_PBMP_WORD_SET(tports, 0, soc_reg_field_get(unit, 3175 HIGIG_TRUNK_CONTROLr, val, 3176 HIGIG_TRUNK_BITMAP0f)<<24); 3177 SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr); 3178 SOC_PBMP_AND(tpbm, tports); 3179 if (SOC_PBMP_NOT_NULL(tpbm)) { 3180 SOC_PBMP_OR(*pbmp_ptr, tports); 3181 } 3182 3183 SOC_PBMP_CLEAR(tports); 3184 SOC_PBMP_WORD_SET(tports, 0, soc_reg_field_get(unit, 3185 HIGIG_TRUNK_CONTROLr, val, 3186 HIGIG_TRUNK_BITMAP1f)<<24); 3187 SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr); 3188 SOC_PBMP_AND(tpbm, tports); 3189 if (SOC_PBMP_NOT_NULL(tpbm)) { 3190 SOC_PBMP_OR(*pbmp_ptr, tports); 3191 } 3192 } 3193 } 3194 #if defined(BCM_TRIUMPH2_SUPPORT) 3195 else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 3196 SOC_IS_VALKYRIE2(unit)) { 3197 uint64 val64; 3198 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) { 3199 uint64 hg_trunk_bmap_f; 3200 rv = soc_reg_get(unit, hg_trunk_bmap, REG_PORT_ANY, tid, &val64); 3201 if (rv < 0) { 3202 break; 3203 } 3204 SOC_PBMP_CLEAR(tports); 3205 hg_trunk_bmap_f = soc_reg64_field_get(unit, 3206 hg_trunk_bmap, 3207 val64, 3208 HIGIG_TRUNK_BITMAPf); 3209 SOC_PBMP_WORD_SET(tports, 3210 0, 3211 COMPILER_64_LO(hg_trunk_bmap_f)); 3212 SOC_PBMP_WORD_SET(tports, 3213 1, 3214 COMPILER_64_HI(hg_trunk_bmap_f)); 3215 SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr); 3216 SOC_PBMP_AND(tpbm, tports); 3217 if (SOC_PBMP_NOT_NULL(tpbm)) { 3218 SOC_PBMP_OR(*pbmp_ptr, tports); 3219 } 3220 } 3221 } 3222 #endif /* BCM_TRIUMPH2_SUPPORT */ 3223 #if defined(BCM_GREYHOUND2_SUPPORT) 3224 else if (SOC_IS_GREYHOUND2(unit)) { 3225 uint64 val64; 3226 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) { 3227 uint64 hg_trunk_bmap_f; 3228 rv = soc_reg_get(unit, hg_trunk_bmap, 3229 REG_PORT_ANY, tid, &val64); 3230 if (rv < 0) { 3231 break; 3232 } 3233 SOC_PBMP_CLEAR(tports); 3234 hg_trunk_bmap_f = soc_reg64_field_get(unit, 3235 hg_trunk_bmap, 3236 val64, 3237 HIGIG_TRUNK_BITMAPf); 3238 SOC_PBMP_WORD_SET(tports, 3239 0, 3240 COMPILER_64_LO(hg_trunk_bmap_f)); 3241 SOC_PBMP_WORD_SET(tports, 3242 1, 3243 COMPILER_64_HI(hg_trunk_bmap_f)); 3244 3245 /* The maximum port number for Greyhound2 is 66 */ 3246 rv = soc_reg_get(unit, HG_TRUNK_BITMAP_HIr, 3247 REG_PORT_ANY, tid, &val64); 3248 if (rv < 0) { 3249 break; 3250 } 3251 hg_trunk_bmap_f = soc_reg64_field_get(unit, 3252 HG_TRUNK_BITMAP_HIr, 3253 val64, 3254 HIGIG_TRUNK_BITMAPf); 3255 SOC_PBMP_WORD_SET(tports, 3256 2, 3257 COMPILER_64_LO(hg_trunk_bmap_f)); 3258 3259 SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr); 3260 SOC_PBMP_AND(tpbm, tports); 3261 if (SOC_PBMP_NOT_NULL(tpbm)) { 3262 SOC_PBMP_OR(*pbmp_ptr, tports); 3263 } 3264 } 3265 } 3266 #endif /* BCM_GREYHOUND2_SUPPORT */ 3267 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 3268 else if (SOC_REG_IS_VALID(unit, hg_trunk_bmap)) { 3269 uint64 val64; 3270 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) { 3271 uint64 hg_trunk_bmap_f; 3272 rv = soc_reg_get(unit, hg_trunk_bmap, REG_PORT_ANY, tid, &val64); 3273 if (rv < 0) { 3274 break; 3275 } 3276 SOC_PBMP_CLEAR(tports); 3277 hg_trunk_bmap_f = soc_reg64_field_get(unit, 3278 hg_trunk_bmap, 3279 val64, 3280 HIGIG_TRUNK_BITMAPf); 3281 SOC_PBMP_WORD_SET(tports, 3282 0, 3283 COMPILER_64_LO(hg_trunk_bmap_f)); 3284 soc_xgs3_higig_bitmap_to_bitmap(unit, tports, &tports); 3285 SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr); 3286 SOC_PBMP_AND(tpbm, tports); 3287 if (SOC_PBMP_NOT_NULL(tpbm)) { 3288 SOC_PBMP_OR(*pbmp_ptr, tports); 3289 } 3290 } 3291 } 3292 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 3293 #ifdef BCM_TRIDENT_SUPPORT 3294 else if (soc_mem_is_valid(unit, HG_TRUNK_BITMAPm)) { 3295 hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry; 3296 3297 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) { 3298 rv = READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tid, &hg_trunk_bitmap_entry); 3299 if (SOC_FAILURE(rv)) { 3300 TRUNK_UNLOCK(unit); 3301 return (rv); 3302 } 3303 SOC_PBMP_CLEAR(tports); 3304 soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry, 3305 HIGIG_TRUNK_BITMAPf, &tports); 3306 3307 SOC_PBMP_ASSIGN(tpbm, in_pbm); 3308 SOC_PBMP_AND(tpbm, tports); 3309 if (SOC_PBMP_NOT_NULL(tpbm)) { 3310 SOC_PBMP_OR(*pbmp_ptr, tports); 3311 } 3312 } 3313 } 3314 #endif /* BCM_TRIDENT_SUPPORT */ 3315 } 3316 #if defined(BCM_TRIDENT_SUPPORT) 3317 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 3318 trident_trunk_arch = TRUE; 3319 } 3320 #endif /* BCM_TRIDENT_SUPPORT */ 3321 if (!(hg_trunk && SOC_IS_FBX(unit)) || trident_trunk_arch) { 3322 trunk_bitmap_entry_t trunk_bitmap_entry; 3323 3324 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 3325 rv = READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tid, 3326 &trunk_bitmap_entry); 3327 if (rv < 0) { 3328 break; 3329 } 3330 3331 SOC_PBMP_CLEAR(tports); 3332 3333 soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 3334 TRUNK_BITMAPf, &tports); 3335 3336 SOC_PBMP_ASSIGN(tpbm, in_pbm); 3337 SOC_PBMP_AND(tpbm, tports); 3338 if (SOC_PBMP_NOT_NULL(tpbm)) { 3339 SOC_PBMP_OR(*pbmp_ptr, tports); 3340 } 3341 } 3342 } 3343 } 3344 #endif /* BCM_XGS_SWITCH_SUPPORT */ 3345 3346 #ifdef BCM_XGS12_FABRIC_SUPPORT 3347 if (SOC_IS_XGS12_FABRIC(unit)) { 3348 uint32 val; 3349 bcm_port_t port; 3350 3351 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) { 3352 PBMP_HG_ITER(unit, port) { 3353 rv = READ_ING_HGTRUNKr(unit, port, tid, &val); 3354 break; 3355 } 3356 if (rv < 0) { 3357 break; 3358 } 3359 SOC_PBMP_CLEAR(tports); 3360 /* coverity[uninit_use_in_call : FALSE] */ 3361 SOC_PBMP_WORD_SET(tports, 0, soc_reg_field_get(unit, 3362 ING_HGTRUNKr, val, BMAPf)); 3363 SOC_PBMP_ASSIGN(tpbm, *pbmp_ptr); 3364 SOC_PBMP_AND(tpbm, tports); 3365 if (SOC_PBMP_NOT_NULL(tpbm)) { 3366 SOC_PBMP_OR(*pbmp_ptr, tports); 3367 } 3368 } 3369 } 3370 #endif /* BCM_XGS_FABRIC_SUPPORT */ 3371 3372 TRUNK_UNLOCK(unit); 3373 3374 return rv; 3375 } 3376 3377 /* 3378 * Function: 3379 * bcm_trunk_egress_set 3380 * Description: 3381 * Set switching only to indicated ports from given trunk. 3382 * Parameters: 3383 * unit - StrataSwitch PCI device unit number (driver internal). 3384 * tid - Trunk Id. Negative trunk id means set all trunks. 3385 * pbmp - bitmap of ports to allow egress. 3386 * Returns: 3387 * BCM_E_xxxx 3388 */ 3389 int 3390 bcm_esw_trunk_egress_set(int unit, bcm_trunk_t tid, bcm_pbmp_t pbmp) 3391 { 3392 trunk_egr_mask_entry_t tem_entry; 3393 bcm_trunk_t tid_min, tid_max; 3394 3395 TRUNK_INIT(unit); 3396 if (soc_feature(unit,soc_feature_trunk_egress)) { 3397 if (tid >= TRUNK_CNTL(unit).ngroups_fp) { 3398 return BCM_E_BADID; 3399 } 3400 3401 if (!SOC_IS_XGS_SWITCH(unit)) { 3402 if (BCM_PBMP_EQ(pbmp, PBMP_ALL(unit))) { 3403 return BCM_E_NONE; 3404 } else { 3405 return BCM_E_UNAVAIL; 3406 } 3407 } 3408 3409 sal_memset(&tem_entry, 0, sizeof(trunk_egr_mask_entry_t)); 3410 3411 BCM_PBMP_NEGATE(pbmp, pbmp); 3412 BCM_PBMP_AND(pbmp, PBMP_ALL(unit)); 3413 BCM_PBMP_REMOVE(pbmp, PBMP_LB(unit)); 3414 soc_mem_pbmp_field_set(unit, TRUNK_EGR_MASKm, &tem_entry, 3415 TRUNK_EGRESS_MASKf, &pbmp); 3416 3417 if (tid < 0) { 3418 tid_min = 0; 3419 tid_max = TRUNK_CNTL(unit).ngroups_fp - 1; 3420 } else if (TRUNK_INFO(unit, tid).tid == BCM_TRUNK_INVALID) { 3421 return BCM_E_NOT_FOUND; 3422 } else { 3423 tid_min = tid_max = tid; 3424 } 3425 3426 for (tid = tid_min; tid <= tid_max; tid++) { 3427 if (TRUNK_INFO(unit, tid).tid == BCM_TRUNK_INVALID) { 3428 continue; 3429 } 3430 BCM_IF_ERROR_RETURN 3431 (WRITE_TRUNK_EGR_MASKm(unit, MEM_BLOCK_ALL, tid, &tem_entry)); 3432 3433 } 3434 } else { 3435 return BCM_E_UNAVAIL; 3436 } 3437 return BCM_E_NONE; 3438 } 3439 3440 /* 3441 * Function: 3442 * bcm_trunk_egress_get 3443 * Description: 3444 * Retrieve bitmap of ports for which switching is enabled for trunk. 3445 * Parameters: 3446 * unit - StrataSwitch PCI device unit number (driver internal). 3447 * tid - Trunk Id. Negative trunk id means choose any trunk. 3448 * pbmp - (OUT) bitmap of ports where egress allowed. 3449 * Returns: 3450 * BCM_E_xxxx 3451 */ 3452 int 3453 bcm_esw_trunk_egress_get(int unit, bcm_trunk_t tid, bcm_pbmp_t *pbmp) 3454 { 3455 trunk_egr_mask_entry_t tem_entry; 3456 bcm_pbmp_t tem_pbmp; 3457 3458 TRUNK_INIT(unit); 3459 if (soc_feature(unit,soc_feature_trunk_egress)) { 3460 if (tid >= TRUNK_CNTL(unit).ngroups_fp) { 3461 return BCM_E_BADID; 3462 } 3463 3464 if (!SOC_IS_XGS_SWITCH(unit)) { 3465 BCM_PBMP_ASSIGN(*pbmp, PBMP_ALL(unit)); 3466 return BCM_E_NONE; 3467 } 3468 3469 if (tid < 0) { 3470 tid = 0; 3471 } 3472 3473 if (TRUNK_INFO(unit, tid).tid == BCM_TRUNK_INVALID) { 3474 return BCM_E_NOT_FOUND; 3475 } 3476 3477 BCM_PBMP_CLEAR(tem_pbmp); 3478 3479 BCM_IF_ERROR_RETURN 3480 (READ_TRUNK_EGR_MASKm(unit, MEM_BLOCK_ANY, tid, &tem_entry)); 3481 3482 soc_mem_pbmp_field_get(unit, TRUNK_EGR_MASKm, &tem_entry, 3483 TRUNK_EGRESS_MASKf, &tem_pbmp); 3484 3485 BCM_PBMP_ASSIGN(*pbmp, PBMP_ALL(unit)); 3486 BCM_PBMP_REMOVE(*pbmp, PBMP_LB(unit)); 3487 BCM_PBMP_XOR(*pbmp, tem_pbmp); 3488 } else{ 3489 return BCM_E_UNAVAIL; 3490 } 3491 3492 return BCM_E_NONE; 3493 } 3494 3495 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT) 3496 #define _TRUNK_OVERRIDE_CHECK(_u, _p, _tid) \ 3497 TRUNK_INIT(_u); \ 3498 if (!SOC_IS_HERCULES15(_u) && (!SOC_IS_FBX(_u) || \ 3499 !soc_feature(_u, soc_feature_hg_trunk_override))) \ 3500 { return (BCM_E_UNAVAIL); } \ 3501 if (!TRUNK_FABRIC_TID(_u, _tid)) \ 3502 { return (BCM_E_PARAM); } \ 3503 if ((_p >= 0) && !IS_PORT(_u, _p)) \ 3504 { return (BCM_E_PARAM); } 3505 #ifdef BCM_HERCULES15_SUPPORT 3506 #define _UCAST_RANGE_CHECK(_u, _id) \ 3507 if (SOC_IS_HERCULES15(_u)) { \ 3508 if ((_id < soc_mem_index_min(_u, MEM_UCm) || \ 3509 _id > soc_mem_index_max(_u, MEM_UCm))) \ 3510 { return (BCM_E_PARAM); } \ 3511 } else if (soc_mem_is_valid(_u, MODPORT_MAPm)) { \ 3512 if ((_id < soc_mem_index_min(_u, MODPORT_MAPm) || \ 3513 _id > soc_mem_index_max(_u, MODPORT_MAPm))) \ 3514 { return (BCM_E_PARAM); } \ 3515 } else if (soc_mem_is_valid(_u, MODPORT_MAP_SWm)) { \ 3516 if ((_id < soc_mem_index_min(_u, MODPORT_MAP_SWm) || \ 3517 _id > soc_mem_index_max(_u, MODPORT_MAP_SWm))) \ 3518 { return (BCM_E_PARAM); }} 3519 #define _MCAST_RANGE_CHECK(_u, _id) \ 3520 if (SOC_IS_HERCULES15(_u)) { \ 3521 if ((_id < soc_mem_index_min(_u, MEM_MCm) || \ 3522 _id > soc_mem_index_max(_u, MEM_MCm))) \ 3523 { return (BCM_E_PARAM); } \ 3524 } else { \ 3525 if ((_id < soc_mem_index_min(_u, L2MCm) || \ 3526 _id > soc_mem_index_max(_u, L2MCm))) \ 3527 { return (BCM_E_PARAM); }} 3528 #define _IPMC_RANGE_CHECK(_u, _id) \ 3529 if (SOC_IS_HERCULES15(_u)) { \ 3530 if ((_id < soc_mem_index_min(_u, MEM_IPMCm) || \ 3531 _id > soc_mem_index_max(_u, MEM_IPMCm))) \ 3532 { return (BCM_E_PARAM); } \ 3533 } else { \ 3534 if ((_id < soc_mem_index_min(_u, L3_IPMCm) || \ 3535 _id > soc_mem_index_max(_u, L3_IPMCm))) \ 3536 { return (BCM_E_PARAM); }} 3537 #define _VLAN_RANGE_CHECK(_u, _id) \ 3538 if (SOC_IS_HERCULES15(_u)) { \ 3539 if ((_id < soc_mem_index_min(_u, MEM_VIDm) || \ 3540 _id > soc_mem_index_max(_u, MEM_VIDm))) \ 3541 { return (BCM_E_PARAM); } \ 3542 } else { \ 3543 if ((_id < soc_mem_index_min(_u, VLAN_TABm) || \ 3544 _id > soc_mem_index_max(_u, VLAN_TABm))) \ 3545 { return (BCM_E_PARAM); }} 3546 #else /* BCM_HERCULES15_SUPPORT */ 3547 #define _UCAST_RANGE_CHECK(_u, _id) \ 3548 if (soc_mem_is_valid(_u, MODPORT_MAPm)) { \ 3549 if ((_id < soc_mem_index_min(_u, MODPORT_MAPm) || \ 3550 _id > soc_mem_index_max(_u, MODPORT_MAPm))) \ 3551 { return (BCM_E_PARAM); } \ 3552 } else if (soc_mem_is_valid(_u, MODPORT_MAP_SWm)) { \ 3553 if ((_id < soc_mem_index_min(_u, MODPORT_MAP_SWm) || \ 3554 _id > soc_mem_index_max(_u, MODPORT_MAP_SWm))) \ 3555 { return (BCM_E_PARAM); }} 3556 #define _MCAST_RANGE_CHECK(_u, _id) \ 3557 { \ 3558 if ((_id < soc_mem_index_min(_u, L2MCm) || \ 3559 _id > soc_mem_index_max(_u, L2MCm))) \ 3560 { return (BCM_E_PARAM); }} 3561 #define _IPMC_RANGE_CHECK(_u, _id) \ 3562 { \ 3563 if ((_id < soc_mem_index_min(_u, L3_IPMCm) || \ 3564 _id > soc_mem_index_max(_u, L3_IPMCm))) \ 3565 { return (BCM_E_PARAM); }} 3566 #define _VLAN_RANGE_CHECK(_u, _id) \ 3567 { \ 3568 if ((_id < soc_mem_index_min(_u, VLAN_TABm) || \ 3569 _id > soc_mem_index_max(_u, VLAN_TABm))) \ 3570 { return (BCM_E_PARAM); }} 3571 #endif /* BCM_HERCULES15_SUPPORT */ 3572 #endif /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */ 3573 3574 /* 3575 * Function: 3576 * bcm_trunk_override_ucast_set 3577 * Description: 3578 * Set the trunk override over UC. 3579 * Parameters: 3580 * unit - StrataSwitch PCI device unit number (driver internal). 3581 * port - Port number, -1 to all ports. 3582 * tid - Trunk id. 3583 * modid - Module id. 3584 * enable - TRUE if enabled, FALSE if disabled. 3585 * Returns: 3586 * BCM_E_xxxx 3587 */ 3588 3589 int 3590 bcm_esw_trunk_override_ucast_set(int unit, bcm_port_t port, 3591 bcm_trunk_t tid, int modid, int enable) 3592 { 3593 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT) 3594 int rv=BCM_E_NONE; 3595 3596 if (port >= 0) { 3597 if (BCM_GPORT_IS_SET(port)) { 3598 bcm_trunk_t tgid; 3599 int id; 3600 3601 BCM_IF_ERROR_RETURN( 3602 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id)); 3603 if ((-1 != id) || (-1 != tgid)){ 3604 return BCM_E_PARAM; 3605 } 3606 } else { 3607 if (!SOC_PORT_VALID(unit, port)) { 3608 return BCM_E_PORT; 3609 } 3610 } 3611 } 3612 _TRUNK_OVERRIDE_CHECK(unit, port, tid); 3613 _UCAST_RANGE_CHECK(unit, modid); 3614 3615 #ifdef BCM_HERCULES15_SUPPORT 3616 if (SOC_IS_HERCULES15(unit)) { 3617 mem_uc_entry_t uc; 3618 soc_field_t tf[] = {TRUNK0_OVER_UCf,TRUNK1_OVER_UCf, 3619 TRUNK2_OVER_UCf,TRUNK3_OVER_UCf}; 3620 int bk=-1, blk; 3621 3622 if (port >= 0) { 3623 bk = SOC_PORT_BLOCK(unit, port); 3624 } 3625 3626 soc_mem_lock(unit, MEM_UCm); 3627 SOC_MEM_BLOCK_ITER(unit, MEM_UCm, blk) { 3628 if ((port >= 0) && (bk != blk)) { 3629 continue; 3630 } 3631 rv = READ_MEM_UCm(unit, blk, modid, &uc); 3632 if (rv >= 0) { 3633 soc_MEM_UCm_field32_set(unit, &uc, 3634 tf[tid], enable ? 1: 0); 3635 rv = WRITE_MEM_UCm(unit, blk, modid, &uc); 3636 } 3637 } 3638 soc_mem_unlock(unit, MEM_UCm); 3639 } 3640 #endif /* BCM_HERCULES15_SUPPORT */ 3641 3642 #ifdef BCM_FIREBOLT_SUPPORT 3643 3644 if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 3645 (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 3646 modport_map_entry_t uc; 3647 uint32 val, hgo_bit; 3648 int i, min, max, idx, modid_count; 3649 soc_mem_t modport_map_mem; 3650 3651 modid_count = SOC_MODID_MAX(unit) + 1; 3652 if (soc_mem_is_valid(unit, MODPORT_MAP_SWm)) { 3653 modport_map_mem = MODPORT_MAP_SWm; 3654 } else { 3655 modport_map_mem = MODPORT_MAPm; 3656 } 3657 min = soc_mem_index_min(unit, modport_map_mem) / modid_count; 3658 max = soc_mem_index_max(unit, modport_map_mem) / modid_count; 3659 if (SOC_IS_HBX(unit)) { 3660 if (port >= min && port <= max) { 3661 min = max = port; 3662 } 3663 } 3664 3665 #ifdef BCM_TRIUMPH_SUPPORT 3666 if (soc_feature(unit, soc_feature_modport_map_profile)) { 3667 bcm_port_t ing_port; 3668 bcm_trunk_t hgtid; 3669 bcm_pbmp_t all_pbmp; 3670 3671 BCM_PBMP_CLEAR(all_pbmp); 3672 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 3673 #if defined(BCM_KATANA2_SUPPORT) 3674 if (soc_feature(unit, soc_feature_linkphy_coe) || 3675 soc_feature(unit, soc_feature_subtag_coe)) { 3676 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 3677 } 3678 if (SOC_IS_KATANA2(unit) && 3679 soc_feature(unit, soc_feature_flex_port)) { 3680 BCM_IF_ERROR_RETURN( 3681 _bcm_kt2_flexio_pbmp_update(unit, 3682 &all_pbmp)); 3683 } 3684 #endif 3685 3686 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp; 3687 if (port == BCM_GPORT_INVALID) { 3688 PBMP_ITER(all_pbmp, ing_port) { 3689 #ifdef BCM_TRIDENT_SUPPORT 3690 if (soc_feature(unit, 3691 soc_feature_modport_map_dest_is_port_or_trunk)) { 3692 BCM_IF_ERROR_RETURN 3693 (bcm_td_stk_trunk_override_ucast_set(unit, 3694 ing_port, hgtid, modid, enable)); 3695 } else 3696 #endif /* BCM_TRIDENT_SUPPORT */ 3697 { 3698 BCM_IF_ERROR_RETURN 3699 (_bcm_esw_tr_trunk_override_ucast_set(unit, 3700 ing_port, hgtid, modid, enable)); 3701 } 3702 } 3703 } else { 3704 #ifdef BCM_TRIDENT_SUPPORT 3705 if (soc_feature(unit, 3706 soc_feature_modport_map_dest_is_port_or_trunk)) { 3707 BCM_IF_ERROR_RETURN 3708 (bcm_td_stk_trunk_override_ucast_set(unit, 3709 port, hgtid, modid, enable)); 3710 } else 3711 #endif /* BCM_TRIDENT_SUPPORT */ 3712 { 3713 BCM_IF_ERROR_RETURN 3714 (_bcm_esw_tr_trunk_override_ucast_set(unit, 3715 port, hgtid, modid, enable)); 3716 } 3717 } 3718 } else 3719 #endif /* BCM_TRIUMPH_SUPPORT */ 3720 { 3721 soc_mem_lock(unit, MODPORT_MAPm); 3722 for (i = min; i <= max; i++) { 3723 idx = i * modid_count + modid; 3724 rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, idx, &uc); 3725 if (rv >= 0) { 3726 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp); 3727 val = soc_MODPORT_MAPm_field32_get(unit, &uc, 3728 HIGIG_TRUNK_OVERRIDEf); 3729 if (enable) { 3730 val |= hgo_bit; 3731 } else { 3732 val &= ~hgo_bit; 3733 } 3734 soc_MODPORT_MAPm_field32_set(unit, &uc, 3735 HIGIG_TRUNK_OVERRIDEf, val); 3736 rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, idx, &uc); 3737 } 3738 } 3739 soc_mem_unlock(unit, MODPORT_MAPm); 3740 } 3741 } 3742 #endif /* BCM_FIREBOLT_SUPPORT */ 3743 3744 return rv; 3745 #else 3746 return BCM_E_UNAVAIL; 3747 #endif /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */ 3748 } 3749 3750 /* 3751 * Function: 3752 * bcm_trunk_override_ucast_get 3753 * Description: 3754 * Get the trunk override over UC. 3755 * Parameters: 3756 * unit - StrataSwitch PCI device unit number (driver internal). 3757 * port - Port number. 3758 * tid - Trunk id. 3759 * modid - Module id. 3760 * enable - (OUT) TRUE if enabled, FALSE if disabled. 3761 * Returns: 3762 * BCM_E_xxxx 3763 */ 3764 3765 int 3766 bcm_esw_trunk_override_ucast_get(int unit, bcm_port_t port, 3767 bcm_trunk_t tid, int modid, int *enable) 3768 { 3769 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT) 3770 int rv=BCM_E_NONE; 3771 3772 if (BCM_GPORT_IS_SET(port)) { 3773 bcm_trunk_t tgid; 3774 int id; 3775 3776 BCM_IF_ERROR_RETURN( 3777 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id)); 3778 if ((-1 != id) || (-1 != tgid)){ 3779 return BCM_E_PARAM; 3780 } 3781 } else { 3782 if (!SOC_PORT_VALID(unit, port)) { 3783 return BCM_E_PORT; 3784 } 3785 } 3786 3787 _TRUNK_OVERRIDE_CHECK(unit, port, tid); 3788 _UCAST_RANGE_CHECK(unit, modid); 3789 3790 #ifdef BCM_HERCULES15_SUPPORT 3791 if (SOC_IS_HERCULES15(unit)) { 3792 mem_uc_entry_t uc; 3793 soc_field_t tf[] = {TRUNK0_OVER_UCf,TRUNK1_OVER_UCf, 3794 TRUNK2_OVER_UCf,TRUNK3_OVER_UCf}; 3795 int blk; 3796 3797 *enable = 0; 3798 3799 blk = SOC_PORT_BLOCK(unit, port); 3800 rv = READ_MEM_UCm(unit, blk, modid, &uc); 3801 if (rv >= 0) { 3802 *enable = soc_MEM_UCm_field32_get(unit, &uc, tf[tid]); 3803 } 3804 } 3805 #endif /* BCM_HERCULES15_SUPPORT */ 3806 3807 #ifdef BCM_FIREBOLT_SUPPORT 3808 3809 if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 3810 (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 3811 modport_map_entry_t uc; 3812 uint32 val, hgo_bit; 3813 int idx; 3814 3815 if (SOC_IS_FB_FX_HX(unit) || SOC_IS_TR_VL(unit)) { 3816 idx = modid; 3817 } else { 3818 idx = (port * (SOC_MODID_MAX(unit) + 1)) + modid; 3819 } 3820 #ifdef BCM_TRIUMPH_SUPPORT 3821 if (soc_feature(unit, soc_feature_modport_map_profile)) { 3822 bcm_trunk_t hgtid; 3823 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp; 3824 #ifdef BCM_TRIDENT_SUPPORT 3825 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 3826 rv = bcm_td_stk_trunk_override_ucast_get(unit, port, hgtid, 3827 modid, enable); 3828 } else 3829 #endif /* BCM_TRIDENT_SUPPORT */ 3830 { 3831 rv = _bcm_esw_tr_trunk_override_ucast_get(unit, port, hgtid, 3832 modid, enable); 3833 } 3834 } else 3835 #endif /* BCM_TRIUMPH_SUPPORT */ 3836 { 3837 *enable = 0; 3838 3839 rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, idx, &uc); 3840 if (rv >= 0) { 3841 val = soc_MODPORT_MAPm_field32_get(unit, &uc, 3842 HIGIG_TRUNK_OVERRIDEf); 3843 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp); 3844 *enable = (val & hgo_bit) ? 1 : 0; 3845 } 3846 } 3847 } 3848 #endif /* BCM_FIREBOLT_SUPPORT */ 3849 3850 return rv; 3851 #else 3852 return BCM_E_UNAVAIL; 3853 #endif /* BCM_HERCULES15_SUPPORT */ 3854 } 3855 3856 /* 3857 * Function: 3858 * bcm_trunk_override_mcast_set 3859 * Description: 3860 * Set the trunk override over MC. 3861 * Parameters: 3862 * unit - StrataSwitch PCI device unit number (driver internal). 3863 * port - Port number, -1 to all ports. 3864 * tid - Trunk id. 3865 * idx - MC index carried in HiGig header. 3866 * enable - TRUE if enabled, FALSE if disabled. 3867 * Returns: 3868 * BCM_E_xxxx 3869 */ 3870 3871 int 3872 bcm_esw_trunk_override_mcast_set(int unit, bcm_port_t port, 3873 bcm_trunk_t tid, int idx, int enable) 3874 { 3875 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT) 3876 int rv=BCM_E_NONE; 3877 3878 /* Translate multicast group ID's */ 3879 if (_BCM_MULTICAST_IS_L2(idx)) { 3880 idx = _BCM_MULTICAST_ID_GET(idx); 3881 } else if (_BCM_MULTICAST_IS_SET(idx)) { 3882 /* This is a non-L2 multicast group. 3883 * Redirect to the IPMC version below */ 3884 idx = _BCM_MULTICAST_ID_GET(idx); 3885 return bcm_esw_trunk_override_ipmc_set(unit, port, tid, 3886 idx, enable); 3887 } 3888 3889 if (port >= 0) { 3890 if (BCM_GPORT_IS_SET(port)) { 3891 bcm_module_t modid; 3892 bcm_trunk_t tgid; 3893 int id; 3894 3895 BCM_IF_ERROR_RETURN( 3896 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id)); 3897 if ((-1 != id) || (-1 != tgid)){ 3898 return BCM_E_PARAM; 3899 } 3900 } else { 3901 if (!SOC_PORT_VALID(unit, port)) { 3902 return BCM_E_PORT; 3903 } 3904 } 3905 } 3906 3907 _TRUNK_OVERRIDE_CHECK(unit, port, tid); 3908 _MCAST_RANGE_CHECK(unit, idx); 3909 3910 #ifdef BCM_HERCULES15_SUPPORT 3911 if (SOC_IS_HERCULES15(unit)) { 3912 mem_mc_entry_t mc; 3913 soc_field_t tf[] = {TRUNK0_OVER_MCf,TRUNK1_OVER_MCf, 3914 TRUNK2_OVER_MCf,TRUNK3_OVER_MCf}; 3915 int bk=-1, blk; 3916 3917 if (port >= 0) { 3918 bk = SOC_PORT_BLOCK(unit, port); 3919 } 3920 3921 soc_mem_lock(unit, MEM_MCm); 3922 SOC_MEM_BLOCK_ITER(unit, MEM_MCm, blk) { 3923 if ((port >= 0) && (bk != blk)) { 3924 continue; 3925 } 3926 rv = READ_MEM_MCm(unit, blk, idx, &mc); 3927 if (rv >= 0) { 3928 soc_MEM_MCm_field32_set(unit, &mc, 3929 tf[tid], enable ? 1: 0); 3930 rv = WRITE_MEM_MCm(unit, blk, idx, &mc); 3931 } 3932 } 3933 soc_mem_unlock(unit, MEM_MCm); 3934 } 3935 #endif /* BCM_HERCULES15_SUPPORT */ 3936 3937 #ifdef BCM_FIREBOLT_SUPPORT 3938 3939 3940 if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 3941 (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 3942 3943 #ifdef BCM_TRIDENT_SUPPORT 3944 if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) { 3945 bcm_trunk_t hgtid; 3946 3947 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp; 3948 rv = _bcm_trident_trunk_override_mcast_set(unit, hgtid, idx, enable); 3949 } else 3950 #endif /* BCM_TRIDENT_SUPPORT */ 3951 { 3952 l2mc_entry_t mc; 3953 uint32 val, hgo_bit; 3954 3955 soc_mem_lock(unit, L2MCm); 3956 rv = READ_L2MCm(unit, MEM_BLOCK_ANY, idx, &mc); 3957 if (rv >= 0) { 3958 val = soc_L2MCm_field32_get(unit, &mc, 3959 HIGIG_TRUNK_OVERRIDEf); 3960 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp); 3961 if (enable) { 3962 val |= hgo_bit; 3963 } else { 3964 val &= ~hgo_bit; 3965 } 3966 soc_L2MCm_field32_set(unit, &mc, 3967 HIGIG_TRUNK_OVERRIDEf, val); 3968 rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, idx, &mc); 3969 } 3970 soc_mem_unlock(unit, L2MCm); 3971 } 3972 } 3973 #endif /* BCM_FIREBOLT_SUPPORT */ 3974 3975 return rv; 3976 #else 3977 return BCM_E_UNAVAIL; 3978 #endif /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */ 3979 } 3980 3981 /* 3982 * Function: 3983 * bcm_trunk_override_mcast_get 3984 * Description: 3985 * Get the trunk override over MC. 3986 * Parameters: 3987 * unit - StrataSwitch PCI device unit number (driver internal). 3988 * port - Port number. 3989 * tid - Trunk id. 3990 * idx - MC index carried in HiGig header. 3991 * enable - (OUT) TRUE if enabled, FALSE if disabled. 3992 * Returns: 3993 * BCM_E_xxxx 3994 */ 3995 3996 int 3997 bcm_esw_trunk_override_mcast_get(int unit, bcm_port_t port, 3998 bcm_trunk_t tid, int idx, int *enable) 3999 { 4000 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT) 4001 int rv=BCM_E_NONE; 4002 4003 /* Translate multicast group ID's */ 4004 if (_BCM_MULTICAST_IS_L2(idx)) { 4005 idx = _BCM_MULTICAST_ID_GET(idx); 4006 } else if (_BCM_MULTICAST_IS_SET(idx)) { 4007 /* This is a non-L2 multicast group. 4008 * Redirect to the IPMC version below */ 4009 idx = _BCM_MULTICAST_ID_GET(idx); 4010 return bcm_esw_trunk_override_ipmc_get(unit, port, tid, 4011 idx, enable); 4012 } 4013 4014 if (BCM_GPORT_IS_SET(port)) { 4015 bcm_module_t modid; 4016 bcm_trunk_t tgid; 4017 int id; 4018 4019 BCM_IF_ERROR_RETURN( 4020 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id)); 4021 if ((-1 != id) || (-1 != tgid)){ 4022 return BCM_E_PARAM; 4023 } 4024 } else { 4025 if (!SOC_PORT_VALID(unit, port)) { 4026 return BCM_E_PORT; 4027 } 4028 } 4029 4030 _TRUNK_OVERRIDE_CHECK(unit, port, tid); 4031 _MCAST_RANGE_CHECK(unit, idx); 4032 4033 #ifdef BCM_HERCULES15_SUPPORT 4034 if (SOC_IS_HERCULES15(unit)) { 4035 mem_mc_entry_t mc; 4036 soc_field_t tf[] = {TRUNK0_OVER_MCf,TRUNK1_OVER_MCf, 4037 TRUNK2_OVER_MCf,TRUNK3_OVER_MCf}; 4038 int blk; 4039 4040 *enable = 0; 4041 4042 blk = SOC_PORT_BLOCK(unit, port); 4043 rv = READ_MEM_MCm(unit, blk, idx, &mc); 4044 if (rv >= 0) { 4045 *enable = soc_MEM_MCm_field32_get(unit, &mc, tf[tid]); 4046 } 4047 } 4048 #endif /* SOC_IS_HERCULES15 */ 4049 4050 #ifdef BCM_FIREBOLT_SUPPORT 4051 4052 if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 4053 (soc_feature(unit,soc_feature_hg_trunk_override))) { 4054 4055 #ifdef BCM_TRIDENT_SUPPORT 4056 if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) { 4057 int hgtid; 4058 4059 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp; 4060 rv = _bcm_trident_trunk_override_mcast_get(unit, hgtid, idx, enable); 4061 } else 4062 #endif /* BCM_TRIDENT_SUPPORT */ 4063 { 4064 l2mc_entry_t mc; 4065 uint32 val, hgo_bit; 4066 4067 *enable = 0; 4068 4069 rv = READ_L2MCm(unit, MEM_BLOCK_ANY, idx, &mc); 4070 if (rv >= 0) { 4071 val = soc_L2MCm_field32_get(unit, &mc, 4072 HIGIG_TRUNK_OVERRIDEf); 4073 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp); 4074 *enable = (val & hgo_bit) ? 1 : 0; 4075 } 4076 } 4077 } 4078 #endif /* BCM_FIREBOLT_SUPPORT */ 4079 4080 return rv; 4081 #else 4082 return BCM_E_UNAVAIL; 4083 #endif /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */ 4084 } 4085 4086 /* 4087 * Function: 4088 * bcm_trunk_override_ipmc_set 4089 * Description: 4090 * Set the trunk override over IPMC. 4091 * Parameters: 4092 * unit - StrataSwitch PCI device unit number (driver internal). 4093 * port - Port number, -1 to all ports. 4094 * tid - Trunk id. 4095 * idx - IPMC index carried in HiGig header. 4096 * enable - TRUE if enabled, FALSE if disabled. 4097 * Returns: 4098 * BCM_E_xxxx 4099 */ 4100 4101 int 4102 bcm_esw_trunk_override_ipmc_set(int unit, bcm_port_t port, 4103 bcm_trunk_t tid, int idx, int enable) 4104 { 4105 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT) 4106 int rv=BCM_E_NONE; 4107 4108 /* Translate multicast group ID's */ 4109 if (_BCM_MULTICAST_IS_L2(idx)) { 4110 /* This is an L2 multicast group. 4111 * Redirect to the mcast version above */ 4112 idx = _BCM_MULTICAST_ID_GET(idx); 4113 return bcm_esw_trunk_override_mcast_set(unit, port, tid, 4114 idx, enable); 4115 } else if (_BCM_MULTICAST_IS_SET(idx)) { 4116 idx = _BCM_MULTICAST_ID_GET(idx); 4117 } 4118 4119 if (!soc_feature(unit, soc_feature_ip_mcast)) { 4120 return BCM_E_UNAVAIL; 4121 } 4122 4123 if (port >= 0) { 4124 if (BCM_GPORT_IS_SET(port)) { 4125 bcm_module_t modid; 4126 bcm_trunk_t tgid; 4127 int id; 4128 4129 BCM_IF_ERROR_RETURN( 4130 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id)); 4131 if ((-1 != id) || (-1 != tgid)){ 4132 return BCM_E_PARAM; 4133 } 4134 } else { 4135 if (!SOC_PORT_VALID(unit, port)) { 4136 return BCM_E_PORT; 4137 } 4138 } 4139 } 4140 4141 _TRUNK_OVERRIDE_CHECK(unit, port, tid); 4142 _IPMC_RANGE_CHECK(unit, idx); 4143 4144 #ifdef BCM_HERCULES15_SUPPORT 4145 if (SOC_IS_HERCULES15(unit)) { 4146 mem_ipmc_entry_t ipmc; 4147 soc_field_t tf[] = {TRUNK0_OVER_IPMCf,TRUNK1_OVER_IPMCf, 4148 TRUNK2_OVER_IPMCf,TRUNK3_OVER_IPMCf}; 4149 int bk=-1, blk; 4150 4151 if (port >= 0) { 4152 bk = SOC_PORT_BLOCK(unit, port); 4153 } 4154 4155 soc_mem_lock(unit, MEM_IPMCm); 4156 SOC_MEM_BLOCK_ITER(unit, MEM_IPMCm, blk) { 4157 if ((port >= 0) && (bk != blk)) { 4158 continue; 4159 } 4160 rv = READ_MEM_IPMCm(unit, blk, idx, &ipmc); 4161 if (rv >= 0) { 4162 soc_MEM_IPMCm_field32_set(unit, &ipmc, 4163 tf[tid], enable ? 1: 0); 4164 rv = WRITE_MEM_IPMCm(unit, blk, idx, &ipmc); 4165 } 4166 } 4167 soc_mem_unlock(unit, MEM_IPMCm); 4168 } 4169 #endif /* BCM_HERCULES15_SUPPORT */ 4170 4171 #ifdef BCM_FIREBOLT_SUPPORT 4172 if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 4173 (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 4174 4175 #ifdef BCM_TRIDENT_SUPPORT 4176 if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) { 4177 bcm_trunk_t hgtid; 4178 4179 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp; 4180 rv = _bcm_trident_trunk_override_ipmc_set(unit, hgtid, idx, enable); 4181 } else 4182 #endif /* BCM_TRIDENT_SUPPORT */ 4183 { 4184 ipmc_entry_t ipmc; 4185 uint32 val, hgo_bit; 4186 4187 soc_mem_lock(unit, L3_IPMCm); 4188 rv = READ_L3_IPMCm(unit, MEM_BLOCK_ANY, idx, &ipmc); 4189 if (rv >= 0) { 4190 val = soc_L3_IPMCm_field32_get(unit, &ipmc, 4191 HIGIG_TRUNK_OVERRIDEf); 4192 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp); 4193 if (enable) { 4194 val |= hgo_bit; 4195 } else { 4196 val &= ~hgo_bit; 4197 } 4198 soc_L3_IPMCm_field32_set(unit, &ipmc, 4199 HIGIG_TRUNK_OVERRIDEf, val); 4200 rv = WRITE_L3_IPMCm(unit, MEM_BLOCK_ALL, idx, &ipmc); 4201 } 4202 soc_mem_unlock(unit, L3_IPMCm); 4203 4204 #if defined(BCM_BRADLEY_SUPPORT) 4205 if (SOC_IS_HBX(unit)) { 4206 l2mc_entry_t mc; 4207 uint32 val, hgo_bit; 4208 int mc_base, mc_size, mc_index; 4209 4210 SOC_IF_ERROR_RETURN 4211 (soc_hbx_ipmc_size_get(unit, &mc_base, &mc_size)); 4212 if (idx < 0 || idx > mc_size) { 4213 return BCM_E_PARAM; 4214 } 4215 mc_index = idx + mc_base; 4216 4217 soc_mem_lock(unit, L2MCm); 4218 rv = READ_L2MCm(unit, MEM_BLOCK_ANY, mc_index, &mc); 4219 if (rv >= 0) { 4220 val = soc_L2MCm_field32_get(unit, &mc, 4221 HIGIG_TRUNK_OVERRIDEf); 4222 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp); 4223 if (enable) { 4224 val |= hgo_bit; 4225 } else { 4226 val &= ~hgo_bit; 4227 } 4228 soc_L2MCm_field32_set(unit, &mc, 4229 HIGIG_TRUNK_OVERRIDEf, val); 4230 rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, mc_index, &mc); 4231 } 4232 soc_mem_unlock(unit, L2MCm); 4233 4234 4235 } 4236 #endif /* BCM_BRADLEY_SUPPORT */ 4237 } 4238 } 4239 #endif /* BCM_FIREBOLT_SUPPORT */ 4240 4241 return rv; 4242 #else 4243 return BCM_E_UNAVAIL; 4244 #endif /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */ 4245 } 4246 4247 /* 4248 * Function: 4249 * bcm_trunk_override_ipmc_get 4250 * Description: 4251 * Get the trunk override over IPMC. 4252 * Parameters: 4253 * unit - StrataSwitch PCI device unit number (driver internal). 4254 * port - Port number. 4255 * tid - Trunk id. 4256 * idx - IPMC index carried in HiGig header. 4257 * enable - (OUT) TRUE if enabled, FALSE if disabled. 4258 * Returns: 4259 * BCM_E_xxxx 4260 */ 4261 4262 int 4263 bcm_esw_trunk_override_ipmc_get(int unit, bcm_port_t port, 4264 bcm_trunk_t tid, int idx, int *enable) 4265 { 4266 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT) 4267 int rv=BCM_E_NONE; 4268 4269 /* Translate multicast group ID's */ 4270 if (_BCM_MULTICAST_IS_L2(idx)) { 4271 /* This is an L2 multicast group. 4272 * Redirect to the mcast version above */ 4273 idx = _BCM_MULTICAST_ID_GET(idx); 4274 return bcm_esw_trunk_override_mcast_get(unit, port, tid, 4275 idx, enable); 4276 } else if (_BCM_MULTICAST_IS_SET(idx)) { 4277 idx = _BCM_MULTICAST_ID_GET(idx); 4278 } 4279 4280 if (!soc_feature(unit, soc_feature_ip_mcast)) { 4281 return BCM_E_UNAVAIL; 4282 } 4283 4284 if (BCM_GPORT_IS_SET(port)) { 4285 bcm_module_t modid; 4286 bcm_trunk_t tgid; 4287 int id; 4288 4289 BCM_IF_ERROR_RETURN( 4290 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id)); 4291 if ((-1 != id) || (-1 != tgid)){ 4292 return BCM_E_PARAM; 4293 } 4294 } else { 4295 if (!SOC_PORT_VALID(unit, port)) { 4296 return BCM_E_PORT; 4297 } 4298 } 4299 4300 _TRUNK_OVERRIDE_CHECK(unit, port, tid); 4301 _IPMC_RANGE_CHECK(unit, idx); 4302 4303 #ifdef BCM_HERCULES15_SUPPORT 4304 if (SOC_IS_HERCULES15(unit)) { 4305 mem_ipmc_entry_t ipmc; 4306 soc_field_t tf[] = {TRUNK0_OVER_IPMCf,TRUNK1_OVER_IPMCf, 4307 TRUNK2_OVER_IPMCf,TRUNK3_OVER_IPMCf}; 4308 int blk; 4309 4310 *enable = 0; 4311 4312 blk = SOC_PORT_BLOCK(unit, port); 4313 rv = READ_MEM_IPMCm(unit, blk, idx, &ipmc); 4314 if (rv >= 0) { 4315 *enable = soc_MEM_IPMCm_field32_get(unit, &ipmc, tf[tid]); 4316 } 4317 } 4318 #endif /* BCM_HERCULES15_SUPPORT */ 4319 4320 #ifdef BCM_FIREBOLT_SUPPORT 4321 4322 if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 4323 (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 4324 4325 #ifdef BCM_TRIDENT_SUPPORT 4326 if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) { 4327 bcm_trunk_t hgtid; 4328 4329 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp; 4330 rv = _bcm_trident_trunk_override_ipmc_get(unit, hgtid, idx, enable); 4331 } else 4332 #endif /* BCM_TRIDENT_SUPPORT */ 4333 { 4334 ipmc_entry_t ipmc; 4335 uint32 val, hgo_bit; 4336 4337 *enable = 0; 4338 4339 rv = READ_L3_IPMCm(unit, MEM_BLOCK_ANY, idx, &ipmc); 4340 if (rv >= 0) { 4341 val = soc_L3_IPMCm_field32_get(unit, &ipmc, 4342 HIGIG_TRUNK_OVERRIDEf); 4343 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp); 4344 *enable = (val & hgo_bit) ? 1 : 0; 4345 } 4346 } 4347 } 4348 #endif /* BCM_FIREBOLT_SUPPORT */ 4349 4350 return rv; 4351 #else 4352 return BCM_E_UNAVAIL; 4353 #endif /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */ 4354 } 4355 4356 /* 4357 * Function: 4358 * bcm_trunk_override_vlan_set 4359 * Description: 4360 * Set the trunk override over VLAN. 4361 * Parameters: 4362 * unit - StrataSwitch PCI device unit number (driver internal). 4363 * port - Port number, -1 to all ports. 4364 * tid - Trunk id. 4365 * vid - VLAN id. 4366 * enable - TRUE if enabled, FALSE if disabled. 4367 * Returns: 4368 * BCM_E_xxxx 4369 */ 4370 4371 int 4372 bcm_esw_trunk_override_vlan_set(int unit, bcm_port_t port, 4373 bcm_trunk_t tid, bcm_vlan_t vid, int enable) 4374 { 4375 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT) 4376 int rv=BCM_E_NONE; 4377 4378 if (port >= 0) { 4379 if (BCM_GPORT_IS_SET(port)) { 4380 bcm_module_t modid; 4381 bcm_trunk_t tgid; 4382 int id; 4383 4384 BCM_IF_ERROR_RETURN( 4385 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id)); 4386 if ((-1 != id) || (-1 != tgid)){ 4387 return BCM_E_PARAM; 4388 } 4389 } else { 4390 if (!SOC_PORT_VALID(unit, port)) { 4391 return BCM_E_PORT; 4392 } 4393 } 4394 } 4395 4396 _TRUNK_OVERRIDE_CHECK(unit, port, tid); 4397 _VLAN_RANGE_CHECK(unit, vid); 4398 4399 #ifdef BCM_HERCULES15_SUPPORT 4400 if (SOC_IS_HERCULES15(unit)) { 4401 mem_vid_entry_t ve; 4402 soc_field_t tf[] = {TRUNK0_OVER_VIDf,TRUNK1_OVER_VIDf, 4403 TRUNK2_OVER_VIDf,TRUNK3_OVER_VIDf}; 4404 int blk, bk = -1; 4405 4406 if (port >= 0) { 4407 bk = SOC_PORT_BLOCK(unit, port); 4408 } 4409 4410 soc_mem_lock(unit, MEM_VIDm); 4411 SOC_MEM_BLOCK_ITER(unit, MEM_VIDm, blk) { 4412 if ((port >= 0) && (bk != blk)) { 4413 continue; 4414 } 4415 rv = READ_MEM_VIDm(unit, blk, vid, &ve); 4416 if (rv >= 0) { 4417 soc_MEM_VIDm_field32_set(unit, &ve, 4418 tf[tid], enable ? 1: 0); 4419 rv = WRITE_MEM_VIDm(unit, blk, vid, &ve); 4420 } 4421 } 4422 soc_mem_unlock(unit, MEM_VIDm); 4423 } 4424 #endif /* BCM_HERCULES15_SUPPORT */ 4425 4426 #ifdef BCM_FIREBOLT_SUPPORT 4427 4428 if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 4429 (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 4430 4431 #ifdef BCM_TRIDENT_SUPPORT 4432 if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) { 4433 bcm_trunk_t hgtid; 4434 4435 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp; 4436 rv = _bcm_trident_trunk_override_vlan_set(unit, hgtid, vid, enable); 4437 } else 4438 #endif /* BCM_TRIDENT_SUPPORT */ 4439 { 4440 vlan_tab_entry_t ve; 4441 uint32 val, hgo_bit; 4442 4443 soc_mem_lock(unit, VLAN_TABm); 4444 rv = READ_VLAN_TABm(unit, MEM_BLOCK_ANY, vid, &ve); 4445 if (rv >= 0) { 4446 val = soc_VLAN_TABm_field32_get(unit, &ve, 4447 HIGIG_TRUNK_OVERRIDEf); 4448 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp); 4449 if (enable) { 4450 val |= hgo_bit; 4451 } else { 4452 val &= ~hgo_bit; 4453 } 4454 soc_VLAN_TABm_field32_set(unit, &ve, 4455 HIGIG_TRUNK_OVERRIDEf, val); 4456 rv = WRITE_VLAN_TABm(unit, MEM_BLOCK_ALL, vid, &ve); 4457 } 4458 soc_mem_unlock(unit, VLAN_TABm); 4459 } 4460 } 4461 #endif /* BCM_FIREBOLT_SUPPORT */ 4462 4463 return rv; 4464 #else 4465 return BCM_E_UNAVAIL; 4466 #endif /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */ 4467 } 4468 4469 /* 4470 * Function: 4471 * bcm_trunk_override_vlan_get 4472 * Description: 4473 * Get the trunk override over VLAN. 4474 * Parameters: 4475 * unit - StrataSwitch PCI device unit number (driver internal). 4476 * port - Port number. 4477 * tid - Trunk id. 4478 * vid - VLAN id. 4479 * enable - (OUT) TRUE if enabled, FALSE if disabled. 4480 * Returns: 4481 * BCM_E_xxxx 4482 */ 4483 4484 int 4485 bcm_esw_trunk_override_vlan_get(int unit, bcm_port_t port, 4486 bcm_trunk_t tid, bcm_vlan_t vid, int *enable) 4487 { 4488 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_FIREBOLT_SUPPORT) 4489 int rv=BCM_E_NONE; 4490 4491 if (BCM_GPORT_IS_SET(port)) { 4492 bcm_module_t modid; 4493 bcm_trunk_t tgid; 4494 int id; 4495 4496 BCM_IF_ERROR_RETURN( 4497 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id)); 4498 if ((-1 != id) || (-1 != tgid)){ 4499 return BCM_E_PARAM; 4500 } 4501 } else { 4502 if (!SOC_PORT_VALID(unit, port)) { 4503 return BCM_E_PORT; 4504 } 4505 } 4506 4507 _TRUNK_OVERRIDE_CHECK(unit, port, tid); 4508 _VLAN_RANGE_CHECK(unit, vid); 4509 4510 #ifdef BCM_HERCULES15_SUPPORT 4511 if (SOC_IS_HERCULES15(unit)) { 4512 mem_vid_entry_t ve; 4513 soc_field_t tf[] = {TRUNK0_OVER_VIDf,TRUNK1_OVER_VIDf, 4514 TRUNK2_OVER_VIDf,TRUNK3_OVER_VIDf}; 4515 int blk; 4516 4517 *enable = 0; 4518 4519 blk = SOC_PORT_BLOCK(unit, port); 4520 rv = READ_MEM_VIDm(unit, blk, vid, &ve); 4521 if (rv >= 0) { 4522 *enable = soc_MEM_VIDm_field32_get(unit, &ve, tf[tid]); 4523 } 4524 } 4525 #endif /* BCM_HERCULES15_SUPPORT */ 4526 4527 #ifdef BCM_FIREBOLT_SUPPORT 4528 4529 if ((SOC_IS_FBX(unit) || SOC_IS_RAVEN(unit)) && 4530 (soc_feature(unit,soc_feature_hg_trunk_override)) ) { 4531 4532 #ifdef BCM_TRIDENT_SUPPORT 4533 if (soc_feature(unit, soc_feature_hg_trunk_override_profile)) { 4534 bcm_trunk_t hgtid; 4535 4536 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp; 4537 rv = _bcm_trident_trunk_override_vlan_get(unit, hgtid, vid, enable); 4538 } else 4539 #endif /* BCM_TRIDENT_SUPPORT */ 4540 { 4541 vlan_tab_entry_t ve; 4542 uint32 val, hgo_bit; 4543 4544 *enable = 0; 4545 4546 rv = READ_VLAN_TABm(unit, MEM_BLOCK_ANY, vid, &ve); 4547 if (rv >= 0) { 4548 val = soc_VLAN_TABm_field32_get(unit, &ve, 4549 HIGIG_TRUNK_OVERRIDEf); 4550 hgo_bit = 1 << (tid - TRUNK_CNTL(unit).ngroups_fp); 4551 *enable = (val & hgo_bit) ? 1 : 0; 4552 } 4553 } 4554 } 4555 #endif /* BCM_FIREBOLT_SUPPORT */ 4556 4557 return rv; 4558 #else 4559 return BCM_E_UNAVAIL; 4560 #endif /* BCM_HERCULES15_SUPPORT || BCM_FIREBOLT_SUPPORT */ 4561 } 4562 4563 /* 4564 * Function: 4565 * bcm_trunk_pool_set 4566 * Description: 4567 * Set trunk pool table that contains the egress port number 4568 * indexed by the hash value. 4569 * Parameters: 4570 * unit - StrataSwitch PCI device unit number (driver internal). 4571 * port - Port number, -1 to all ports. 4572 * tid - Trunk id. 4573 * size - Trunk pool size. 4574 * weights - Weights for each port, all 0 means weighted fair. 4575 * Returns: 4576 * BCM_E_xxxx 4577 */ 4578 4579 int 4580 bcm_esw_trunk_pool_set(int unit, bcm_port_t port, bcm_trunk_t tid, 4581 int size, const int weights[BCM_TRUNK_MAX_PORTCNT]) 4582 { 4583 #ifdef BCM_HERCULES15_SUPPORT 4584 uint32 val; 4585 int idx_min, idx_max, weighted, p, idx; 4586 mem_trunk_port_pool_entry_t trk_pool; 4587 trunk_private_t *t_info; 4588 bcm_trunk_member_t member_array[BCM_TRUNK_FABRIC_MAX_PORTCNT]; 4589 int member_count; 4590 bcm_port_t tp[BCM_TRUNK_FABRIC_MAX_PORTCNT]; 4591 soc_field_t pf[] = {PORT_NO_0f, PORT_NO_1f, PORT_NO_2f, PORT_NO_3f}; 4592 int token[BCM_TRUNK_MAX_PORTCNT], index; 4593 int i, reset=0, blk, rv=BCM_E_NONE, lp=0; 4594 4595 if (!SOC_IS_HERCULES15(unit)) { 4596 return BCM_E_UNAVAIL; 4597 } 4598 4599 if (port >= 0) { 4600 if (BCM_GPORT_IS_SET(port)) { 4601 bcm_trunk_t tgid; 4602 bcm_module_t modid; 4603 int id; 4604 4605 BCM_IF_ERROR_RETURN( 4606 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id)); 4607 if ((-1 != id) || (-1 != tgid)){ 4608 return BCM_E_PARAM; 4609 } 4610 } else { 4611 if (!SOC_PORT_VALID(unit, port) || !IS_HG_PORT(unit, port) ) { 4612 return BCM_E_PORT; 4613 } 4614 } 4615 } 4616 4617 TRUNK_INIT(unit); 4618 TRUNK_CHECK(unit, tid); 4619 t_info = &TRUNK_INFO(unit, tid); 4620 if (t_info->tid == BCM_TRUNK_INVALID) { 4621 return BCM_E_NOT_FOUND; 4622 } 4623 4624 idx_min = soc_mem_index_min(unit, MEM_TRUNK_PORT_POOLm); 4625 idx_max = soc_mem_index_max(unit, MEM_TRUNK_PORT_POOLm); 4626 if ((size < idx_min) || (size > idx_max)) { 4627 return BCM_E_PARAM; 4628 } 4629 if (size == 0) { 4630 index = size = idx_max; 4631 } else { 4632 index = size - 1; 4633 } 4634 4635 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, tid, NULL, 4636 BCM_TRUNK_FABRIC_MAX_PORTCNT, member_array, &member_count)); 4637 if (member_count <= 0) { 4638 return BCM_E_NOT_FOUND; 4639 } 4640 4641 for (i=0; i < member_count; i++) { 4642 BCM_IF_ERROR_RETURN 4643 (bcm_esw_port_local_get(unit, member_array[i].gport, &tp[i])); 4644 lp |= weights[tp[i]-1]; 4645 if ((lp & ~0x3f) != 0) { 4646 return BCM_E_PARAM; 4647 } 4648 } 4649 weighted = (lp) ? 1 : 0; 4650 4651 soc_mem_lock(unit, MEM_TRUNK_PORT_POOLm); 4652 PBMP_PORT_ITER(unit, p) { 4653 if ((port >= 0) && (p != port)) { 4654 continue; 4655 } 4656 4657 if ((rv = READ_ING_HGTRUNKr(unit, p, tid, &val)) >= 0) { 4658 soc_reg_field_set(unit, ING_HGTRUNKr, &val, 4659 TRUNK_POOL_SIZEf, size); 4660 rv = WRITE_ING_HGTRUNKr(unit, p, tid, val); 4661 } 4662 if (rv < 0) { 4663 break; 4664 } 4665 4666 if (weighted) { 4667 for (i = 0; i < member_count; i++) { 4668 token[tp[i]-1] = weights[tp[i]-1]; 4669 } 4670 } 4671 4672 idx = index; 4673 blk = SOC_PORT_BLOCK(unit, p); 4674 4675 while (idx >= 0) { 4676 if (weighted) { 4677 for (i = 0; i < member_count; i++) { 4678 if (token[tp[i]-1]) { 4679 reset = 0; 4680 break; 4681 } 4682 reset = 1; 4683 } 4684 if (reset) { 4685 for (i = 0; i < member_count; i++) { 4686 token[tp[i]-1] = weights[tp[i]-1]; 4687 } 4688 } 4689 } 4690 for (i = 0; i < member_count; i++) { 4691 if (idx < 0) break; 4692 sal_memset(&trk_pool, 0, sizeof(trk_pool)); 4693 if (weighted) { 4694 if (token[tp[i]-1]) { 4695 if ((rv = READ_MEM_TRUNK_PORT_POOLm(unit, blk, index-idx, &trk_pool)) >= 0) { 4696 soc_MEM_TRUNK_PORT_POOLm_field32_set(unit, &trk_pool, pf[tid], tp[i]); 4697 rv = WRITE_MEM_TRUNK_PORT_POOLm(unit, blk, index-idx, &trk_pool); 4698 } 4699 token[tp[i]-1]--; 4700 idx--; 4701 } else { 4702 continue; 4703 } 4704 } else { 4705 if ((rv = READ_MEM_TRUNK_PORT_POOLm(unit, blk, index-idx, &trk_pool)) >= 0) { 4706 soc_MEM_TRUNK_PORT_POOLm_field32_set(unit, &trk_pool, pf[tid], tp[i]); 4707 rv = WRITE_MEM_TRUNK_PORT_POOLm(unit, blk, index-idx, &trk_pool); 4708 } 4709 idx--; 4710 } 4711 } 4712 } 4713 } 4714 soc_mem_unlock(unit, MEM_TRUNK_PORT_POOLm); 4715 4716 return rv; 4717 #else 4718 return BCM_E_UNAVAIL; 4719 #endif /* BCM_HERCULES15_SUPPORT */ 4720 } 4721 4722 /* 4723 * Function: 4724 * bcm_trunk_pool_get 4725 * Description: 4726 * Get trunk pool table that contains the egress port number 4727 * indexed by the hash value. 4728 * Parameters: 4729 * unit - StrataSwitch PCI device unit number (driver internal). 4730 * port - Port number. 4731 * tid - Trunk id. 4732 * size - (OUT) Trunk pool size. 4733 * weights - (OUT) Weights (total count) for each port. 4734 * Returns: 4735 * BCM_E_xxxx 4736 */ 4737 4738 int 4739 bcm_esw_trunk_pool_get(int unit, bcm_port_t port, bcm_trunk_t tid, 4740 int *size, int weights[BCM_TRUNK_MAX_PORTCNT]) 4741 { 4742 #ifdef BCM_HERCULES15_SUPPORT 4743 uint32 val; 4744 mem_trunk_port_pool_entry_t trk_pool; 4745 trunk_private_t *t_info; 4746 bcm_trunk_member_t member_array[BCM_TRUNK_FABRIC_MAX_PORTCNT]; 4747 int member_count; 4748 bcm_port_t tp[BCM_TRUNK_FABRIC_MAX_PORTCNT]; 4749 soc_field_t pf[] = {PORT_NO_0f, PORT_NO_1f, PORT_NO_2f, PORT_NO_3f}; 4750 int i,pool, idx, blk, pool_port, rv=BCM_E_NONE; 4751 4752 if (!SOC_IS_HERCULES15(unit)) { 4753 return BCM_E_UNAVAIL; 4754 } 4755 4756 if (BCM_GPORT_IS_SET(port)) { 4757 bcm_trunk_t tgid; 4758 bcm_module_t modid; 4759 int id; 4760 4761 BCM_IF_ERROR_RETURN( 4762 _bcm_esw_gport_resolve(unit, port, &modid, &port, &tgid, &id)); 4763 if ((-1 != id) || (-1 != tgid)){ 4764 return BCM_E_PARAM; 4765 } 4766 } else { 4767 if (!SOC_PORT_VALID(unit, port) || !IS_HG_PORT(unit, port) ) { 4768 return BCM_E_PORT; 4769 } 4770 } 4771 4772 TRUNK_INIT(unit); 4773 TRUNK_CHECK(unit, tid); 4774 t_info = &TRUNK_INFO(unit, tid); 4775 if (t_info->tid == BCM_TRUNK_INVALID) { 4776 return BCM_E_NOT_FOUND; 4777 } 4778 4779 *size = 0; 4780 for (idx=0; idx < BCM_TRUNK_MAX_PORTCNT; idx++) { 4781 weights[idx] = 0; 4782 } 4783 4784 SOC_IF_ERROR_RETURN(READ_ING_HGTRUNKr(unit, port, tid, &val)); 4785 *size = soc_reg_field_get(unit, ING_HGTRUNKr, val, TRUNK_POOL_SIZEf); 4786 if (*size == 0) { /* HW meaning, we never program 0 above in _set */ 4787 *size = 1; 4788 } 4789 4790 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, tid, NULL, 4791 BCM_TRUNK_FABRIC_MAX_PORTCNT, member_array, &member_count)); 4792 for (i=0; i < member_count; i++) { 4793 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, 4794 member_array[i].gport, &tp[i])); 4795 } 4796 4797 blk = SOC_PORT_BLOCK(unit, port); 4798 pool = *size; 4799 for (idx = 0; idx < pool; idx++) { 4800 if ((rv = READ_MEM_TRUNK_PORT_POOLm(unit, blk, idx, &trk_pool)) >= 0) { 4801 pool_port = soc_MEM_TRUNK_PORT_POOLm_field32_get(unit, &trk_pool, pf[tid]); 4802 for (i=0; i < member_count; i++) { 4803 if (pool_port == tp[i]) { 4804 weights[tp[i]-1]++; 4805 break; 4806 } 4807 } 4808 } 4809 } 4810 4811 return rv; 4812 #else 4813 return BCM_E_UNAVAIL; 4814 #endif /* BCM_HERCULES15_SUPPORT */ 4815 } 4816 4817 int _bcm_nuc_tpbm_get(int unit, 4818 int num_ports, 4819 bcm_module_t *tm, 4820 uint32 *nuc_tpbm) 4821 { 4822 int i, mod = -1; 4823 uint32 mod_type; 4824 int all_equal = 1; 4825 uint32 xgs12_tpbm = 0; 4826 uint32 xgs3_tpbm = 0; 4827 uint32 unknown_tpbm = 0; 4828 4829 *nuc_tpbm = 0x1; 4830 for (i = 0; i < num_ports; i++) { 4831 if (i == 0) { 4832 mod = tm[i]; 4833 } else if (mod != tm[i]) { 4834 all_equal = 0; 4835 } 4836 BCM_IF_ERROR_RETURN 4837 (_bcm_switch_module_type_get(unit, tm[i], &mod_type)); 4838 switch(mod_type) { 4839 case BCM_SWITCH_MODULE_XGS1 : 4840 case BCM_SWITCH_MODULE_XGS2 : xgs12_tpbm |= (1 << i); break; 4841 case BCM_SWITCH_MODULE_XGS3 : xgs3_tpbm |= (1 << i); break; 4842 case BCM_SWITCH_MODULE_UNKNOWN: 4843 default : unknown_tpbm |= (1 << i); break; 4844 } 4845 } 4846 if (all_equal) { 4847 *nuc_tpbm = ((0x1 << num_ports) - 1); 4848 } else if (unknown_tpbm || xgs12_tpbm) { 4849 *nuc_tpbm = 0x1; 4850 } else if (xgs3_tpbm) { 4851 *nuc_tpbm = xgs3_tpbm; 4852 } 4853 4854 return(BCM_E_NONE); 4855 } 4856 4857 /* 4858 * Function: 4859 * bcm_trunk_find 4860 * Description: 4861 * Get trunk id that contains the given system port 4862 * Parameters: 4863 * unit - StrataSwitch PCI device unit number (driver internal) 4864 * modid - Module ID 4865 * port - Port number 4866 * tid - (OUT) Trunk id 4867 * Returns: 4868 * BCM_E_xxxx 4869 */ 4870 int 4871 bcm_esw_trunk_find(int unit, bcm_module_t modid, bcm_port_t port, 4872 bcm_trunk_t *tid) 4873 { 4874 bcm_module_t hw_mod; 4875 bcm_port_t hw_port; 4876 int tgid, id; 4877 int isLocal; 4878 4879 TRUNK_INIT(unit); 4880 4881 if (tid == NULL) { 4882 return BCM_E_PARAM; 4883 } 4884 4885 if (BCM_GPORT_IS_SET(port)) { 4886 BCM_IF_ERROR_RETURN( 4887 _bcm_esw_gport_resolve(unit, port, &hw_mod, &hw_port, &tgid, &id)); 4888 4889 #if defined(BCM_HGPROXY_COE_SUPPORT) 4890 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4891 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 4892 id = -1; 4893 } else 4894 #endif 4895 #if defined(BCM_KATANA2_SUPPORT) 4896 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, port)) { 4897 id = -1; 4898 } 4899 #endif 4900 if (-1 != tgid) { 4901 return BCM_E_PORT; 4902 } else if (-1 != id) { 4903 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 4904 if (soc_feature(unit, soc_feature_vp_lag)) { 4905 return bcm_td2_vp_lag_find(unit, port, tid); 4906 } else 4907 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 4908 { 4909 return BCM_E_PORT; 4910 } 4911 } 4912 } else { 4913 PORT_DUALMODID_VALID(unit, port); 4914 BCM_IF_ERROR_RETURN 4915 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 4916 modid, port, 4917 &hw_mod, &hw_port)); 4918 4919 if (!SOC_MODID_ADDRESSABLE(unit, hw_mod)) { 4920 return BCM_E_BADID; 4921 } 4922 4923 if (!SOC_PORT_ADDRESSABLE(unit, hw_port)) { 4924 return BCM_E_PORT; 4925 } 4926 } 4927 4928 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, hw_mod, &isLocal)); 4929 4930 #ifdef BCM_XGS3_SWITCH_SUPPORT 4931 if (SOC_IS_XGS3_SWITCH(unit)) { 4932 #ifdef BCM_TOMAHAWK3_SUPPORT 4933 if (SOC_IS_TOMAHAWK3(unit)) { 4934 return(_bcm_th3_trunk_get_port_property(unit, hw_port, tid)); 4935 } else 4936 #endif 4937 { 4938 #ifdef BCM_TRIDENT_SUPPORT 4939 int rv = BCM_E_NONE; 4940 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 4941 if (isLocal && (IS_ST_PORT(unit, hw_port) 4942 || (soc_feature(unit, soc_feature_subtag_coe) && 4943 IS_SUBTAG_PORT (unit, hw_port)) 4944 || (soc_feature(unit, soc_feature_linkphy_coe) && 4945 IS_LP_PORT (unit, hw_port)) 4946 || (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4947 IS_SUBTAG_PORT (unit, hw_port)))) { 4948 4949 int my_modid = 0; 4950 /* If the passed in mod-id matches the local mod-id, look for 4951 the trunk with only the port. Else, for CoE type of 4952 applications look for both the mod-id and port-id */ 4953 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 4954 if (IS_ST_PORT(unit, hw_port) && (my_modid == hw_mod)) { 4955 rv = _bcm_trident_trunk_fabric_find(unit, hw_port, tid); 4956 } else { 4957 return (_bcm_trident_trunk_get_port_property(unit, hw_mod, 4958 hw_port, tid)); 4959 } 4960 4961 if (BCM_SUCCESS(rv)) { 4962 return rv; 4963 } 4964 4965 return(_bcm_trident_trunk_get_port_property(unit, hw_mod, 4966 hw_port, tid)); 4967 } else { 4968 return(_bcm_trident_trunk_get_port_property(unit, hw_mod, hw_port, tid)); 4969 } 4970 } else 4971 #endif /* BCM_TRIDENT_SUPPORT */ 4972 { 4973 if (isLocal && IS_ST_PORT(unit, hw_port)) { 4974 return(_bcm_xgs3_trunk_fabric_find(unit, hw_port, tid)); 4975 } else { 4976 return(_bcm_xgs3_trunk_get_port_property(unit, hw_mod, hw_port, tid)); 4977 } 4978 } 4979 } 4980 } else 4981 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 4982 { 4983 /* Hercules 1.5 */ 4984 4985 int idx = 0; 4986 int i; 4987 bcm_trunk_member_t member_array[BCM_TRUNK_FABRIC_MAX_PORTCNT]; 4988 int member_count; 4989 bcm_port_t tp[BCM_TRUNK_FABRIC_MAX_PORTCNT]; 4990 4991 for (idx = 0; idx < TRUNK_NUM_GROUPS(unit); idx++) { 4992 if (TRUNK_INFO(unit, idx).tid == BCM_TRUNK_INVALID) { 4993 continue; 4994 } 4995 4996 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, idx, NULL, 4997 BCM_TRUNK_FABRIC_MAX_PORTCNT, member_array, &member_count)); 4998 if (member_count <= 0) { 4999 continue; 5000 } 5001 5002 for (i = 0; i < member_count; i++) { 5003 BCM_IF_ERROR_RETURN 5004 (bcm_esw_port_local_get(unit, member_array[i].gport, &tp[i])); 5005 5006 if (isLocal && IS_ST_PORT(unit, hw_port)) { 5007 if (TRUNK_FABRIC_TID(unit, idx)) { 5008 if (tp[i] == hw_port) { 5009 *tid = idx; 5010 return BCM_E_NONE; 5011 } 5012 } 5013 } 5014 } 5015 } 5016 5017 return BCM_E_NOT_FOUND; 5018 } 5019 } 5020 5021 /* 5022 * Function: 5023 * bcm_esw_trunk_failover_set 5024 * Purpose: 5025 * Assign the failover port list for a specific trunk port. 5026 * Parameters: 5027 * unit - (IN) Unit number. 5028 * tid - (IN) Trunk id. 5029 * failport - (IN) Port in trunk for which to specify failover port list. 5030 * psc - (IN) Port selection criteria for failover port list. 5031 * flags - (IN) BCM_TRUNK_FLAG_FAILOVER_xxx. 5032 * count - (IN) Number of ports in failover port list. 5033 * fail_to_array - (IN) Failover port list. 5034 * Returns: 5035 * BCM_E_XXX 5036 * Notes: 5037 */ 5038 int 5039 bcm_esw_trunk_failover_set(int unit, bcm_trunk_t tid, bcm_gport_t failport, 5040 int psc, uint32 flags, int count, 5041 bcm_gport_t *fail_to_array) 5042 { 5043 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5044 trunk_private_t *t_info; 5045 int rv, id, fabric_trunk; 5046 bcm_port_t port, *ftp=NULL; 5047 bcm_module_t modid, *ftm=NULL; 5048 bcm_trunk_t tgid; 5049 5050 TRUNK_INIT(unit); 5051 5052 TRUNK_CHECK(unit, tid); 5053 5054 t_info = &TRUNK_INFO(unit, tid); 5055 5056 if (t_info->tid == BCM_TRUNK_INVALID) { 5057 return (BCM_E_NOT_FOUND); 5058 } 5059 5060 fabric_trunk = TRUNK_FABRIC_TID(unit, tid); 5061 5062 if (fabric_trunk) { 5063 if (!soc_feature(unit, soc_feature_hg_trunk_failover)) { 5064 return BCM_E_UNAVAIL; 5065 } 5066 if (BCM_GPORT_IS_SET(failport)) { 5067 BCM_IF_ERROR_RETURN 5068 (bcm_esw_port_local_get(unit, failport, &port)); 5069 } else { 5070 port = failport; 5071 } 5072 modid = -1; 5073 } else { 5074 if (!soc_feature(unit, soc_feature_port_lag_failover)) { 5075 return BCM_E_UNAVAIL; 5076 } 5077 #if defined(BCM_TRIDENT_SUPPORT) 5078 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 5079 if (BCM_GPORT_IS_SET(failport)) { 5080 BCM_IF_ERROR_RETURN 5081 (bcm_esw_port_local_get(unit, failport, &port)); 5082 } else { 5083 port = failport; 5084 } 5085 5086 if (IS_HG_PORT(unit, port)) { 5087 return BCM_E_UNAVAIL; 5088 } 5089 /* not supported for Cascaded Physical Ports*/ 5090 if ((soc_feature(unit, soc_feature_linkphy_coe) && 5091 IS_LP_PORT(unit, port)) || 5092 (soc_feature(unit, soc_feature_subtag_coe) && 5093 IS_SUBTAG_PORT(unit, port)) || 5094 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 5095 IS_SUBTAG_PORT (unit, port))) { 5096 return BCM_E_UNAVAIL; 5097 } 5098 } 5099 #endif 5100 5101 BCM_IF_ERROR_RETURN 5102 (_bcm_esw_gport_resolve(unit, failport, &modid, &port, &tgid, &id)); 5103 if ((-1 != tgid) || (-1 != id)) { 5104 return BCM_E_PARAM; 5105 } 5106 } 5107 5108 if (psc <= 0) { 5109 psc = BCM_TRUNK_PSC_DEFAULT; 5110 } 5111 5112 /* Failover options: 5113 * 1) Specify plan with a flag 5114 * 2) Specify plan with count > 0 and fail_to_array listing ports 5115 * 3) Disable failover with count == 0 5116 */ 5117 if ((flags == 0) && ((count < 0) || 5118 ((count > 0) && (fail_to_array == NULL)))) { 5119 return BCM_E_PARAM; 5120 } 5121 5122 if (count > 0) { 5123 if ((TRUNK_FP_TID(unit, tid) && 5124 (count > TRUNK_CNTL(unit).nports_fp)) || 5125 (TRUNK_FABRIC_TID(unit, tid) && 5126 (count > TRUNK_CNTL(unit).nports_hg)) ) { 5127 return (BCM_E_PARAM); 5128 } else { 5129 ftp = sal_alloc(sizeof(bcm_port_t) * count, "failover ports"); 5130 if (NULL == ftp) { 5131 return BCM_E_MEMORY; 5132 } 5133 ftm = sal_alloc(sizeof(bcm_module_t) * count, "failover mods"); 5134 if (NULL == ftm) { 5135 sal_free(ftp); 5136 return BCM_E_MEMORY; 5137 } 5138 rv = _bcm_esw_trunk_gport_array_resolve(unit, fabric_trunk, 5139 count, fail_to_array, 5140 ftp, ftm); 5141 if (BCM_FAILURE(rv)) { 5142 sal_free(ftp); 5143 sal_free(ftm); 5144 } 5145 } 5146 } 5147 5148 /* Offset of trunk type */ 5149 tgid = tid - (fabric_trunk ? TRUNK_CNTL(unit).ngroups_fp : 0); 5150 5151 TRUNK_LOCK(unit); 5152 #ifdef BCM_TOMAHAWK3_SUPPORT 5153 if (SOC_IS_TOMAHAWK3(unit)) { 5154 rv = _bcm_th3_trunk_hwfailover_set(unit, tid, 5155 port, psc, flags, count, fail_to_array); 5156 } else 5157 #endif /* BCM_TRIDENT_SUPPORT */ 5158 #ifdef BCM_TRIDENT_SUPPORT 5159 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 5160 rv = _bcm_trident_trunk_hwfailover_set(unit, tgid, fabric_trunk, 5161 port, modid, psc, flags, count, ftp, ftm); 5162 } else 5163 #endif /* BCM_TRIDENT_SUPPORT */ 5164 { 5165 rv = _bcm_xgs3_trunk_hwfailover_set(unit, tgid, fabric_trunk, 5166 port, modid, psc, flags, count, ftp, ftm); 5167 } 5168 if (NULL != ftp) { 5169 sal_free(ftp); 5170 } 5171 if (NULL != ftm) { 5172 sal_free(ftm); 5173 } 5174 5175 #ifdef BCM_WARM_BOOT_SUPPORT 5176 SOC_CONTROL_LOCK(unit); 5177 SOC_CONTROL(unit)->scache_dirty = 1; 5178 SOC_CONTROL_UNLOCK(unit); 5179 #endif 5180 5181 TRUNK_UNLOCK(unit); 5182 5183 return rv; 5184 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5185 return BCM_E_UNAVAIL; 5186 #endif 5187 } 5188 5189 /* 5190 * Function: 5191 * bcm_esw_trunk_failover_get 5192 * Purpose: 5193 * Retrieve the failover port list for a specific trunk port. 5194 * Parameters: 5195 * unit - (IN) Unit number. 5196 * tid - (IN) Trunk id. 5197 * failport - (IN) Port in trunk for which to retrieve failover port list. 5198 * psc - (OUT) Port selection criteria for failover port list. 5199 * flags - (OUT) BCM_TRUNK_FLAG_FAILOVER_xxx. 5200 * array_size - (IN) Maximum number of ports in provided failover port list. 5201 * fail_to_array - (OUT) Failover port list. 5202 * array_count - (OUT) Number of ports in returned failover port list. 5203 * Returns: 5204 * BCM_E_XXX 5205 * Notes: 5206 */ 5207 int 5208 bcm_esw_trunk_failover_get(int unit, bcm_trunk_t tid, bcm_gport_t failport, 5209 int *psc, uint32 *flags, int array_size, 5210 bcm_gport_t *fail_to_array, int *array_count) 5211 { 5212 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5213 trunk_private_t *t_info; 5214 int rv, id, fabric_trunk; 5215 bcm_port_t port, *ftp=NULL; 5216 bcm_module_t modid, *ftm=NULL; 5217 bcm_trunk_t tgid; 5218 5219 TRUNK_INIT(unit); 5220 5221 /* Following check is for Non-Tomahawk3 */ 5222 if (!SOC_IS_TOMAHAWK3(unit)) { 5223 if (!soc_feature(unit, soc_feature_hg_trunk_failover)) { 5224 return BCM_E_UNAVAIL; 5225 } 5226 } 5227 5228 TRUNK_CHECK(unit, tid); 5229 5230 t_info = &TRUNK_INFO(unit, tid); 5231 5232 if (t_info->tid == BCM_TRUNK_INVALID) { 5233 return (BCM_E_NOT_FOUND); 5234 } 5235 5236 fabric_trunk = TRUNK_FABRIC_TID(unit, tid); 5237 5238 if (fabric_trunk) { 5239 if (!soc_feature(unit, soc_feature_hg_trunk_failover)) { 5240 return BCM_E_UNAVAIL; 5241 } 5242 if (BCM_GPORT_IS_SET(failport)) { 5243 BCM_IF_ERROR_RETURN 5244 (bcm_esw_port_local_get(unit, failport, &port)); 5245 } else { 5246 port = failport; 5247 } 5248 modid = -1; 5249 } else { 5250 if (!soc_feature(unit, soc_feature_port_lag_failover)) { 5251 return BCM_E_UNAVAIL; 5252 } 5253 5254 #if defined(BCM_TRIDENT_SUPPORT) 5255 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 5256 if (BCM_GPORT_IS_SET(failport)) { 5257 BCM_IF_ERROR_RETURN 5258 (bcm_esw_port_local_get(unit, failport, &port)); 5259 } else { 5260 port = failport; 5261 } 5262 5263 if (IS_HG_PORT(unit, port)) { 5264 return BCM_E_UNAVAIL; 5265 } 5266 /* not supported for Cascaded Physical Ports*/ 5267 if ((soc_feature(unit, soc_feature_linkphy_coe) && 5268 IS_LP_PORT(unit, port)) || 5269 (soc_feature(unit, soc_feature_subtag_coe) && 5270 IS_SUBTAG_PORT(unit, port)) || 5271 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 5272 IS_SUBTAG_PORT (unit, port))) { 5273 return BCM_E_UNAVAIL; 5274 } 5275 } 5276 #endif 5277 BCM_IF_ERROR_RETURN 5278 (_bcm_esw_gport_resolve(unit, failport, &modid, &port, &tgid, &id)); 5279 if ((-1 != tgid) || (-1 != id)) { 5280 return BCM_E_PARAM; 5281 } 5282 } 5283 5284 if ((psc == NULL) || (flags == NULL) || (array_size < 0) || 5285 (fail_to_array == NULL) || (array_count == NULL)) { 5286 return BCM_E_PARAM; 5287 } 5288 5289 /* Offset of trunk type */ 5290 tgid = tid - (fabric_trunk ? TRUNK_CNTL(unit).ngroups_fp : 0); 5291 5292 if (array_size > 0) { 5293 ftp = sal_alloc(sizeof(bcm_port_t) * array_size, "failover ports"); 5294 if (NULL == ftp) { 5295 return BCM_E_MEMORY; 5296 } 5297 ftm = sal_alloc(sizeof(bcm_module_t) * array_size, "failover mods"); 5298 if (NULL == ftm) { 5299 sal_free(ftp); 5300 return BCM_E_MEMORY; 5301 } 5302 } 5303 sal_memset(ftm, 0, sizeof(bcm_module_t) * array_size); 5304 sal_memset(ftp, 0, sizeof(bcm_port_t) * array_size); 5305 5306 TRUNK_LOCK(unit); 5307 #ifdef BCM_TOMAHAWK3_SUPPORT 5308 if (SOC_IS_TOMAHAWK3(unit)) { 5309 rv = _bcm_th3_trunk_hwfailover_get(unit, tid, 5310 port, psc, flags, array_size, ftp, array_count); 5311 } else 5312 #endif 5313 #ifdef BCM_TRIDENT_SUPPORT 5314 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 5315 rv = _bcm_trident_trunk_hwfailover_get(unit, tgid, fabric_trunk, 5316 port, modid, psc, flags, array_size, ftp, ftm, array_count); 5317 } else 5318 #endif /* BCM_TRIDENT_SUPPORT */ 5319 { 5320 rv = _bcm_xgs3_trunk_hwfailover_get(unit, tgid, fabric_trunk, 5321 port, modid, psc, flags, array_size, ftp, ftm, array_count); 5322 } 5323 TRUNK_UNLOCK(unit); 5324 5325 if (BCM_SUCCESS(rv)) { 5326 rv = _bcm_esw_trunk_gport_construct(unit, fabric_trunk, *array_count, 5327 ftp, ftm, fail_to_array); 5328 } 5329 5330 if (NULL != ftp) { 5331 sal_free(ftp); 5332 } 5333 if (NULL != ftm) { 5334 sal_free(ftm); 5335 } 5336 5337 return rv; 5338 5339 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5340 return BCM_E_UNAVAIL; 5341 #endif 5342 } 5343 5344 /* 5345 * Function: 5346 * bcm_esw_trunk_member_add 5347 * Purpose: 5348 * Add a member to a trunk group. 5349 * Parameters: 5350 * unit - (IN) Unit number. 5351 * tid - (IN) Trunk id. 5352 * member - (IN) Pointer to a trunk member structure. 5353 * Returns: 5354 * BCM_E_XXX 5355 */ 5356 int 5357 bcm_esw_trunk_member_add( 5358 int unit, 5359 bcm_trunk_t tid, 5360 bcm_trunk_member_t *member) 5361 { 5362 trunk_private_t *t_info; 5363 int rv = BCM_E_NONE; 5364 int member_count; 5365 bcm_trunk_member_t *member_array = NULL; 5366 bcm_trunk_info_t trunk_info; 5367 int tid_is_vp_lag; 5368 bcm_module_t modid, member_modid; 5369 bcm_port_t port, member_port; 5370 bcm_trunk_t tgid, member_tgid; 5371 int id, member_id; 5372 int i; 5373 5374 TRUNK_INIT(unit); 5375 5376 BCM_IF_ERROR_RETURN 5377 (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 5378 if (!tid_is_vp_lag) { 5379 TRUNK_CHECK(unit, tid); 5380 t_info = &TRUNK_INFO(unit, tid); 5381 if (t_info->tid == BCM_TRUNK_INVALID) { 5382 return BCM_E_NOT_FOUND; 5383 } 5384 } 5385 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 5386 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 5387 int status = 1; 5388 SOC_LINKSCAN_MODPORT_MAP_LOCK(unit); 5389 rv = _bcm_td_stk_modport_map_member_link_handler(unit, 5390 member->gport, tid, 0, &status); 5391 SOC_LINKSCAN_MODPORT_MAP_UNLOCK(unit); 5392 if (BCM_FAILURE(rv)) { 5393 return rv; 5394 } 5395 if (status == 0) { 5396 return rv; 5397 } else { 5398 rv = BCM_E_NONE; 5399 } 5400 } 5401 #endif /* #(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) */ 5402 BCM_IF_ERROR_RETURN 5403 (_bcm_esw_gport_resolve(unit, member->gport, 5404 &modid, &port, &tgid, &id)); 5405 if (!tid_is_vp_lag && (-1 != tgid)) { 5406 return BCM_E_PARAM; 5407 } 5408 5409 /* Get number of trunk group's existing member ports */ 5410 BCM_IF_ERROR_RETURN 5411 (bcm_esw_trunk_get(unit, tid, &trunk_info, 0, NULL, &member_count)); 5412 5413 /* Allocate member array to accomodate existing members and 5414 * the new member to be added. 5415 */ 5416 member_array = sal_alloc(sizeof(bcm_trunk_member_t) * 5417 (member_count + 1), "trunk_member_array"); 5418 if (member_array == NULL) { 5419 return BCM_E_MEMORY; 5420 } 5421 sal_memset(member_array, 0, 5422 sizeof(bcm_trunk_member_t) * (member_count + 1)); 5423 5424 /* Retrieve existing member ports */ 5425 rv = bcm_esw_trunk_get(unit, tid, &trunk_info, member_count + 1, 5426 member_array, &member_count); 5427 if (BCM_FAILURE(rv)) { 5428 sal_free(member_array); 5429 return rv; 5430 } 5431 5432 /* If resilient hashing is enabled, check that the given member is not 5433 * already a member of the group. 5434 */ 5435 if (trunk_info.psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 5436 for (i = 0; i < member_count; i++) { 5437 rv = _bcm_esw_gport_resolve(unit, member_array[i].gport, 5438 &member_modid, &member_port, &member_tgid, &member_id); 5439 if (BCM_FAILURE(rv)) { 5440 sal_free(member_array); 5441 return rv; 5442 } 5443 if (-1 != member_id) { 5444 if (member_array[i].gport == member->gport) { 5445 sal_free(member_array); 5446 return BCM_E_EXISTS; 5447 } 5448 } else if (-1 != member_tgid) { 5449 sal_free(member_array); 5450 return BCM_E_INTERNAL; 5451 } else { 5452 if ((member_modid == modid) && (member_port == port)) { 5453 sal_free(member_array); 5454 return BCM_E_EXISTS; 5455 } 5456 } 5457 } 5458 } 5459 5460 /* Add given member to group */ 5461 member_array[member_count].flags = member->flags; 5462 member_array[member_count].gport = member->gport; 5463 member_array[member_count].dynamic_scaling_factor = 5464 member->dynamic_scaling_factor; 5465 member_array[member_count].dynamic_load_weight = 5466 member->dynamic_load_weight; 5467 member_array[member_count].dynamic_queue_size_weight = 5468 member->dynamic_queue_size_weight; 5469 rv = _bcm_esw_trunk_modify(unit, tid, &trunk_info, member_count + 1, 5470 member_array, TRUNK_MEMBER_OP_ADD, member); 5471 sal_free(member_array); 5472 return rv; 5473 } 5474 5475 /* 5476 * Function: 5477 * bcm_esw_trunk_member_delete 5478 * Purpose: 5479 * Remove a member from a trunk group. 5480 * Parameters: 5481 * unit - (IN) Unit number. 5482 * tid - (IN) Trunk id. 5483 * member - (IN) Pointer to a trunk member structure. 5484 * Returns: 5485 * BCM_E_XXX 5486 */ 5487 int 5488 bcm_esw_trunk_member_delete( 5489 int unit, 5490 bcm_trunk_t tid, 5491 bcm_trunk_member_t *member) 5492 { 5493 trunk_private_t *t_info; 5494 bcm_module_t modid; 5495 bcm_port_t port; 5496 bcm_trunk_t tgid; 5497 int id; 5498 int rv = BCM_E_NONE; 5499 int i, k; 5500 int member_count; 5501 bcm_trunk_member_t *member_array; 5502 bcm_module_t member_modid; 5503 bcm_port_t member_port; 5504 bcm_trunk_t member_tgid; 5505 int member_id; 5506 bcm_trunk_info_t trunk_info; 5507 int tid_is_vp_lag; 5508 5509 TRUNK_INIT(unit); 5510 5511 BCM_IF_ERROR_RETURN 5512 (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 5513 if (!tid_is_vp_lag) { 5514 TRUNK_CHECK(unit, tid); 5515 t_info = &TRUNK_INFO(unit, tid); 5516 if (t_info->tid == BCM_TRUNK_INVALID) { 5517 return BCM_E_NOT_FOUND; 5518 } 5519 } 5520 5521 BCM_IF_ERROR_RETURN 5522 (_bcm_esw_gport_resolve(unit, member->gport, 5523 &modid, &port, &tgid, &id)); 5524 if (!tid_is_vp_lag && (-1 != tgid)) { 5525 return BCM_E_PARAM; 5526 } 5527 5528 /* Get number of trunk group's existing member ports */ 5529 BCM_IF_ERROR_RETURN 5530 (bcm_esw_trunk_get(unit, tid, &trunk_info, 0, NULL, &member_count)); 5531 5532 if (member_count == 0) { 5533 return BCM_E_NOT_FOUND; 5534 } 5535 5536 /* Allocate member array to get existing members */ 5537 member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count, 5538 "trunk_member_array"); 5539 if (member_array == NULL) { 5540 return BCM_E_MEMORY; 5541 } 5542 sal_memset(member_array, 0, 5543 sizeof(bcm_trunk_member_t) * member_count); 5544 5545 /* Retrieve existing member ports */ 5546 rv = bcm_esw_trunk_get(unit, tid, &trunk_info, member_count, 5547 member_array, &member_count); 5548 if (BCM_FAILURE(rv)) { 5549 sal_free(member_array); 5550 return rv; 5551 } 5552 5553 /* Find the index of the given member in the array */ 5554 for (i = 0; i < member_count; i++) { 5555 rv = _bcm_esw_gport_resolve(unit, member_array[i].gport, 5556 &member_modid, &member_port, 5557 &member_tgid, &member_id); 5558 if (BCM_FAILURE(rv)) { 5559 sal_free(member_array); 5560 return rv; 5561 } 5562 if (-1 != member_id) { 5563 if (member_array[i].gport == member->gport) { 5564 break; 5565 } 5566 } else if (-1 != member_tgid) { 5567 sal_free(member_array); 5568 return BCM_E_INTERNAL; 5569 } else { 5570 if ((member_modid == modid) && (member_port == port)) { 5571 break; 5572 } 5573 } 5574 } 5575 5576 if (i == member_count) { 5577 sal_free(member_array); 5578 return BCM_E_NOT_FOUND; 5579 } 5580 5581 /* Delete given member from array, and shift the remaining 5582 * elements of the array. 5583 */ 5584 for (k = i; k < member_count - 1; k++) { 5585 member_array[k].flags = member_array[k+1].flags; 5586 member_array[k].gport = member_array[k+1].gport; 5587 } 5588 5589 member_count--; 5590 if (0 == member_count) { 5591 rv = _bcm_esw_trunk_modify(unit, tid, &trunk_info, 5592 0, NULL, TRUNK_MEMBER_OP_DELETE, member); 5593 } else { 5594 rv = _bcm_esw_trunk_modify(unit, tid, &trunk_info, 5595 member_count, member_array, TRUNK_MEMBER_OP_DELETE, member); 5596 } 5597 5598 sal_free(member_array); 5599 return rv; 5600 } 5601 5602 /* 5603 * Function: 5604 * bcm_esw_trunk_member_delete_all 5605 * Purpose: 5606 * Remove all members of a trunk group. 5607 * Parameters: 5608 * unit - (IN) Unit number. 5609 * tid - (IN) Trunk id. 5610 * Returns: 5611 * BCM_E_XXX 5612 */ 5613 int 5614 bcm_esw_trunk_member_delete_all( 5615 int unit, 5616 bcm_trunk_t tid) 5617 { 5618 bcm_trunk_info_t trunk_info; 5619 int member_count; 5620 5621 BCM_IF_ERROR_RETURN 5622 (bcm_esw_trunk_get(unit, tid, &trunk_info, 0, NULL, &member_count)); 5623 5624 if (member_count > 0) { 5625 BCM_IF_ERROR_RETURN 5626 (bcm_esw_trunk_set(unit, tid, &trunk_info, 0, NULL)); 5627 } 5628 5629 return BCM_E_NONE; 5630 } 5631 5632 /* 5633 * Function: 5634 * bcm_esw_trunk_member_status_set 5635 * Purpose: 5636 * Set trunk member status. 5637 * Parameters: 5638 * unit - (IN) Unit number. 5639 * member - (IN) Trunk member GPORT ID. 5640 * status - (IN) Trunk member link status: 0 = down, 1 = up. 5641 * Returns: 5642 * BCM_E_XXX 5643 */ 5644 int 5645 bcm_esw_trunk_member_status_set( 5646 int unit, 5647 bcm_gport_t member, 5648 int status) 5649 { 5650 int rv = BCM_E_UNAVAIL; 5651 bcm_module_t mod; 5652 bcm_port_t port; 5653 bcm_trunk_t tid; 5654 int hw_id; 5655 int is_local; 5656 int set_hg_dlb_member_status = FALSE; 5657 5658 TRUNK_INIT(unit); 5659 5660 BCM_IF_ERROR_RETURN 5661 (_bcm_esw_gport_resolve(unit, member, &mod, &port, &tid, &hw_id)); 5662 if ((tid != -1) || (hw_id != -1)) { 5663 return BCM_E_PORT; 5664 } 5665 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, mod, &is_local)); 5666 5667 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5668 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 5669 if (!is_local) { 5670 return BCM_E_PORT; 5671 } 5672 if (soc_feature(unit, soc_feature_hg_dlb)) { 5673 if (!IS_HG_PORT(unit, port)) { 5674 return BCM_E_PORT; 5675 } 5676 } 5677 TRUNK_LOCK(unit); 5678 rv = bcm_th2_hgt_lag_dlb_member_status_set(unit, port, status); 5679 TRUNK_UNLOCK(unit); 5680 return rv; 5681 } 5682 #endif /* BCM_TOMAHAWK2_SUPPORT */ 5683 5684 if (is_local) { 5685 if (IS_HG_PORT(unit, port)) { 5686 set_hg_dlb_member_status = TRUE; 5687 } 5688 } 5689 5690 TRUNK_LOCK(unit); 5691 5692 if (set_hg_dlb_member_status) { 5693 if (soc_feature(unit, soc_feature_hg_dlb)) { 5694 #ifdef BCM_TRIDENT_SUPPORT 5695 rv = bcm_trident_hg_dlb_member_status_set(unit, port, status); 5696 #endif /* BCM_TRIDENT_SUPPORT */ 5697 } else { 5698 rv = BCM_E_UNAVAIL; 5699 } 5700 } else { 5701 if (soc_feature(unit, soc_feature_lag_dlb)) { 5702 #ifdef BCM_TRIUMPH3_SUPPORT 5703 rv = bcm_tr3_lag_dlb_member_status_set(unit, mod, port, status); 5704 #endif /* BCM_TRIUMPH3_SUPPORT */ 5705 } else { 5706 rv = BCM_E_UNAVAIL; 5707 } 5708 } 5709 5710 TRUNK_UNLOCK(unit); 5711 return rv; 5712 } 5713 5714 /* 5715 * Function: 5716 * bcm_esw_trunk_member_status_get 5717 * Purpose: 5718 * Get trunk member status. 5719 * Parameters: 5720 * unit - (IN) Unit number. 5721 * member - (IN) Trunk member GPORT ID. 5722 * status - (OUT) Trunk member link status. 5723 * Returns: 5724 * BCM_E_XXX 5725 */ 5726 int 5727 bcm_esw_trunk_member_status_get( 5728 int unit, 5729 bcm_gport_t member, 5730 int *status) 5731 { 5732 int rv = BCM_E_UNAVAIL; 5733 bcm_module_t mod; 5734 bcm_port_t port; 5735 bcm_trunk_t tid; 5736 int hw_id; 5737 int is_local; 5738 int get_hg_dlb_member_status = FALSE; 5739 5740 if (NULL == status) { 5741 return BCM_E_PARAM; 5742 } 5743 5744 TRUNK_INIT(unit); 5745 5746 BCM_IF_ERROR_RETURN 5747 (_bcm_esw_gport_resolve(unit, member, &mod, &port, &tid, &hw_id)); 5748 if ((tid != -1) || (hw_id != -1)) { 5749 return BCM_E_PORT; 5750 } 5751 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, mod, &is_local)); 5752 5753 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5754 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 5755 if (!is_local) { 5756 return BCM_E_PORT; 5757 } 5758 if (soc_feature(unit, soc_feature_hg_dlb)) { 5759 if (!IS_HG_PORT(unit, port)) { 5760 return BCM_E_PORT; 5761 } 5762 } 5763 TRUNK_LOCK(unit); 5764 rv = bcm_th2_hgt_lag_dlb_member_status_get(unit, port, status); 5765 TRUNK_UNLOCK(unit); 5766 return rv; 5767 } 5768 #endif /* BCM_TOMAHAWK2_SUPPORT */ 5769 if (is_local) { 5770 if (IS_HG_PORT(unit, port)) { 5771 get_hg_dlb_member_status = TRUE; 5772 } 5773 } 5774 5775 TRUNK_LOCK(unit); 5776 5777 if (get_hg_dlb_member_status) { 5778 if (soc_feature(unit, soc_feature_hg_dlb)) { 5779 #ifdef BCM_TRIDENT_SUPPORT 5780 rv = bcm_trident_hg_dlb_member_status_get(unit, port, status); 5781 #endif /* BCM_TRIDENT_SUPPORT */ 5782 } else { 5783 rv = BCM_E_UNAVAIL; 5784 } 5785 } else { 5786 if (soc_feature(unit, soc_feature_lag_dlb)) { 5787 #ifdef BCM_TRIUMPH3_SUPPORT 5788 rv = bcm_tr3_lag_dlb_member_status_get(unit, mod, port, status); 5789 #endif /* BCM_TRIUMPH3_SUPPORT */ 5790 } else { 5791 rv = BCM_E_UNAVAIL; 5792 } 5793 } 5794 5795 TRUNK_UNLOCK(unit); 5796 return rv; 5797 } 5798 5799 /* 5800 * Function: 5801 * bcm_esw_trunk_ethertype_set 5802 * Purpose: 5803 * Set the Ethertypes that are eligible or ineligible for 5804 * dynamic load balancing or resilient hashing. 5805 * Parameters: 5806 * unit - (IN) Unit number. 5807 * flags - (IN) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags. 5808 * ethertype_count - (IN) Number of elements in ethertype_array. 5809 * ethertype_array - (IN) Array of Ethertypes. 5810 * Returns: 5811 * BCM_E_XXX 5812 */ 5813 int 5814 bcm_esw_trunk_ethertype_set( 5815 int unit, 5816 uint32 flags, 5817 int ethertype_count, 5818 int *ethertype_array) 5819 { 5820 int rv; 5821 int i; 5822 5823 if ((ethertype_count > 0) && (NULL == ethertype_array)) { 5824 return BCM_E_PARAM; 5825 } 5826 for (i = 0; i < ethertype_count; i++) { 5827 if (ethertype_array[i] < 0 || ethertype_array[i] > 0xffff) { 5828 return BCM_E_PARAM; 5829 } 5830 } 5831 5832 TRUNK_INIT(unit); 5833 TRUNK_LOCK(unit); 5834 5835 rv = BCM_E_UNAVAIL; 5836 5837 if (flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_TRUNK) { 5838 if (flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_RESILIENT) { 5839 #ifdef BCM_TRIDENT2_SUPPORT 5840 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 5841 rv = bcm_td2_lag_rh_ethertype_set(unit, flags, ethertype_count, 5842 ethertype_array); 5843 if (BCM_FAILURE(rv)) { 5844 TRUNK_UNLOCK(unit); 5845 return rv; 5846 } 5847 } else 5848 #endif /* BCM_TRIDENT2_SUPPORT */ 5849 { 5850 /* Resilient hashing not supported for LAGs */ 5851 return BCM_E_UNAVAIL; 5852 } 5853 5854 } else { 5855 #ifdef BCM_TRIUMPH3_SUPPORT 5856 if (soc_feature(unit, soc_feature_lag_dlb)) { 5857 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5858 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 5859 rv = bcm_th2_hgt_lag_dlb_ethertype_set(unit, flags, 5860 ethertype_count, ethertype_array); 5861 } else 5862 #endif /* BCM_TOMAHAWK2_SUPPORT */ 5863 { 5864 rv = bcm_tr3_lag_dlb_ethertype_set(unit, flags, ethertype_count, 5865 ethertype_array); 5866 } 5867 if (BCM_FAILURE(rv)) { 5868 TRUNK_UNLOCK(unit); 5869 return rv; 5870 } 5871 } 5872 #endif /* BCM_TRIUMPH3_SUPPORT */ 5873 } 5874 } else if (flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_FABRIC_TRUNK) { 5875 if (flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_RESILIENT) { 5876 #ifdef BCM_TRIDENT2_SUPPORT 5877 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 5878 rv = bcm_td2_hg_rh_ethertype_set(unit, flags, ethertype_count, 5879 ethertype_array); 5880 if (BCM_FAILURE(rv)) { 5881 TRUNK_UNLOCK(unit); 5882 return rv; 5883 } 5884 } else 5885 #endif /* BCM_TRIDENT2_SUPPORT */ 5886 { 5887 /* Resilient hashing not supported for LAGs */ 5888 return BCM_E_UNAVAIL; 5889 } 5890 } else { 5891 if (soc_feature(unit, soc_feature_hg_dlb)) { 5892 #ifdef BCM_TRIUMPH3_SUPPORT 5893 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5894 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 5895 rv = bcm_th2_hgt_lag_dlb_ethertype_set(unit, flags, ethertype_count, 5896 ethertype_array); 5897 if (BCM_FAILURE(rv)) { 5898 TRUNK_UNLOCK(unit); 5899 return rv; 5900 } 5901 } else 5902 #endif /* BCM_TOMAHAWK2_SUPPORT */ 5903 { 5904 if (soc_mem_is_valid(unit, DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm)) { 5905 rv = bcm_tr3_hg_dlb_ethertype_set(unit, flags, ethertype_count, 5906 ethertype_array); 5907 if (BCM_FAILURE(rv)) { 5908 TRUNK_UNLOCK(unit); 5909 return rv; 5910 } 5911 } 5912 } 5913 #endif /* BCM_TRIUMPH3_SUPPORT */ 5914 } 5915 } 5916 } else { 5917 TRUNK_UNLOCK(unit); 5918 return BCM_E_PARAM; 5919 } 5920 5921 TRUNK_UNLOCK(unit); 5922 return rv; 5923 } 5924 5925 /* 5926 * Function: 5927 * bcm_esw_trunk_ethertype_get 5928 * Purpose: 5929 * Get the Ethertypes that are eligible or ineligible for 5930 * dynamic load balancing or resilient hashing. 5931 * Parameters: 5932 * unit - (IN) Unit number. 5933 * flags - (INOUT) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags. 5934 * ethertype_max - (IN) Number of elements in ethertype_array. 5935 * ethertype_array - (OUT) Array of Ethertypes. 5936 * ethertype_count - (OUT) Number of elements returned in ethertype_array. 5937 * Returns: 5938 * BCM_E_XXX 5939 */ 5940 int 5941 bcm_esw_trunk_ethertype_get( 5942 int unit, 5943 uint32 *flags, 5944 int ethertype_max, 5945 int *ethertype_array, 5946 int *ethertype_count) 5947 { 5948 int rv; 5949 5950 if (NULL == flags) { 5951 return BCM_E_PARAM; 5952 } 5953 if ((ethertype_max > 0) && (NULL == ethertype_array)) { 5954 return BCM_E_PARAM; 5955 } 5956 if (NULL == ethertype_count) { 5957 return BCM_E_PARAM; 5958 } 5959 5960 TRUNK_INIT(unit); 5961 TRUNK_LOCK(unit); 5962 5963 rv = BCM_E_UNAVAIL; 5964 5965 if (*flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_TRUNK) { 5966 if (*flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_RESILIENT) { 5967 #ifdef BCM_TRIDENT2_SUPPORT 5968 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 5969 rv = bcm_td2_lag_rh_ethertype_get(unit, flags, ethertype_max, 5970 ethertype_array, ethertype_count); 5971 if (BCM_FAILURE(rv)) { 5972 TRUNK_UNLOCK(unit); 5973 return rv; 5974 } 5975 } else 5976 #endif /* BCM_TRIDENT2_SUPPORT */ 5977 { 5978 /* Resilient hashing not supported for LAGs */ 5979 return BCM_E_UNAVAIL; 5980 } 5981 } else { 5982 #ifdef BCM_TRIUMPH3_SUPPORT 5983 if (soc_feature(unit, soc_feature_lag_dlb)) { 5984 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5985 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 5986 rv = bcm_th2_hgt_lag_dlb_ethertype_get(unit, flags, 5987 ethertype_max, ethertype_array, ethertype_count); 5988 } else 5989 #endif /* BCM_TOMAHAWK2_SUPPORT */ 5990 { 5991 rv = bcm_tr3_lag_dlb_ethertype_get(unit, flags, ethertype_max, 5992 ethertype_array, ethertype_count); 5993 } 5994 if (BCM_FAILURE(rv)) { 5995 TRUNK_UNLOCK(unit); 5996 return rv; 5997 } 5998 } 5999 #endif /* BCM_TRIUMPH3_SUPPORT */ 6000 } 6001 } else if (*flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_FABRIC_TRUNK) { 6002 if (*flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_RESILIENT) { 6003 #ifdef BCM_TRIDENT2_SUPPORT 6004 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 6005 rv = bcm_td2_hg_rh_ethertype_get(unit, flags, ethertype_max, 6006 ethertype_array, ethertype_count); 6007 if (BCM_FAILURE(rv)) { 6008 TRUNK_UNLOCK(unit); 6009 return rv; 6010 } 6011 } else 6012 #endif /* BCM_TRIDENT2_SUPPORT */ 6013 { 6014 /* Resilient hashing not supported for Higig trunks */ 6015 return BCM_E_UNAVAIL; 6016 } 6017 } else { 6018 if (soc_feature(unit, soc_feature_hg_dlb)) { 6019 #ifdef BCM_TRIUMPH3_SUPPORT 6020 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 6021 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 6022 rv = bcm_th2_hgt_lag_dlb_ethertype_get(unit, flags, 6023 ethertype_max, ethertype_array, ethertype_count); 6024 if (BCM_FAILURE(rv)) { 6025 TRUNK_UNLOCK(unit); 6026 return rv; 6027 } 6028 } else 6029 #endif /* BCM_TOMAHAWK2_SUPPORT */ 6030 { 6031 if (soc_mem_is_valid(unit, DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm)) { 6032 rv = bcm_tr3_hg_dlb_ethertype_get(unit, flags, ethertype_max, 6033 ethertype_array, ethertype_count); 6034 if (BCM_FAILURE(rv)) { 6035 TRUNK_UNLOCK(unit); 6036 return rv; 6037 } 6038 } 6039 } 6040 #endif /* BCM_TRIUMPH3_SUPPORT */ 6041 } 6042 } 6043 } else { 6044 TRUNK_UNLOCK(unit); 6045 return BCM_E_PARAM; 6046 } 6047 6048 TRUNK_UNLOCK(unit); 6049 return rv; 6050 } 6051 6052 #ifdef BCM_TOMAHAWK_SUPPORT 6053 6054 STATIC int 6055 _bcm_th_trunk_agm_update(int unit, bcm_trunk_t tid, 6056 bcm_switch_agm_type_t agm_type, 6057 int agm_pool_id, 6058 int agm_index) 6059 { 6060 int rv = BCM_E_NONE, hgtid; 6061 uint32 tg_entry[SOC_MAX_MEM_WORDS]; 6062 hg_trunk_group_entry_t hg_trunk_group_entry; 6063 bcm_trunk_chip_info_t chip_info; 6064 int tid_is_vp_lag; 6065 trunk_private_t *t_info; 6066 6067 TRUNK_INIT(unit); 6068 6069 BCM_IF_ERROR_RETURN 6070 (_bcm_esw_trunk_id_is_vp_lag(unit, tid, &tid_is_vp_lag)); 6071 if (!tid_is_vp_lag) { 6072 TRUNK_CHECK(unit, tid); 6073 t_info = &TRUNK_INFO(unit, tid); 6074 if (t_info->tid == BCM_TRUNK_INVALID) { 6075 return BCM_E_NOT_FOUND; 6076 } 6077 } else { 6078 /* XXX vp_lag ? */ 6079 return BCM_E_UNAVAIL; 6080 } 6081 6082 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 6083 LOG_INFO(BSL_LS_BCM_TRUNK, (BSL_META_U(unit, "tid %d min %d tid max %d fabId min %d fabId max %d \n"), 6084 tid, chip_info.trunk_id_min, chip_info.trunk_id_max, 6085 chip_info.trunk_fabric_id_min, chip_info.trunk_fabric_id_max)); 6086 6087 if ((tid >= chip_info.trunk_id_min) && (tid <= chip_info.trunk_id_max)) { 6088 if (agm_type != bcmSwitchAgmTypeTrunk) { 6089 return BCM_E_PARAM; 6090 } 6091 /* trunk group entry */ 6092 if (soc_feature(unit, soc_feature_fastlag)) { 6093 #ifdef BCM_TOMAHAWK3_SUPPORT 6094 if (SOC_IS_TOMAHAWK3(unit)) { 6095 fast_trunk_ports_1_entry_t fast_1; 6096 SOC_IF_ERROR_RETURN 6097 (READ_FAST_TRUNK_PORTS_1m(unit, MEM_BLOCK_ALL, tid, &fast_1)); 6098 soc_FAST_TRUNK_PORTS_1m_field32_set(unit, &fast_1, AGM_MONITOR_POOL_IDf, agm_pool_id); 6099 soc_FAST_TRUNK_PORTS_1m_field32_set(unit, &fast_1, AGM_MONITOR_IDf, agm_index); 6100 SOC_IF_ERROR_RETURN 6101 (WRITE_FAST_TRUNK_PORTS_1m(unit, MEM_BLOCK_ALL, tid, &fast_1)); 6102 } else 6103 #endif 6104 { 6105 SOC_IF_ERROR_RETURN 6106 (READ_FAST_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 6107 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, AGM_MONITOR_POOL_IDf, 6108 agm_pool_id); 6109 soc_FAST_TRUNK_GROUPm_field32_set(unit, &tg_entry, AGM_MONITOR_IDf, 6110 agm_index); 6111 SOC_IF_ERROR_RETURN 6112 (WRITE_FAST_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 6113 } 6114 } else { /* Not a Fast lag */ 6115 SOC_IF_ERROR_RETURN 6116 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 6117 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, AGM_MONITOR_POOL_IDf, 6118 agm_pool_id); 6119 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, AGM_MONITOR_IDf, 6120 agm_index); 6121 SOC_IF_ERROR_RETURN 6122 (WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 6123 } 6124 } else if ((tid >= chip_info.trunk_fabric_id_min) && 6125 (tid <= (chip_info.trunk_fabric_id_max + 1))) { 6126 if (agm_type != bcmSwitchAgmTypeFabricTrunk) { 6127 return BCM_E_PARAM; 6128 } 6129 /* Higig trunk group entry */ 6130 hgtid = tid - chip_info.trunk_fabric_id_min; 6131 SOC_IF_ERROR_RETURN 6132 (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, 6133 &hg_trunk_group_entry)); 6134 soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry, 6135 AGM_MONITOR_POOL_IDf, agm_pool_id); 6136 soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry, 6137 AGM_MONITOR_IDf, agm_index); 6138 SOC_IF_ERROR_RETURN 6139 (WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid, 6140 &hg_trunk_group_entry)); 6141 } else { 6142 rv = BCM_E_PARAM; 6143 } 6144 6145 return rv; 6146 } 6147 6148 /* 6149 * Function: 6150 * bcm_th_trunk_agm_attach 6151 * Purpose: 6152 * Attach already created monitor entry to a trunk or a fabric trunk 6153 * Internally, Map the monitor_entry_id to an aggregation group. 6154 */ 6155 int 6156 bcm_th_trunk_agm_attach(int unit, bcm_trunk_t tid, 6157 bcm_switch_agm_id_t agm_id) 6158 { 6159 int rv = BCM_E_NONE; 6160 6161 agm_monitor_t agm_mnt; 6162 bcm_switch_agm_id_t agm_id_old; 6163 int agm_pool_id; 6164 uint32 agm_index; 6165 6166 bcm_trunk_info_t tinfo; 6167 int mbm_cnt, mbm_max; 6168 bcm_trunk_member_t *mbm_arr; 6169 6170 /* Validate parameters */ 6171 if (!SOC_UNIT_VALID(unit)) { 6172 return BCM_E_UNIT; 6173 } 6174 TRUNK_CHECK(unit, tid); 6175 6176 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_info(unit, agm_id, &agm_mnt)); 6177 if (agm_mnt.group_id == (int)tid) { 6178 return BCM_E_EXISTS; 6179 } 6180 6181 mbm_max = agm_mnt.attr.num_members; 6182 mbm_arr = sal_alloc(mbm_max * sizeof(*mbm_arr), "mbm_arr"); 6183 if (mbm_arr == NULL) { 6184 return BCM_E_MEMORY; 6185 } 6186 6187 rv = bcm_esw_trunk_get(unit, tid, &tinfo, mbm_max, mbm_arr, &mbm_cnt); 6188 sal_free(mbm_arr); 6189 if (BCM_FAILURE(rv)) { 6190 return rv; 6191 } 6192 6193 if (mbm_cnt != agm_mnt.attr.num_members) { 6194 LOG_VERBOSE(BSL_LS_BCM_TRUNK, (BSL_META_U(unit, 6195 "AGM %d member cnt %d doesn't match trunk %d member cnt %d\n"), 6196 agm_id, agm_mnt.attr.num_members, tid, mbm_cnt)); 6197 return BCM_E_PARAM; 6198 } 6199 6200 agm_pool_id = agm_mnt.agm_pool_id; 6201 agm_index = agm_mnt.attr.agm_id; 6202 6203 BCM_IF_ERROR_RETURN(_bcm_th_trunk_agm_update(unit, tid, agm_mnt.attr.agm_type, 6204 agm_pool_id, agm_index)); 6205 6206 /* in case of changing AGM, detach the old AGM first */ 6207 if (BCM_SUCCESS(bcm_th_switch_agm_id_get_by_group(unit, tid, &agm_id_old))) { 6208 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_fwd_grp_update(unit, agm_id_old, 6209 _AGM_GROUP_ID_INVALID)); 6210 } 6211 6212 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_fwd_grp_update(unit, agm_id, tid)); 6213 6214 return rv; 6215 } 6216 6217 /* 6218 * Function: 6219 * bcm_th_trunk_agm_detach 6220 * Purpose: 6221 * Detach a monitor entry from a trunk or a fabric trunk 6222 * Internally, un-map the monitor_entry_id from an aggregation 6223 * group (fp_lag/fabric_channel_lag). 6224 */ 6225 int 6226 bcm_th_trunk_agm_detach(int unit, bcm_trunk_t tid, 6227 bcm_switch_agm_id_t agm_id) 6228 { 6229 int rv = BCM_E_NONE; 6230 agm_monitor_t agm_mnt; 6231 6232 /* Validate parameters */ 6233 if (!SOC_UNIT_VALID(unit)) { 6234 return BCM_E_UNIT; 6235 } 6236 TRUNK_CHECK(unit, tid); 6237 6238 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_info(unit, agm_id, &agm_mnt)); 6239 if (agm_mnt.group_id != (int)tid) { 6240 return BCM_E_NOT_FOUND; 6241 } 6242 6243 BCM_IF_ERROR_RETURN(_bcm_th_trunk_agm_update(unit, tid, 6244 agm_mnt.attr.agm_type, 0, _AGM_ID_INVALID)); 6245 BCM_IF_ERROR_RETURN(bcm_th_switch_agm_fwd_grp_update(unit, agm_id, 6246 _AGM_GROUP_ID_INVALID)); 6247 6248 return rv; 6249 } 6250 6251 /* 6252 * Function: 6253 * bcm_th_trunk_agm_attach_get 6254 * Purpose: 6255 * Retrieve a monitor id attached to a (fabric)trunk 6256 */ 6257 int 6258 bcm_th_trunk_agm_attach_get(int unit, bcm_trunk_t trunk_id, 6259 bcm_switch_agm_id_t *agm_id) 6260 { 6261 /* Validate parameters */ 6262 if (!SOC_UNIT_VALID(unit)) { 6263 return BCM_E_UNIT; 6264 } 6265 TRUNK_CHECK(unit, trunk_id); 6266 6267 return bcm_th_switch_agm_id_get_by_group(unit, trunk_id, agm_id); 6268 } 6269 6270 #endif /* BCM_TOMAHAWK_SUPPORT */ 6271 6272 /* 6273 * Function: 6274 * bcm_esw_trunk_agm_attach 6275 * Purpose: 6276 * Attach already created monitor entry to a trunk or a fabric trunk 6277 * Internally, Map the monitor_entry_id to an aggregation group. 6278 * Parameters: 6279 * unit - (IN) bcm device. 6280 * trunk_id - (IN) id of a (fabric) trunk. 6281 * agm_id - (IN) id of aggregation group monitoring entry created 6282 * via the bcm_switch_agm_create api. 6283 * Returns: 6284 * BCM_E_NONE: if the attachment is succeed 6285 * BCM_E_PARAM: if the monitor_id is not valid or the monitor 6286 * entry is not created. If the trunk id is not valid 6287 * BCM_E_FULL: if a monitor entry is already attached to 6288 * BCM_E_PARAM: if number of trunk member is different from the 6289 * number on the monitor entry 6290 */ 6291 int 6292 bcm_esw_trunk_agm_attach(int unit, bcm_trunk_t trunk_id, 6293 bcm_switch_agm_id_t agm_id) 6294 { 6295 int rv = BCM_E_UNAVAIL; 6296 6297 #if defined(BCM_TOMAHAWK_SUPPORT) 6298 if (soc_feature(unit, soc_feature_agm)) { 6299 TRUNK_LOCK(unit); 6300 rv = bcm_th_trunk_agm_attach(unit, trunk_id, agm_id); 6301 TRUNK_UNLOCK(unit); 6302 } 6303 #endif /* BCM_TOMAHAWK_SUPPORT */ 6304 return rv; 6305 } 6306 6307 /* 6308 * Function: 6309 * bcm_esw_trunk_agm_detach 6310 * Purpose: 6311 * Detach a monitor entry from a trunk or a fabric trunk 6312 * Internally, un-map the monitor_entry_id from an aggregation 6313 * group (fp_lag/fabric_channel_lag). 6314 * Parameters: 6315 * unit - (IN) bcm device. 6316 * trunk_id - (IN) id of a (fabric) trunk. 6317 * agm_id - (IN) id of aggregation group monitoring entry created 6318 * via the bcm_switch_agm_create api. 6319 * Returns: 6320 * BCM_E_NONE: if the enable or disable is succeed 6321 * BCM_E_PARAM: If the ecmp id is not valid 6322 * BCM_E_NOT_FOUND: if there is no monitor entry attached to the 6323 * aggregation group. 6324 */ 6325 int 6326 bcm_esw_trunk_agm_detach(int unit, bcm_trunk_t trunk_id, 6327 bcm_switch_agm_id_t agm_id) 6328 { 6329 int rv = BCM_E_UNAVAIL; 6330 6331 #if defined(BCM_TOMAHAWK_SUPPORT) 6332 if (soc_feature(unit, soc_feature_agm)) { 6333 TRUNK_LOCK(unit); 6334 rv = bcm_th_trunk_agm_detach(unit, trunk_id, agm_id); 6335 TRUNK_UNLOCK(unit); 6336 } 6337 #endif /* BCM_TOMAHAWK_SUPPORT */ 6338 return rv; 6339 } 6340 6341 /* 6342 * Function: 6343 * bcm_esw_trunk_agm_attach_get 6344 * Purpose: 6345 * Retrieve a monitor id attached to a (fabric)trunk 6346 * Parameters: 6347 * unit - (IN) bcm device. 6348 * trunk_id - (IN) (fabric) trunk id. 6349 * agm_id - (IN/OUT) aggregation group monitoring entry. 6350 * Returns: 6351 * BCM_E_NONE: if monitor entry id found 6352 * BCM_E_NOT_FOUND: if no monitor entry is attached to the 6353 * aggregation group. 6354 */ 6355 int 6356 bcm_esw_trunk_agm_attach_get(int unit, bcm_trunk_t trunk_id, 6357 bcm_switch_agm_id_t *agm_id) 6358 { 6359 int rv = BCM_E_UNAVAIL; 6360 6361 #if defined(BCM_TOMAHAWK_SUPPORT) 6362 if (soc_feature(unit, soc_feature_agm)) { 6363 TRUNK_LOCK(unit); 6364 rv = bcm_th_trunk_agm_attach_get(unit, trunk_id, agm_id); 6365 TRUNK_UNLOCK(unit); 6366 } 6367 #endif /* BCM_TOMAHAWK_SUPPORT */ 6368 return rv; 6369 } 6370 6371 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 6372 /* 6373 * Function : _bcm_esw_trunk_gport_add 6374 * Description : Add the GPORT ID for the specified trunk. 6375 * 6376 * Parameters : (IN) unit - BCM device number 6377 * (IN) tid - Trunk Group 6378 * (IN) gport - GPORT ID 6379 * Returns : BCM_E_XXX 6380 */ 6381 int 6382 _bcm_esw_trunk_gport_add(int unit, bcm_trunk_t tid, bcm_gport_t gport) 6383 { 6384 int id_out = 0; 6385 int result = FALSE; 6386 int is_trunk = 0; 6387 int base_index = 0; 6388 int subport_index = 0; 6389 bcm_port_t port_out = 0; 6390 bcm_module_t mod_out = 0; 6391 bcm_trunk_t tgid_out = 0; 6392 bcm_trunk_t old_tid = 0; 6393 modid_base_ptr_entry_t modid_base_entry; 6394 modport_map_subport_entry_t modport_map_subport_entry; 6395 trunk_private_t *t_info; 6396 6397 /* Make sure trunk module is initialized. */ 6398 TRUNK_INIT(unit); 6399 6400 /* Parameter check */ 6401 if (!TRUNK_FABRIC_TID(unit, tid)) { 6402 return BCM_E_PARAM; 6403 } 6404 6405 t_info = &TRUNK_INFO(unit, tid); 6406 if (t_info->tid == BCM_TRUNK_INVALID) { 6407 return BCM_E_NOT_FOUND; 6408 } 6409 6410 tid -= TRUNK_CNTL(unit).ngroups_fp; 6411 6412 if (!BCM_GPORT_IS_MODPORT(gport)) { 6413 return BCM_E_PARAM; 6414 } 6415 6416 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport, 6417 &mod_out, &port_out, &tgid_out, &id_out)); 6418 if ((-1 != tgid_out) || (-1 != id_out)) { 6419 return BCM_E_PARAM; 6420 } 6421 6422 /* Check modport in one of additional module */ 6423 BCM_IF_ERROR_RETURN ( 6424 _bcm_esw_my_modid_additional_check(unit, mod_out, &result)); 6425 if (result == FALSE) { 6426 return BCM_E_PARAM; 6427 } 6428 6429 mod_out %= 64; /* lower 6 bit */ 6430 SOC_IF_ERROR_RETURN 6431 (READ_MODID_BASE_PTRm(unit, MEM_BLOCK_ANY, mod_out, 6432 &modid_base_entry)); 6433 base_index = soc_MODID_BASE_PTRm_field32_get(unit, 6434 &modid_base_entry, MODID_BASEf); 6435 subport_index = base_index; /* the index is indicated by module base ptr */ 6436 SOC_IF_ERROR_RETURN 6437 (READ_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, subport_index, 6438 &modport_map_subport_entry)); 6439 is_trunk = soc_MODPORT_MAP_SUBPORTm_field32_get(unit, 6440 &modport_map_subport_entry, ISTRUNKf); 6441 old_tid = soc_MODPORT_MAP_SUBPORTm_field32_get(unit, 6442 &modport_map_subport_entry, DESTf); 6443 if (is_trunk && (old_tid == tid)) { 6444 return BCM_E_NONE; 6445 } 6446 if (is_trunk && old_tid >= 0) { 6447 return BCM_E_RESOURCE; 6448 } 6449 6450 soc_MODPORT_MAP_SUBPORTm_field32_set (unit, 6451 &modport_map_subport_entry, DESTf, tid); 6452 soc_MODPORT_MAP_SUBPORTm_field32_set (unit, 6453 &modport_map_subport_entry, ISTRUNKf, 1); 6454 soc_MODPORT_MAP_SUBPORTm_field32_set (unit, 6455 &modport_map_subport_entry, ENABLEf, 1); 6456 SOC_IF_ERROR_RETURN 6457 (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, subport_index, 6458 &modport_map_subport_entry)); 6459 6460 return BCM_E_NONE; 6461 } 6462 6463 /* 6464 * Function : _bcm_esw_trunk_gport_get_all 6465 * Description : Add the GPORT ID for the specified trunk. 6466 * 6467 * Parameters : (IN) unit - BCM device number 6468 * (IN) tid - Trunk Group 6469 * (IN) gport_size - GPORT ID 6470 (OUT) gport_array - GPORT Array 6471 (OUT) count - GPORT Count 6472 * Returns : BCM_E_XXX 6473 */ 6474 int 6475 _bcm_esw_trunk_gport_get_all(int unit, bcm_trunk_t tid, int gport_size, 6476 bcm_gport_t *gport_array, int *count) 6477 { 6478 int rv = BCM_E_NONE; 6479 int mod_idx = 0; 6480 int port_idx = 0; 6481 int is_trunk = 0; 6482 int base_index = 0; 6483 bcm_gport_t modport = 0; 6484 _bcm_gport_dest_t dest; 6485 bcm_trunk_t egress_tid = 0; 6486 bcm_stk_modid_config_t mod_cfg; 6487 modid_base_ptr_entry_t modid_base_entry; 6488 modport_map_subport_entry_t modport_map_subport_entry; 6489 trunk_private_t *t_info; 6490 6491 /* Make sure trunk module is initialized. */ 6492 TRUNK_INIT(unit); 6493 6494 /* Parameter check */ 6495 if (!TRUNK_FABRIC_TID(unit, tid)) { 6496 return BCM_E_PARAM; 6497 } 6498 6499 t_info = &TRUNK_INFO(unit, tid); 6500 if (t_info->tid == BCM_TRUNK_INVALID) { 6501 return BCM_E_NOT_FOUND; 6502 } 6503 6504 tid -= TRUNK_CNTL(unit).ngroups_fp; 6505 6506 if (gport_size < 0 || count == NULL) { 6507 return BCM_E_PARAM; 6508 } 6509 6510 if ((gport_size > 0) && gport_array == NULL) { 6511 return BCM_E_PARAM; 6512 } 6513 6514 mod_cfg.modid_type = bcmStkModidTypeMultiNextHops; 6515 BCM_IF_ERROR_RETURN(bcm_esw_stk_modid_config_get(unit, &mod_cfg)); 6516 6517 *count = 0; 6518 if (gport_size == 0) { 6519 for (mod_idx = mod_cfg.modid; mod_idx < mod_cfg.modid + mod_cfg.num_mods; 6520 mod_idx ++) { 6521 mod_idx %= 64; /* lower 6 bit */ 6522 SOC_IF_ERROR_RETURN 6523 (READ_MODID_BASE_PTRm(unit, MEM_BLOCK_ANY, mod_idx, &modid_base_entry)); 6524 base_index = soc_MODID_BASE_PTRm_field32_get(unit, 6525 &modid_base_entry, MODID_BASEf); 6526 /* Search for unused index. */ 6527 for (port_idx = base_index; port_idx < base_index + mod_cfg.num_ports; 6528 port_idx++) { 6529 SOC_IF_ERROR_RETURN 6530 (READ_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, port_idx, 6531 &modport_map_subport_entry)); 6532 is_trunk = soc_MODPORT_MAP_SUBPORTm_field32_get(unit, 6533 &modport_map_subport_entry, ISTRUNKf); 6534 /* Check if index is used. */ 6535 egress_tid = soc_MODPORT_MAP_SUBPORTm_field32_get(unit, 6536 &modport_map_subport_entry, DESTf); 6537 if (is_trunk && (egress_tid == tid)) {/* Entry found. */ 6538 (*count)++; 6539 } 6540 } 6541 } 6542 return BCM_E_NONE; 6543 } 6544 6545 _bcm_gport_dest_t_init(&dest); 6546 for (mod_idx = mod_cfg.modid; mod_idx < mod_cfg.modid + mod_cfg.num_mods; 6547 mod_idx ++) { 6548 mod_idx %= 64; /* lower 6 bit */ 6549 SOC_IF_ERROR_RETURN 6550 (READ_MODID_BASE_PTRm(unit, MEM_BLOCK_ANY, mod_idx, &modid_base_entry)); 6551 base_index = soc_MODID_BASE_PTRm_field32_get(unit, 6552 &modid_base_entry, MODID_BASEf); 6553 /* Search for unused index. */ 6554 for (port_idx = base_index; port_idx < base_index + mod_cfg.num_ports; 6555 port_idx++) { 6556 if ((*count) < gport_size) { 6557 SOC_IF_ERROR_RETURN 6558 (READ_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, port_idx, 6559 &modport_map_subport_entry)); 6560 is_trunk = soc_MODPORT_MAP_SUBPORTm_field32_get(unit, 6561 &modport_map_subport_entry, ISTRUNKf); 6562 /* Check if index is used. */ 6563 egress_tid = soc_MODPORT_MAP_SUBPORTm_field32_get(unit, 6564 &modport_map_subport_entry, DESTf); 6565 if (is_trunk && (egress_tid == tid)) { 6566 /* Entry found. */ 6567 dest.port = port_idx; 6568 dest.modid = mod_idx; 6569 dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 6570 rv = _bcm_esw_gport_construct(unit, &dest, &modport); 6571 gport_array[(*count)++] = modport; 6572 } 6573 } 6574 } 6575 } 6576 6577 return rv; 6578 6579 } 6580 6581 /* 6582 * Function : _bcm_esw_trunk_gport_delete 6583 * Description : Delete the GPORT ID for the specified trunk. 6584 * 6585 * Parameters : (IN) unit - BCM device number 6586 * (IN) tid - Trunk Group 6587 * (IN) gport - GPORT ID 6588 * Returns : BCM_E_XXX 6589 */ 6590 int 6591 _bcm_esw_trunk_gport_delete(int unit, bcm_trunk_t tid, bcm_gport_t gport) 6592 { 6593 int id_out = 0; 6594 int base_index = 0; 6595 int is_trunk = 0; 6596 int result = FALSE; 6597 int subport_index = 0; 6598 bcm_port_t port_out = 0; 6599 bcm_module_t mod_out = 0; 6600 bcm_trunk_t tgid_out = 0; 6601 modid_base_ptr_entry_t modid_base_entry; 6602 modport_map_subport_entry_t modport_map_subport_entry; 6603 trunk_private_t *t_info; 6604 6605 /* Make sure trunk module is initialized. */ 6606 TRUNK_INIT(unit); 6607 6608 /* Parameter check */ 6609 if (!TRUNK_FABRIC_TID(unit, tid)) { 6610 return BCM_E_PARAM; 6611 } 6612 6613 t_info = &TRUNK_INFO(unit, tid); 6614 if (t_info->tid == BCM_TRUNK_INVALID) { 6615 return BCM_E_NOT_FOUND; 6616 } 6617 tid -= TRUNK_CNTL(unit).ngroups_fp; 6618 6619 if (!BCM_GPORT_IS_MODPORT(gport)) { 6620 return BCM_E_PARAM; 6621 } 6622 6623 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport, 6624 &mod_out, &port_out, &tgid_out, &id_out)); 6625 if ((-1 != tgid_out) || (-1 != id_out)) { 6626 return BCM_E_PARAM; 6627 } 6628 6629 /* Check modport in one of additional module */ 6630 BCM_IF_ERROR_RETURN ( 6631 _bcm_esw_my_modid_additional_check(unit, mod_out, &result)); 6632 if (result == FALSE) { 6633 return BCM_E_PARAM; 6634 } 6635 6636 mod_out %= 64; /* lower 6 bit */ 6637 SOC_IF_ERROR_RETURN 6638 (READ_MODID_BASE_PTRm(unit, MEM_BLOCK_ANY, mod_out, 6639 &modid_base_entry)); 6640 base_index = soc_MODID_BASE_PTRm_field32_get(unit, 6641 &modid_base_entry, MODID_BASEf); 6642 subport_index = base_index; /* the index is indicated by module base ptr */ 6643 SOC_IF_ERROR_RETURN 6644 (READ_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, subport_index, 6645 &modport_map_subport_entry)); 6646 is_trunk = soc_MODPORT_MAP_SUBPORTm_field32_get(unit, 6647 &modport_map_subport_entry, ISTRUNKf); 6648 if (!is_trunk) { 6649 return BCM_E_NOT_FOUND; 6650 } 6651 soc_MODPORT_MAP_SUBPORTm_field32_set(unit, 6652 &modport_map_subport_entry, DESTf, 0); 6653 soc_MODPORT_MAP_SUBPORTm_field32_set (unit, 6654 &modport_map_subport_entry, ISTRUNKf, 0); 6655 soc_MODPORT_MAP_SUBPORTm_field32_set (unit, 6656 &modport_map_subport_entry, ENABLEf, 0); 6657 SOC_IF_ERROR_RETURN 6658 (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, subport_index, 6659 &modport_map_subport_entry)); 6660 6661 return BCM_E_NONE; 6662 } 6663 6664 /* 6665 * Function : _bcm_esw_trunk_gport_delete_all 6666 * Description : Delete the GPORT ID for the specified trunk. 6667 * 6668 * Parameters : (IN) unit - BCM device number 6669 * (IN) tid - Trunk Group 6670 * Returns : BCM_E_XXX 6671 */ 6672 int 6673 _bcm_esw_trunk_gport_delete_all(int unit, bcm_trunk_t tid) 6674 { 6675 int mod_idx = 0; 6676 int port_idx = 0; 6677 int is_trunk = 0; 6678 int base_index = 0; 6679 bcm_trunk_t egress_tid = 0; 6680 bcm_stk_modid_config_t mod_cfg; 6681 modid_base_ptr_entry_t modid_base_entry; 6682 modport_map_subport_entry_t modport_map_subport_entry; 6683 trunk_private_t *t_info; 6684 6685 /* Make sure trunk module is initialized. */ 6686 TRUNK_INIT(unit); 6687 6688 /* Parameter check */ 6689 if (!TRUNK_FABRIC_TID(unit, tid)) { 6690 return BCM_E_PARAM; 6691 } 6692 t_info = &TRUNK_INFO(unit, tid); 6693 if (t_info->tid == BCM_TRUNK_INVALID) { 6694 return BCM_E_NOT_FOUND; 6695 } 6696 tid -= TRUNK_CNTL(unit).ngroups_fp; 6697 6698 mod_cfg.modid_type = bcmStkModidTypeMultiNextHops; 6699 BCM_IF_ERROR_RETURN( 6700 bcm_esw_stk_modid_config_get(unit, &mod_cfg)); 6701 6702 for (mod_idx = mod_cfg.modid; mod_idx < mod_cfg.modid + mod_cfg.num_mods; 6703 mod_idx ++) { 6704 mod_idx %= 64; /* lower 6 bit */ 6705 SOC_IF_ERROR_RETURN 6706 (READ_MODID_BASE_PTRm(unit, MEM_BLOCK_ANY, mod_idx, &modid_base_entry)); 6707 base_index = soc_MODID_BASE_PTRm_field32_get(unit, 6708 &modid_base_entry, MODID_BASEf); 6709 /* Search for unused index. */ 6710 for (port_idx = base_index; port_idx < base_index + mod_cfg.num_ports; 6711 port_idx++) { 6712 SOC_IF_ERROR_RETURN 6713 (READ_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, port_idx, 6714 &modport_map_subport_entry)); 6715 is_trunk = soc_MODPORT_MAP_SUBPORTm_field32_get(unit, 6716 &modport_map_subport_entry, ISTRUNKf); 6717 /* Check if index is used. */ 6718 egress_tid = soc_MODPORT_MAP_SUBPORTm_field32_get(unit, 6719 &modport_map_subport_entry, DESTf); 6720 if (is_trunk && (egress_tid == tid)) { 6721 /* Entry found. */ 6722 soc_MODPORT_MAP_SUBPORTm_field32_set (unit, 6723 &modport_map_subport_entry, DESTf, 0); 6724 soc_MODPORT_MAP_SUBPORTm_field32_set (unit, 6725 &modport_map_subport_entry, ISTRUNKf, 0); 6726 soc_MODPORT_MAP_SUBPORTm_field32_set (unit, 6727 &modport_map_subport_entry, ENABLEf, 0); 6728 SOC_IF_ERROR_RETURN 6729 (WRITE_MODPORT_MAP_SUBPORTm(unit, MEM_BLOCK_ANY, port_idx, 6730 &modport_map_subport_entry)); 6731 } 6732 } 6733 } 6734 6735 return BCM_E_NONE; 6736 } 6737 6738 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 6739 6740 /* 6741 * Function : bcm_esw_trunk_gport_add 6742 * Description : Add the GPORT ID for the specified trunk. 6743 * 6744 * Parameters : (IN) unit - BCM device number 6745 * (IN) tid - Trunk Group 6746 * (IN) gport - GPORT ID 6747 * Returns : BCM_E_XXX 6748 */ 6749 int 6750 bcm_esw_trunk_gport_add(int unit, bcm_trunk_t tid, bcm_gport_t gport) 6751 { 6752 int rv = BCM_E_UNAVAIL; 6753 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 6754 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 6755 rv = _bcm_esw_trunk_gport_add(unit, tid, gport); 6756 } 6757 #endif 6758 return rv; 6759 } 6760 6761 /* 6762 * Function : bcm_esw_trunk_gport_get_all 6763 * Description : Add the GPORT ID for the specified trunk. 6764 * 6765 * Parameters : (IN) unit - BCM device number 6766 * (IN) tid - Trunk Group 6767 * (IN) gport_size - GPORT ID 6768 (OUT) gport_array - GPORT Array 6769 (OUT) count - GPORT Count 6770 * Returns : BCM_E_XXX 6771 */ 6772 int 6773 bcm_esw_trunk_gport_get_all(int unit, bcm_trunk_t tid, int gport_size, 6774 bcm_gport_t *gport_array, int *count) 6775 { 6776 int rv = BCM_E_UNAVAIL; 6777 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 6778 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 6779 if (gport_size < 0 || count == NULL) { 6780 return BCM_E_PARAM; 6781 } 6782 6783 if ((gport_size > 0) && gport_array == NULL) { 6784 return BCM_E_PARAM; 6785 } 6786 6787 rv = _bcm_esw_trunk_gport_get_all(unit, tid, gport_size, gport_array, count); 6788 } 6789 #endif 6790 return rv; 6791 } 6792 6793 /* 6794 * Function : bcm_esw_trunk_gport_delete 6795 * Description : Delete the GPORT ID for the specified trunk. 6796 * 6797 * Parameters : (IN) unit - BCM device number 6798 * (IN) tid - Trunk Group 6799 * (IN) gport - GPORT ID 6800 * Returns : BCM_E_XXX 6801 */ 6802 int 6803 bcm_esw_trunk_gport_delete(int unit, bcm_trunk_t tid, bcm_gport_t gport) 6804 { 6805 int rv = BCM_E_UNAVAIL; 6806 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 6807 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 6808 rv = _bcm_esw_trunk_gport_delete(unit, tid, gport); 6809 } 6810 #endif 6811 return rv; 6812 } 6813 6814 /* 6815 * Function : bcm_esw_trunk_gport_delete_all 6816 * Description : Delete the GPORT ID for the specified trunk. 6817 * 6818 * Parameters : (IN) unit - BCM device number 6819 * (IN) tid - Trunk Group 6820 * Returns : BCM_E_XXX 6821 */ 6822 int 6823 bcm_esw_trunk_gport_delete_all(int unit, bcm_trunk_t tid) 6824 { 6825 int rv = BCM_E_UNAVAIL; 6826 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 6827 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 6828 rv = _bcm_esw_trunk_gport_delete_all(unit, tid); 6829 } 6830 #endif 6831 return rv; 6832 } 6833 6834 /* 6835 * Function: 6836 * _bcm_esw_trunk_local_members_get 6837 * Purpose: 6838 * Get local member ports of a trunk group. 6839 * Parameters: 6840 * unit - (IN) Device Number 6841 * trunk_id - (IN) Trunk Identifier 6842 * local_member_max - (OUT) Size of local_member_array 6843 * local_member_array - (OUT) Array of local trunk members 6844 * local_member_count - (OUT) Number of local trunk members 6845 * Returns: 6846 * BCM_E_XXX 6847 * Notes: 6848 * If local_member_max = 0 and local_member_array == NULL, 6849 * the number of local trunk members will still be returned in 6850 * local_member_count. 6851 */ 6852 6853 int 6854 _bcm_esw_trunk_local_members_get(int unit, bcm_trunk_t trunk_id, 6855 int local_member_max, 6856 bcm_port_t *local_member_array, 6857 int *local_member_count) 6858 { 6859 int rv; 6860 int member_count; 6861 bcm_trunk_member_t *member_array; 6862 int i; 6863 bcm_module_t mod_out; 6864 bcm_port_t port_out; 6865 bcm_trunk_t tgid_out; 6866 int id_out; 6867 int modid_local; 6868 bcm_trunk_info_t trunk_info; 6869 #if defined(BCM_KATANA2_SUPPORT) 6870 int local_subport = 0; 6871 #endif 6872 6873 if (local_member_max < 0) { 6874 return BCM_E_PARAM; 6875 } 6876 6877 if ((local_member_max == 0) && (NULL != local_member_array)) { 6878 return BCM_E_PARAM; 6879 } 6880 6881 if ((local_member_max > 0) && (NULL == local_member_array)) { 6882 return BCM_E_PARAM; 6883 } 6884 6885 if (NULL == local_member_count) { 6886 return BCM_E_PARAM; 6887 } 6888 6889 *local_member_count = 0; 6890 6891 BCM_IF_ERROR_RETURN(_bcm_trunk_id_validate(unit, trunk_id)); 6892 6893 /* First, get the number of trunk members. */ 6894 rv = bcm_esw_trunk_get(unit, trunk_id, &trunk_info, 0, NULL, &member_count); 6895 if (BCM_FAILURE(rv)) { 6896 return BCM_E_PORT; 6897 } 6898 6899 if (0 == member_count) { 6900 return BCM_E_NONE; 6901 } 6902 6903 member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count, 6904 "trunk member array"); 6905 if (member_array == NULL) { 6906 return BCM_E_MEMORY; 6907 } 6908 sal_memset(member_array, 0, sizeof(bcm_trunk_member_t) * member_count); 6909 6910 rv = bcm_esw_trunk_get(unit, trunk_id, &trunk_info, member_count, 6911 member_array, &member_count); 6912 if (BCM_FAILURE(rv)) { 6913 sal_free(member_array); 6914 return BCM_E_PORT; 6915 } 6916 6917 for (i = 0; i < member_count; i++) { 6918 rv = _bcm_esw_gport_resolve(unit, member_array[i].gport, 6919 &mod_out, &port_out, &tgid_out, &id_out); 6920 if (BCM_FAILURE(rv)) { 6921 sal_free(member_array); 6922 return rv; 6923 } 6924 6925 #if defined(BCM_KATANA2_SUPPORT) 6926 /* Coverity fix for leaked_storage issue. Freeing member_array 6927 if the function returns with error */ 6928 rv = _bcm_kt2_modport_is_local_coe_subport(unit, 6929 mod_out, port_out, &local_subport); 6930 if (BCM_FAILURE(rv)) { 6931 sal_free(member_array); 6932 return rv; 6933 } 6934 if (local_subport) { 6935 if (NULL != local_member_array) { 6936 local_member_array[*local_member_count] = 6937 BCM_GPORT_SUBPORT_PORT_GET(member_array[i].gport); 6938 } 6939 (*local_member_count)++; 6940 if (*local_member_count == local_member_max) { 6941 break; 6942 } 6943 } 6944 #endif 6945 6946 #ifdef BCM_HGPROXY_COE_SUPPORT 6947 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 6948 _bcm_xgs5_subport_coe_mod_port_local(unit, mod_out, port_out)) { 6949 rv = _bcmi_coe_subport_mod_port_physical_port_get( 6950 unit, mod_out, port_out, &port_out); 6951 if (BCM_FAILURE(rv)) { 6952 sal_free(member_array); 6953 return rv; 6954 } 6955 modid_local = 1; 6956 } else 6957 #endif 6958 { 6959 rv = _bcm_esw_modid_is_local(unit, mod_out, &modid_local); 6960 if (BCM_FAILURE(rv)) { 6961 sal_free(member_array); 6962 return rv; 6963 } 6964 } 6965 6966 if (modid_local) { 6967 /* Convert system port to physical port */ 6968 if (soc_feature(unit, soc_feature_sysport_remap)) { 6969 BCM_XLATE_SYSPORT_S2P(unit, &port_out); 6970 } 6971 6972 if (NULL != local_member_array) { 6973 local_member_array[*local_member_count] = port_out; 6974 } 6975 (*local_member_count)++; 6976 if (*local_member_count == local_member_max) { 6977 break; 6978 } 6979 } 6980 } 6981 6982 sal_free(member_array); 6983 6984 return BCM_E_NONE; 6985 } 6986 6987 #ifdef BCM_WARM_BOOT_SUPPORT 6988 6989 #define TRUNK_MIN_FABRIC_TID(unit) \ 6990 (TRUNK_CNTL(unit).ngroups_hg ? TRUNK_CNTL(unit).ngroups_fp : -1) 6991 #define TRUNK_MAX_FABRIC_TID(unit) \ 6992 ( TRUNK_CNTL(unit).ngroups_hg ? \ 6993 (TRUNK_CNTL(unit).ngroups_fp + TRUNK_CNTL(unit).ngroups_hg - 1): -1) 6994 6995 /* 6996 * _bcm_trunk_lag_reinit 6997 * 6998 * Restores sw state for front pannel trunks 6999 * Note: Application must register modid-port mapping function 7000 * using bcm_stk_modmap_register before calling this 7001 */ 7002 STATIC int 7003 _bcm_trunk_lag_reinit(int unit) 7004 { 7005 #if defined(BCM_TRIDENT_SUPPORT) 7006 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7007 return (_bcm_trident_trunk_lag_reinit(unit, TRUNK_CNTL(unit).ngroups_fp, 7008 TRUNK_CNTL(unit).t_info)); 7009 } else 7010 #ifdef BCM_TOMAHAWK3_SUPPORT 7011 if (SOC_IS_TOMAHAWK3(unit)) { 7012 7013 return (_bcm_th3_trunk_lag_reinit(unit, TRUNK_CNTL(unit).ngroups_fp, 7014 TRUNK_CNTL(unit).t_info)); 7015 } else 7016 #endif /*BCM_TOMAHAWK3_SUPPORT*/ 7017 #endif /* BCM_TRIDENT_SUPPORT */ 7018 7019 #if defined(BCM_FIREBOLT_SUPPORT) 7020 if (SOC_IS_FBX(unit)) { 7021 return (_xgs3_trunk_reinit(unit, TRUNK_CNTL(unit).ngroups_fp, 7022 TRUNK_CNTL(unit).t_info)); 7023 } 7024 #endif /* BCM_FIREBOLT_SUPPORT */ 7025 7026 return BCM_E_NONE; 7027 } 7028 7029 /* 7030 * _bcm_trunk_fabric_reinit 7031 * 7032 * Restores sw state for fabric trunks 7033 */ 7034 STATIC int 7035 _bcm_trunk_fabric_reinit(int unit) 7036 { 7037 #if defined(BCM_TRIDENT_SUPPORT) 7038 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7039 int min_tid = TRUNK_MIN_FABRIC_TID(unit); 7040 7041 return (_bcm_trident_trunk_fabric_reinit(unit, 7042 TRUNK_MIN_FABRIC_TID(unit), 7043 TRUNK_MAX_FABRIC_TID(unit), 7044 &TRUNK_INFO(unit,min_tid))); 7045 } else 7046 #endif /* BCM_TRIDENT_SUPPORT */ 7047 #if defined(BCM_FIREBOLT_SUPPORT) 7048 if (SOC_IS_FBX(unit) && !SOC_IS_RAPTOR(unit)) { 7049 int min_tid = TRUNK_MIN_FABRIC_TID(unit); 7050 if (SOC_IS_TOMAHAWKX(unit)) { 7051 if (soc_feature(unit, soc_feature_higig2)) { 7052 /* In TH, HG ports are not supported in low latency modes */ 7053 return (_xgs3_trunk_fabric_reinit(unit, 7054 TRUNK_MIN_FABRIC_TID(unit), 7055 TRUNK_MAX_FABRIC_TID(unit), 7056 &TRUNK_INFO(unit,min_tid))); 7057 } 7058 } else { 7059 return (_xgs3_trunk_fabric_reinit(unit, 7060 TRUNK_MIN_FABRIC_TID(unit), 7061 TRUNK_MAX_FABRIC_TID(unit), 7062 &TRUNK_INFO(unit,min_tid))); 7063 } 7064 } 7065 #endif /* BCM_FIREBOLT_SUPPORT */ 7066 7067 return BCM_E_NONE; 7068 } 7069 7070 /* 7071 * _bcm_trunk_reinit 7072 * 7073 * Recovers trunk state from hardware (Reload) 7074 */ 7075 int 7076 _bcm_trunk_reinit(int unit) 7077 { 7078 int rv; 7079 bcm_trunk_t tid; 7080 trunk_private_t *t_info; 7081 soc_scache_handle_t scache_handle; 7082 uint8 *trunk_scache; 7083 uint16 recovered_ver; 7084 uint32 ngroups; 7085 uint8 flags; 7086 int recovered_dlf_index; 7087 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 7088 bcm_trunk_t hgtid; 7089 int tix, idx; 7090 int fp_hwf_recover = 1; 7091 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 7092 uint32 additional_scache_size; 7093 #if defined(BCM_SABER2_SUPPORT) 7094 uint32 fp_ngroups = 0; 7095 uint32 hg_ngroups = 0; 7096 uint16 default_ver = BCM_WB_DEFAULT_VERSION; 7097 #endif /* BCM_SABER2_SUPPORT */ 7098 7099 /* 7100 * Trunk state initialization 7101 */ 7102 t_info = TRUNK_CNTL(unit).t_info; 7103 7104 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRUNK, 0); 7105 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 7106 0, &trunk_scache, 7107 BCM_WB_DEFAULT_VERSION, &recovered_ver); 7108 7109 if (BCM_E_NOT_FOUND == rv) { 7110 trunk_scache = NULL; 7111 } else if (BCM_FAILURE(rv)) { 7112 return rv; 7113 } else { 7114 /* Validate trunk info matches */ 7115 #if defined(BCM_SABER2_SUPPORT) 7116 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) && 7117 (recovered_ver <= BCM_WB_VERSION_1_4) && 7118 (default_ver > BCM_WB_VERSION_1_4)) { 7119 sal_memcpy(&fp_ngroups, trunk_scache, sizeof(ngroups)); 7120 ngroups = SABER2_5626X_NGROUPS_FP; 7121 } else 7122 #endif /* BCM_SABER2_SUPPORT */ 7123 { 7124 sal_memcpy(&ngroups, trunk_scache, sizeof(ngroups)); 7125 } 7126 if (ngroups != TRUNK_CNTL(unit).ngroups_fp) { 7127 return BCM_E_CONFIG; 7128 } 7129 trunk_scache += sizeof(ngroups); 7130 7131 #if defined(BCM_SABER2_SUPPORT) 7132 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) && 7133 (recovered_ver <= BCM_WB_VERSION_1_4) && 7134 (default_ver > BCM_WB_VERSION_1_4)) { 7135 sal_memcpy(&hg_ngroups, trunk_scache, sizeof(ngroups)); 7136 ngroups = SABER2_5626X_NGROUPS_HG; 7137 } else 7138 #endif /* BCM_SABER2_SUPPORT */ 7139 { 7140 sal_memcpy(&ngroups, trunk_scache, sizeof(ngroups)); 7141 } 7142 if (ngroups != TRUNK_CNTL(unit).ngroups_hg) { 7143 return BCM_E_CONFIG; 7144 } 7145 trunk_scache += sizeof(ngroups); 7146 7147 sal_memset(TRUNK_CNTL(unit).trunk_bmp_ptr, 0, 7148 TRUNK_CNTL(unit).trunk_bmp_alloc); 7149 sal_memcpy(TRUNK_CNTL(unit).trunk_bmp_ptr, trunk_scache, 7150 TRUNK_CNTL(unit).trunk_bmp_alloc); 7151 7152 for (tid = 0; tid < TRUNK_NUM_GROUPS(unit); tid++) { 7153 if (SHR_BITGET(TRUNK_CNTL(unit).trunk_bmp_ptr, tid)) { 7154 t_info->tid = tid; 7155 } 7156 t_info++; 7157 } 7158 #if defined(BCM_SABER2_SUPPORT) 7159 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) && 7160 (recovered_ver <= BCM_WB_VERSION_1_4) && 7161 (default_ver > BCM_WB_VERSION_1_4)) { 7162 int tmp_trunk_bmp_alloc = SHR_BITALLOCSIZE(fp_ngroups + hg_ngroups); 7163 trunk_scache += tmp_trunk_bmp_alloc; 7164 } else 7165 #endif /* BCM_SABER2_SUPPORT */ 7166 { 7167 trunk_scache += TRUNK_CNTL(unit).trunk_bmp_alloc; 7168 } 7169 7170 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 7171 #if defined(BCM_TRIDENT2_SUPPORT) 7172 /* WarmBoot recovery support for front panel ports hardware failover 7173 * configuration(for scorpion) is always present in SDK. 7174 * But hardware failover support for front panel ports in Trident2 7175 * is added when trunk scache is at WB version 1.3 by enabling the 7176 * corresponding soc_feature. A new version 1.4 is introducted to 7177 * recover front panel hardware failover configuration on Trident2. 7178 */ 7179 if (SOC_IS_TRIDENT2(unit) && recovered_ver <= BCM_WB_VERSION_1_3) { 7180 fp_hwf_recover = 0; 7181 } 7182 #endif /* BCM_TRIDENT2_SUPPORT */ 7183 7184 if ((TRUNK_CNTL(unit).fp_hwf_alloc) && (fp_hwf_recover)) { 7185 idx = 0; 7186 sal_memcpy(TRUNK_CNTL(unit).fp_hwf_flags, trunk_scache, 7187 TRUNK_CNTL(unit).fp_hwf_alloc); 7188 #if defined(BCM_SABER2_SUPPORT) 7189 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) && 7190 (recovered_ver <= BCM_WB_VERSION_1_4) && 7191 (default_ver > BCM_WB_VERSION_1_4)) { 7192 int tmp_fp_hwf_alloc = (fp_ngroups * 3 + 7193 soc_mem_index_count(unit, SOURCE_TRUNK_MAP_TABLEm)) * 7194 sizeof(uint8); 7195 trunk_scache += tmp_fp_hwf_alloc; 7196 } else 7197 #endif /* BCM_SABER2_SUPPORT */ 7198 { 7199 trunk_scache += TRUNK_CNTL(unit).fp_hwf_alloc; 7200 } 7201 7202 if (soc_feature(unit, soc_feature_port_lag_failover)) { 7203 /* FP trunk failover flags */ 7204 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7205 TRUNK_INFO(unit, tid).flags = 7206 TRUNK_CNTL(unit).fp_hwf_flags[idx++]; 7207 #ifdef BCM_TRIDENT_SUPPORT 7208 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7209 uint16 num_ports; 7210 num_ports = TRUNK_CNTL(unit).fp_hwf_flags[idx++] << 8; 7211 num_ports += TRUNK_CNTL(unit).fp_hwf_flags[idx++]; 7212 _bcm_trident_hw_failover_num_ports_set(unit, tid, 7213 FALSE, num_ports); 7214 for (tix = 0; tix < num_ports; tix++) { 7215 BCM_IF_ERROR_RETURN 7216 (_bcm_trident_hw_failover_flags_set(unit, tid, 7217 tix, FALSE, 7218 TRUNK_CNTL(unit).fp_hwf_flags[idx++])); 7219 } 7220 7221 } else 7222 #ifdef BCM_TOMAHAWK3_SUPPORT 7223 if (SOC_IS_TOMAHAWK3(unit)) { 7224 uint16 num_ports; 7225 num_ports = TRUNK_CNTL(unit).fp_hwf_flags[idx++] << 8; 7226 num_ports += TRUNK_CNTL(unit).fp_hwf_flags[idx++]; 7227 _bcm_th3_trunk_hwfailover_num_ports_set(unit, tid, 7228 num_ports); 7229 for (tix = 0; tix < num_ports; tix++) { 7230 _bcm_th3_trunk_hwfailover_flags_set(unit, tid, 7231 tix, TRUNK_CNTL(unit).fp_hwf_flags[idx++]); 7232 } 7233 7234 } else 7235 #endif 7236 #endif /* BCM_TRIDENT_SUPPORT */ 7237 { 7238 for (tix = 0; tix < TRUNK_CNTL(unit).nports_fp; tix++) { 7239 _bcm_xgs3_hw_failover_flags_set(unit, tid, 7240 tix, FALSE, 7241 TRUNK_CNTL(unit).fp_hwf_flags[idx++]); 7242 } 7243 } 7244 } 7245 } 7246 } 7247 7248 if (TRUNK_CNTL(unit).hg_hwf_alloc) { 7249 idx = 0; 7250 7251 sal_memcpy(TRUNK_CNTL(unit).hg_hwf_flags, trunk_scache, 7252 TRUNK_CNTL(unit).hg_hwf_alloc); 7253 #if defined(BCM_SABER2_SUPPORT) 7254 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) && 7255 (recovered_ver <= BCM_WB_VERSION_1_4) && 7256 (default_ver > BCM_WB_VERSION_1_4)) { 7257 int tmp_hg_hwf_alloc = (hg_ngroups * (hg_ngroups + 1)) * 7258 sizeof(uint8); 7259 trunk_scache += tmp_hg_hwf_alloc; 7260 } else 7261 #endif /* BCM_SABER2_SUPPORT */ 7262 { 7263 trunk_scache += TRUNK_CNTL(unit).hg_hwf_alloc; 7264 } 7265 7266 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 7267 /* HG trunk failover flags */ 7268 for (tid = TRUNK_CNTL(unit).ngroups_fp; 7269 tid < TRUNK_NUM_GROUPS(unit); tid++) { 7270 TRUNK_INFO(unit, tid).flags = 7271 TRUNK_CNTL(unit).hg_hwf_flags[idx++]; 7272 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp; 7273 #ifdef BCM_TRIDENT_SUPPORT 7274 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7275 uint16 num_ports; 7276 num_ports = TRUNK_CNTL(unit).hg_hwf_flags[idx++]; 7277 _bcm_trident_hw_failover_num_ports_set(unit, hgtid, 7278 TRUE, num_ports); 7279 for (tix = 0; tix < num_ports; tix++) { 7280 _bcm_trident_hw_failover_flags_set(unit, hgtid, 7281 tix, TRUE, 7282 TRUNK_CNTL(unit).hg_hwf_flags[idx++]); 7283 } 7284 7285 } else 7286 #endif /* BCM_TRIDENT_SUPPORT */ 7287 { 7288 for (tix = 0; tix < TRUNK_CNTL(unit).nports_hg; tix++) { 7289 _bcm_xgs3_hw_failover_flags_set(unit, hgtid, 7290 tix, TRUE, 7291 TRUNK_CNTL(unit).hg_hwf_flags[idx++]); 7292 } 7293 } 7294 } 7295 } 7296 } 7297 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 7298 7299 additional_scache_size = 0; 7300 7301 if (recovered_ver >= BCM_WB_VERSION_1_1) { 7302 /* Recover BCM_TRUNK_FLAG_IPMC_CLEAVE flag */ 7303 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7304 sal_memcpy(&flags, trunk_scache, sizeof(uint8)); 7305 trunk_scache += sizeof(uint8); 7306 if (flags & 0x1) { 7307 t_info = &TRUNK_INFO(unit, tid); 7308 t_info->flags |= BCM_TRUNK_FLAG_IPMC_CLEAVE; 7309 } 7310 } 7311 #if defined(BCM_SABER2_SUPPORT) 7312 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) && 7313 (recovered_ver <= BCM_WB_VERSION_1_4) && 7314 (default_ver > BCM_WB_VERSION_1_4)) { 7315 int tmp_ngroups_fp = 7316 (fp_ngroups - TRUNK_CNTL(unit).ngroups_fp) * 7317 sizeof(uint8); 7318 trunk_scache += tmp_ngroups_fp; 7319 } 7320 #endif /* BCM_SABER2_SUPPORT */ 7321 /* Recover ipmc_psc */ 7322 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7323 t_info = &TRUNK_INFO(unit, tid); 7324 sal_memcpy(&t_info->ipmc_psc, trunk_scache, sizeof(int)); 7325 trunk_scache += sizeof(int); 7326 } 7327 #if defined(BCM_SABER2_SUPPORT) 7328 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) && 7329 (recovered_ver <= BCM_WB_VERSION_1_4) && 7330 (default_ver > BCM_WB_VERSION_1_4)) { 7331 int tmp_ngroups_fp = 7332 (fp_ngroups - TRUNK_CNTL(unit).ngroups_fp) * 7333 sizeof(int); 7334 trunk_scache += tmp_ngroups_fp; 7335 } 7336 #endif /* BCM_SABER2_SUPPORT */ 7337 } else { 7338 additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp * 7339 sizeof(uint8)); 7340 additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp * 7341 sizeof(int)); 7342 } 7343 7344 if (recovered_ver >= BCM_WB_VERSION_1_2) { 7345 /* Recover front panel trunk membership */ 7346 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7347 #if defined(BCM_TRIDENT_SUPPORT) 7348 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7349 uint16 num_ports; 7350 uint16 *modport; 7351 uint32 *member_flags; 7352 uint8 truncated_flags; 7353 int i; 7354 7355 sal_memcpy(&num_ports, trunk_scache, sizeof(uint16)); 7356 trunk_scache += sizeof(uint16); 7357 7358 modport = sal_alloc(sizeof(uint16) * num_ports, "modport"); 7359 if (NULL == modport) { 7360 return BCM_E_MEMORY; 7361 } 7362 member_flags = sal_alloc(sizeof(uint32) * num_ports, 7363 "member_flags"); 7364 if (NULL == member_flags) { 7365 sal_free(modport); 7366 return BCM_E_MEMORY; 7367 } 7368 7369 #if defined(BCM_SABER2_SUPPORT) 7370 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) && 7371 (recovered_ver <= BCM_WB_VERSION_1_4) && 7372 (default_ver > BCM_WB_VERSION_1_4) && 7373 (num_ports > TRUNK_CNTL(unit).nports_fp)) { 7374 LOG_ERROR(BSL_LS_BCM_TRUNK, (BSL_META_U(unit, 7375 "ERROR: Maximum port supported on " 7376 "5626x devices are %d\n" 7377 "Trunk id: %d has extra %d ports " 7378 "Please remove extra ports " 7379 "re-sync and update/warm boot\n"), 7380 TRUNK_CNTL(unit).nports_fp, tid, 7381 num_ports - 7382 TRUNK_CNTL(unit).nports_fp)); 7383 sal_free(modport); 7384 sal_free(member_flags); 7385 return BCM_E_CONFIG; 7386 } 7387 #endif /* BCM_SABER2_SUPPORT */ 7388 for (i = 0; i < num_ports; i++) { 7389 sal_memcpy(&modport[i], trunk_scache, sizeof(uint16)); 7390 trunk_scache += sizeof(uint16); 7391 sal_memcpy(&truncated_flags, trunk_scache, 7392 sizeof(uint8)); 7393 trunk_scache += sizeof(uint8); 7394 member_flags[i] = truncated_flags; 7395 } 7396 rv = _bcm_trident_trunk_member_info_set(unit, tid, 7397 num_ports, modport, member_flags); 7398 sal_free(modport); 7399 sal_free(member_flags); 7400 if (BCM_FAILURE(rv)) { 7401 return rv; 7402 } 7403 } else 7404 #if defined(BCM_TOMAHAWK3_SUPPORT) 7405 if (SOC_IS_TOMAHAWK3(unit)) { 7406 uint16 num_ports; 7407 uint8 *member_port; 7408 uint32 *member_flags; 7409 uint8 truncated_flags; 7410 int i; 7411 7412 sal_memcpy(&num_ports, trunk_scache, sizeof(uint16)); 7413 trunk_scache += sizeof(uint16); 7414 if (num_ports == 0) { 7415 continue; 7416 } 7417 t_info = &TRUNK_INFO(unit, tid); 7418 t_info->in_use = 1; 7419 7420 member_port = sal_alloc(sizeof(uint8) * num_ports, "port"); 7421 if (NULL == member_port) { 7422 return BCM_E_MEMORY; 7423 } 7424 member_flags = sal_alloc(sizeof(uint32) * num_ports, 7425 "member_flags"); 7426 if (NULL == member_flags) { 7427 sal_free(member_port); 7428 return BCM_E_MEMORY; 7429 } 7430 7431 for (i = 0; i < num_ports; i++) { 7432 sal_memcpy(&member_port[i], trunk_scache, sizeof(uint8)); 7433 trunk_scache += sizeof(uint8); 7434 sal_memcpy(&truncated_flags, trunk_scache, 7435 sizeof(uint8)); 7436 trunk_scache += sizeof(uint8); 7437 member_flags[i] = truncated_flags; 7438 } 7439 rv = _bcm_th3_trunk_member_info_set(unit, tid, 7440 num_ports, member_port, member_flags); 7441 sal_free(member_port); 7442 sal_free(member_flags); 7443 if (BCM_FAILURE(rv)) { 7444 return rv; 7445 } 7446 } else 7447 #endif /* BCM_TOMAHAWK3_SUPPORT */ 7448 #endif /* BCM_TRIDENT_SUPPORT */ 7449 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7450 { 7451 uint8 num_ports = 0; 7452 uint16 *modport; 7453 uint32 *member_flags; 7454 uint8 truncated_flags; 7455 int i; 7456 7457 sal_memcpy(&num_ports, trunk_scache, sizeof(uint8)); 7458 trunk_scache += sizeof(uint8); 7459 modport = sal_alloc(sizeof(uint16) * num_ports, "modport"); 7460 if (NULL == modport) { 7461 return BCM_E_MEMORY; 7462 } 7463 member_flags = sal_alloc(sizeof(uint32) * num_ports, 7464 "member_flags"); 7465 if (NULL == member_flags) { 7466 sal_free(modport); 7467 return BCM_E_MEMORY; 7468 } 7469 7470 sal_memset(modport, 0, 7471 (sizeof(uint16) * num_ports)); 7472 sal_memset(member_flags, 0, 7473 (sizeof(uint32) * num_ports)); 7474 for (i = 0; i < num_ports; i++) { 7475 sal_memcpy(&modport[i], trunk_scache, sizeof(uint16)); 7476 trunk_scache += sizeof(uint16); 7477 sal_memcpy(&truncated_flags, trunk_scache, 7478 sizeof(uint8)); 7479 trunk_scache += sizeof(uint8); 7480 member_flags[i] = truncated_flags; 7481 } 7482 _bcm_xgs3_trunk_member_info_set(unit, tid, num_ports, 7483 modport, member_flags); 7484 sal_free(modport); 7485 sal_free(member_flags); 7486 } 7487 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7488 } 7489 #if defined(BCM_SABER2_SUPPORT) 7490 if (SOC_IS_SABER2(unit) && soc_sb2_5626x_devtype(unit) && 7491 (recovered_ver <= BCM_WB_VERSION_1_4) && 7492 (default_ver > BCM_WB_VERSION_1_4)) { 7493 for (tid = TRUNK_CNTL(unit).ngroups_fp; tid < fp_ngroups; 7494 tid++) { 7495 if (soc_feature(unit, 7496 soc_feature_shared_trunk_member_table)) { 7497 uint16 num_ports; 7498 sal_memcpy(&num_ports, trunk_scache, sizeof(uint8)); 7499 trunk_scache += sizeof(uint8); 7500 if (num_ports > 0) { 7501 LOG_ERROR(BSL_LS_BCM_TRUNK, (BSL_META_U(unit, 7502 "ERROR: Maximum trunk supported " 7503 "on 5626x devices are %d \n" 7504 "Please remove Trunk id %d " 7505 "re-sync and update/warm boot\n"), 7506 TRUNK_CNTL(unit).ngroups_fp - 1, 7507 tid)); 7508 return BCM_E_CONFIG; 7509 } 7510 } 7511 } 7512 } 7513 #endif /* BCM_SABER2_SUPPORT */ 7514 } else { 7515 #if defined(BCM_TRIDENT_SUPPORT) 7516 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7517 additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp * 2 + 7518 soc_mem_index_count(unit, TRUNK_MEMBERm) * 3) * 7519 sizeof(uint8); 7520 } else 7521 #endif /* BCM_TRIDENT_SUPPORT */ 7522 #if defined(BCM_XGS3_SWITCH_SUPPORT) 7523 { 7524 additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp * 7525 (1 + 3 * TRUNK_CNTL(unit).nports_fp) * sizeof(uint8)); 7526 } 7527 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 7528 } 7529 7530 if (recovered_ver >= BCM_WB_VERSION_1_3) { 7531 #ifdef BCM_TRIDENT_SUPPORT 7532 if (soc_feature(unit, soc_feature_hg_dlb) && 7533 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 7534 BCM_IF_ERROR_RETURN(bcm_trident_hg_dlb_scache_recover(unit, 7535 &trunk_scache)); 7536 } 7537 #endif /* BCM_TRIDENT_SUPPORT */ 7538 7539 #ifdef BCM_TRIUMPH3_SUPPORT 7540 if (soc_feature(unit, soc_feature_lag_dlb) && 7541 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 7542 /* Recover LAG dynamic load balancing info */ 7543 BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_scache_recover(unit, 7544 &trunk_scache)); 7545 } 7546 #endif /* BCM_TRIUMPH3_SUPPORT */ 7547 7548 #ifdef BCM_TOMAHAWK2_SUPPORT 7549 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 7550 /* Recover HGT_LAG dynamic load balancing info */ 7551 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_scache_recover(unit, 7552 &trunk_scache)); 7553 } 7554 #endif /* BCM_TOMAHAWK2_SUPPORT */ 7555 7556 } else { 7557 #ifdef BCM_TRIDENT_SUPPORT 7558 if (soc_feature(unit, soc_feature_hg_dlb)) { 7559 int hg_dlb_scache_size; 7560 BCM_IF_ERROR_RETURN(bcm_trident_hg_dlb_wb_alloc_size_get(unit, 7561 &hg_dlb_scache_size)); 7562 additional_scache_size += hg_dlb_scache_size; 7563 } 7564 #endif /* BCM_TRIDENT_SUPPORT */ 7565 7566 #ifdef BCM_TRIUMPH3_SUPPORT 7567 if (soc_feature(unit, soc_feature_lag_dlb)) { 7568 int lag_dlb_scache_size; 7569 BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_wb_alloc_size_get(unit, 7570 &lag_dlb_scache_size)); 7571 additional_scache_size += lag_dlb_scache_size; 7572 } 7573 #endif /* BCM_TRIUMPH3_SUPPORT */ 7574 } 7575 7576 if (recovered_ver <= BCM_WB_VERSION_1_3) { 7577 #ifdef BCM_TRIDENT2_SUPPORT 7578 if (SOC_IS_TRIDENT2(unit)) { 7579 additional_scache_size += TRUNK_CNTL(unit).fp_hwf_alloc; 7580 } 7581 #endif /* BCM_TRIDENT2_SUPPORT */ 7582 } 7583 7584 #if defined(BCM_TRIDENT_SUPPORT) 7585 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7586 if (recovered_ver >= BCM_WB_VERSION_1_6) { 7587 /* Recover psc from scache in Level 2 warmboot */ 7588 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7589 t_info = &TRUNK_INFO(unit, tid); 7590 sal_memcpy(&t_info->psc, trunk_scache, sizeof(int)); 7591 trunk_scache += sizeof(int); 7592 } 7593 } else { 7594 additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp * 7595 sizeof(int)); 7596 } 7597 } 7598 /*#if defined(BCM_TOMAHAWK3_SUPPORT) Will Revisit why this piece is a problem. */ 7599 #if 0 7600 else { 7601 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7602 t_info = &TRUNK_INFO(unit, tid); 7603 sal_memcpy(&t_info->psc, trunk_scache, sizeof(int)); 7604 trunk_scache += sizeof(int); 7605 } 7606 } 7607 #endif 7608 7609 #endif /* BCM_TRIDENT_SUPPORT */ 7610 if (recovered_ver >= BCM_WB_VERSION_1_7) { 7611 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7612 7613 t_info = &TRUNK_INFO(unit, tid); 7614 sal_memcpy(&recovered_dlf_index, trunk_scache, 7615 sizeof(int)); 7616 trunk_scache += sizeof(int); 7617 7618 t_info->dlf_index_spec = recovered_dlf_index; 7619 t_info->dlf_index_used = recovered_dlf_index; 7620 t_info->mc_index_spec = recovered_dlf_index; 7621 t_info->mc_index_used = recovered_dlf_index; 7622 t_info->ipmc_index_spec = recovered_dlf_index; 7623 t_info->ipmc_index_used = recovered_dlf_index; 7624 } 7625 } else { 7626 additional_scache_size += (TRUNK_CNTL(unit).ngroups_fp * 7627 sizeof(int)); 7628 } 7629 7630 #if defined(BCM_TRIDENT_SUPPORT) 7631 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7632 if (recovered_ver >= BCM_WB_VERSION_1_8) { 7633 sal_memcpy(&bcm_trident_trunk_mbr_zero_rsvd[unit], 7634 trunk_scache, 7635 sizeof(int)); 7636 } else { 7637 additional_scache_size += (sizeof(int)); 7638 } 7639 } 7640 #endif /* BCM_TRIDENT_SUPPORT */ 7641 7642 if (additional_scache_size > 0) { 7643 SOC_IF_ERROR_RETURN 7644 (soc_scache_realloc(unit, scache_handle, 7645 additional_scache_size)); 7646 } 7647 7648 /* To add new state: 7649 * if (recovered_ver >= BCM_WB_VERSION_1_x) { 7650 * Recover state for ver 1_x 7651 * } else { 7652 * Re-alloc scache for 'sync' operation for ver 1_x state. 7653 * } 7654 */ 7655 } 7656 7657 if (SOC_IS_XGS12_FABRIC(unit)) { 7658 #ifdef BCM_XGS12_FABRIC_SUPPORT 7659 bcm_pbmp_t tports; 7660 bcm_port_t port; 7661 bcm_trunk_info_t *t_data, td; 7662 int member_count; 7663 uint32 val; 7664 7665 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_hg; tid++) { 7666 PBMP_HG_ITER(unit, port) { 7667 SOC_IF_ERROR_RETURN(READ_ING_HGTRUNKr(unit, port, tid, &val)); 7668 break; 7669 } 7670 7671 SOC_PBMP_CLEAR(tports); 7672 SOC_PBMP_WORD_SET(tports, 0, 7673 soc_reg_field_get(unit, ING_HGTRUNKr, val, BMAPf)); 7674 SOC_PBMP_COUNT(tports, member_count); 7675 if (0 == member_count) { 7676 /* 7677 * Nothing to update for this TID 7678 */ 7679 continue; 7680 } 7681 7682 sal_memset(&td, 0, sizeof(bcm_trunk_info_t)); 7683 t_data = &td; 7684 7685 switch(soc_reg_field_get(unit, ING_HGTRUNKr, val, ALGORITHMf)) { 7686 case 0: 7687 t_data->psc = BCM_TRUNK_PSC_SRCDSTMAC; 7688 7689 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPMACSAf)) { 7690 t_data->psc |= BCM_TRUNK_PSC_IPMACSA; 7691 } 7692 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPMACDAf)) { 7693 t_data->psc |= BCM_TRUNK_PSC_IPMACDA; 7694 } 7695 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPTYPEf)) { 7696 t_data->psc |= BCM_TRUNK_PSC_IPTYPE; 7697 } 7698 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPVIDf)) { 7699 t_data->psc |= BCM_TRUNK_PSC_IPVID; 7700 } 7701 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPSAf)) { 7702 t_data->psc |= BCM_TRUNK_PSC_IPSA; 7703 } 7704 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_IPDAf)) { 7705 t_data->psc |= BCM_TRUNK_PSC_IPDA; 7706 } 7707 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_L4SSf)) { 7708 t_data->psc |= BCM_TRUNK_PSC_L4SS; 7709 } 7710 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_L4DSf)) { 7711 t_data->psc |= BCM_TRUNK_PSC_L4DS; 7712 } 7713 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_MACDAf)) { 7714 t_data->psc |= BCM_TRUNK_PSC_MACDA; 7715 } 7716 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_MACSAf)) { 7717 t_data->psc |= BCM_TRUNK_PSC_MACSA; 7718 } 7719 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_TYPEf)) { 7720 t_data->psc |= BCM_TRUNK_PSC_TYPE; 7721 } 7722 if (soc_reg_field_get(unit, ING_HGTRUNKr, val, EN_VIDf)) { 7723 t_data->psc |= BCM_TRUNK_PSC_VID; 7724 } 7725 break; 7726 case 1: 7727 t_data->psc = BCM_TRUNK_PSC_REDUNDANT; 7728 break; 7729 default: 7730 t_data->psc = -1; 7731 break; 7732 } 7733 7734 t_data->dlf_index = -1; 7735 t_data->mc_index = -1; 7736 t_data->ipmc_index = -1; 7737 7738 /* 7739 * Fill in t_info struct for this tid 7740 */ 7741 t_info = &TRUNK_INFO(unit, tid); 7742 7743 /* 7744 * Check number of ports in trunk group 7745 */ 7746 if (member_count < 1 || 7747 (TRUNK_FP_TID(unit, tid) && 7748 (member_count > TRUNK_CNTL(unit).nports_fp)) || 7749 (TRUNK_FABRIC_TID(unit, tid) && 7750 (member_count > TRUNK_CNTL(unit).nports_hg))) { 7751 return (BCM_E_PARAM); 7752 } 7753 7754 TRUNK_LOCK(unit); 7755 t_info->tid = tid; 7756 t_info->psc = t_data->psc; 7757 t_info->in_use = TRUE; 7758 TRUNK_UNLOCK(unit); 7759 } 7760 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 7761 } else if (SOC_IS_XGS3_FABRIC(unit)) { 7762 #ifdef BCM_XGS3_FABRIC_SUPPORT 7763 /* 7764 * recover software state for fabric trunks 7765 */ 7766 BCM_IF_ERROR_RETURN(_bcm_trunk_fabric_reinit(unit)); 7767 #endif /* BCM_XGS3_FABRIC_SUPPORT */ 7768 } 7769 7770 #ifdef BCM_XGS_SWITCH_SUPPORT 7771 if (SOC_IS_XGS3_SWITCH(unit)) { 7772 if (SOC_IS_FBX(unit)) { 7773 /* 7774 * recover software state for fabric trunks 7775 */ 7776 BCM_IF_ERROR_RETURN(_bcm_trunk_fabric_reinit(unit)); 7777 7778 /* 7779 * recover software state for ether trunks 7780 */ 7781 BCM_IF_ERROR_RETURN(_bcm_trunk_lag_reinit(unit)); 7782 } 7783 } 7784 #endif 7785 7786 #ifdef BCM_APACHE_SUPPORT 7787 if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) { 7788 int tid; 7789 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7790 if (TRUNK_CNTL(unit).t_info[tid].rr_lag_select != -1) { 7791 SHR_BITSET(TRUNK_CNTL(unit).fp_rr_lag_bmp, 7792 TRUNK_CNTL(unit).t_info[tid].rr_lag_select); 7793 } 7794 } 7795 } 7796 #endif /* BCM_APACHE_SUPPORT */ 7797 7798 return BCM_E_NONE; 7799 } 7800 7801 /* 7802 * Function: 7803 * _bcm_esw_trunk_sync 7804 * Purpose: 7805 * Record Trunk module persisitent info for Level 2 Warm Boot 7806 * Parameters: 7807 * unit - StrataSwitch unit number. 7808 * Returns: 7809 * BCM_E_XXX 7810 */ 7811 7812 int 7813 _bcm_esw_trunk_sync(int unit) 7814 { 7815 bcm_trunk_t tid; 7816 trunk_private_t *t_info; 7817 soc_scache_handle_t scache_handle; 7818 uint8 *trunk_scache; 7819 uint32 ngroups; 7820 uint8 flags; 7821 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 7822 bcm_trunk_t hgtid; 7823 int tix, idx; 7824 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 7825 7826 if (SOC_IS_XGS12_FABRIC(unit)) { 7827 return BCM_E_NONE; 7828 } 7829 7830 TRUNK_INIT(unit); 7831 7832 /* Limited scache mode unsupported */ 7833 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) { 7834 return BCM_E_NONE; 7835 } 7836 7837 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TRUNK, 0); 7838 BCM_IF_ERROR_RETURN 7839 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 7840 0, 7841 &trunk_scache, BCM_WB_DEFAULT_VERSION, NULL)); 7842 7843 ngroups = TRUNK_CNTL(unit).ngroups_fp; 7844 sal_memcpy(trunk_scache, &ngroups, sizeof(ngroups)); 7845 trunk_scache += sizeof(ngroups); 7846 7847 ngroups = TRUNK_CNTL(unit).ngroups_hg; 7848 sal_memcpy(trunk_scache, &ngroups, sizeof(ngroups)); 7849 if (ngroups != TRUNK_CNTL(unit).ngroups_hg) { 7850 return BCM_E_CONFIG; 7851 } 7852 trunk_scache += sizeof(ngroups); 7853 7854 sal_memset(TRUNK_CNTL(unit).trunk_bmp_ptr, 0, 7855 TRUNK_CNTL(unit).trunk_bmp_alloc); 7856 7857 for (tid = 0; tid < TRUNK_NUM_GROUPS(unit); tid++) { 7858 t_info = &TRUNK_INFO(unit, tid); 7859 if (BCM_TRUNK_INVALID != t_info->tid) { 7860 SHR_BITSET(TRUNK_CNTL(unit).trunk_bmp_ptr, tid); 7861 } 7862 t_info++; 7863 } 7864 sal_memcpy(trunk_scache, TRUNK_CNTL(unit).trunk_bmp_ptr, 7865 TRUNK_CNTL(unit).trunk_bmp_alloc); 7866 trunk_scache += TRUNK_CNTL(unit).trunk_bmp_alloc; 7867 7868 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 7869 if (TRUNK_CNTL(unit).fp_hwf_alloc) { 7870 idx = 0; 7871 7872 if (soc_feature(unit, soc_feature_port_lag_failover)) { 7873 /* FP trunk failover flags */ 7874 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7875 TRUNK_CNTL(unit).fp_hwf_flags[idx++] = 7876 TRUNK_INFO(unit, tid).flags; 7877 #if defined(BCM_TRIDENT_SUPPORT) 7878 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7879 uint16 num_ports; 7880 num_ports = _bcm_trident_hw_failover_num_ports_get(unit, tid, FALSE); 7881 /* Max number of ports per front-panel trunk group is 256, 7882 * requiring two bytes of storage. */ 7883 TRUNK_CNTL(unit).fp_hwf_flags[idx++] = num_ports >> 8; 7884 TRUNK_CNTL(unit).fp_hwf_flags[idx++] = num_ports & 0xff; 7885 for (tix = 0; tix < num_ports; tix++) { 7886 TRUNK_CNTL(unit).fp_hwf_flags[idx++] = 7887 _bcm_trident_hw_failover_flags_get(unit, tid, 7888 tix, FALSE); 7889 } 7890 } else 7891 #if defined(BCM_TOMAHAWK3_SUPPORT) 7892 if (SOC_IS_TOMAHAWK3(unit)) { 7893 int fail_to_ports, fpid; 7894 fail_to_ports = _bcm_th3_trunk_hwfailover_num_ports_get(unit, tid); 7895 TRUNK_CNTL(unit).fp_hwf_flags[idx++] = fail_to_ports >> 8; 7896 TRUNK_CNTL(unit).fp_hwf_flags[idx++] = fail_to_ports & 0xff; 7897 for (fpid = 0; fpid < fail_to_ports; fpid++) { 7898 TRUNK_CNTL(unit).fp_hwf_flags[idx++] = 7899 _bcm_th3_trunk_hwfailover_flags_get(unit, tid, fpid); 7900 } 7901 } else 7902 #endif 7903 #endif /* BCM_TRIDENT_SUPPORT */ 7904 { 7905 for (tix = 0; tix < TRUNK_CNTL(unit).nports_fp; tix++) { 7906 TRUNK_CNTL(unit).fp_hwf_flags[idx++] = 7907 _bcm_xgs3_hw_failover_flags_get(unit, tid, 7908 tix, FALSE); 7909 } 7910 } 7911 } /* tid */ 7912 } /* lag failover */ 7913 sal_memcpy(trunk_scache, TRUNK_CNTL(unit).fp_hwf_flags, 7914 TRUNK_CNTL(unit).fp_hwf_alloc); 7915 trunk_scache += TRUNK_CNTL(unit).fp_hwf_alloc; 7916 } 7917 if (TRUNK_CNTL(unit).hg_hwf_alloc) { 7918 7919 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 7920 idx = 0; 7921 /* HG trunk failover flags */ 7922 for (tid = TRUNK_CNTL(unit).ngroups_fp; 7923 tid < TRUNK_NUM_GROUPS(unit); tid++) { 7924 TRUNK_CNTL(unit).hg_hwf_flags[idx++] = 7925 TRUNK_INFO(unit, tid).flags; 7926 hgtid = tid - TRUNK_CNTL(unit).ngroups_fp; 7927 #if defined(BCM_TRIDENT_SUPPORT) 7928 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7929 uint16 num_ports; 7930 num_ports = _bcm_trident_hw_failover_num_ports_get(unit, hgtid, TRUE); 7931 /* Max number of ports per front-panel trunk group is 32, 7932 * requiring one byte of storage. */ 7933 TRUNK_CNTL(unit).hg_hwf_flags[idx++] = num_ports; 7934 for (tix = 0; tix < num_ports; tix++) { 7935 TRUNK_CNTL(unit).hg_hwf_flags[idx++] = 7936 _bcm_trident_hw_failover_flags_get(unit, hgtid, 7937 tix, TRUE); 7938 } 7939 } else 7940 #endif /* BCM_TRIDENT_SUPPORT */ 7941 { 7942 for (tix = 0; tix < TRUNK_CNTL(unit).nports_hg; tix++) { 7943 TRUNK_CNTL(unit).hg_hwf_flags[idx++] = 7944 _bcm_xgs3_hw_failover_flags_get(unit, hgtid, 7945 tix, TRUE); 7946 } 7947 } 7948 } 7949 } 7950 sal_memcpy(trunk_scache, TRUNK_CNTL(unit).hg_hwf_flags, 7951 TRUNK_CNTL(unit).hg_hwf_alloc); 7952 trunk_scache += TRUNK_CNTL(unit).hg_hwf_alloc; 7953 } 7954 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 7955 7956 /* Store BCM_TRUNK_FLAG_IPMC_CLEAVE flag */ 7957 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7958 t_info = &TRUNK_INFO(unit, tid); 7959 if (t_info->flags & BCM_TRUNK_FLAG_IPMC_CLEAVE) { 7960 flags = 0x1; 7961 } else { 7962 flags = 0x0; 7963 } 7964 sal_memcpy(trunk_scache, &flags, sizeof(uint8)); 7965 trunk_scache += sizeof(uint8); 7966 } 7967 7968 /* Store ipmc_psc */ 7969 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7970 t_info = &TRUNK_INFO(unit, tid); 7971 sal_memcpy(trunk_scache, &t_info->ipmc_psc, sizeof(int)); 7972 trunk_scache += sizeof(int); 7973 } 7974 7975 /* Store front-panel trunk membership info */ 7976 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 7977 #if defined(BCM_TRIDENT_SUPPORT) 7978 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 7979 uint16 num_ports; 7980 uint16 *modport; 7981 uint32 *member_flags; 7982 uint8 truncated_flags; 7983 int rv, i; 7984 7985 BCM_IF_ERROR_RETURN(_bcm_trident_trunk_member_info_get(unit, tid, 7986 0, NULL, NULL, &num_ports)); 7987 modport = sal_alloc(sizeof(uint16) * num_ports, "modport"); 7988 if (NULL == modport) { 7989 return BCM_E_MEMORY; 7990 } 7991 member_flags = sal_alloc(sizeof(uint32) * num_ports, 7992 "member_flags"); 7993 if (NULL == member_flags) { 7994 sal_free(modport); 7995 return BCM_E_MEMORY; 7996 } 7997 rv = _bcm_trident_trunk_member_info_get(unit, tid, 7998 num_ports, modport, member_flags, &num_ports); 7999 if (BCM_FAILURE(rv)) { 8000 sal_free(modport); 8001 sal_free(member_flags); 8002 return rv; 8003 } 8004 8005 sal_memcpy(trunk_scache, &num_ports, sizeof(uint16)); 8006 trunk_scache += sizeof(uint16); 8007 for (i = 0; i < num_ports; i++) { 8008 sal_memcpy(trunk_scache, &modport[i], sizeof(uint16)); 8009 trunk_scache += sizeof(uint16); 8010 8011 /* Truncate the flags to 1 byte, as there are only 8 flags */ 8012 truncated_flags = member_flags[i] & 0xff; 8013 sal_memcpy(trunk_scache, &truncated_flags, sizeof(uint8)); 8014 trunk_scache += sizeof(uint8); 8015 } 8016 8017 sal_free(modport); 8018 sal_free(member_flags); 8019 } else 8020 #endif /* BCM_TRIDENT_SUPPORT */ 8021 #if defined(BCM_TOMAHAWK3_SUPPORT) 8022 if (SOC_IS_TOMAHAWK3(unit)) { 8023 _esw_trunk_add_info_t *t_data; 8024 uint16 num_ports; 8025 uint8 port; 8026 uint8 mflags; 8027 int rv, i; 8028 8029 t_info = &TRUNK_INFO(unit, tid); 8030 t_data = sal_alloc(sizeof(_esw_trunk_add_info_t), "trunk_add_info"); 8031 if (t_data == NULL) { 8032 return BCM_E_MEMORY; 8033 } 8034 sal_memset(t_data, 0, sizeof(_esw_trunk_add_info_t)); 8035 8036 /* first obtain the number of member ports */ 8037 8038 rv = _bcm_th3_trunk_member_info_get(unit, tid, t_data, t_info); 8039 if (BCM_FAILURE(rv)) { 8040 sal_free(t_data); 8041 return rv; 8042 } 8043 num_ports = t_data->num_ports; 8044 sal_memcpy(trunk_scache, &num_ports, sizeof(uint16)); 8045 trunk_scache += sizeof(uint16); 8046 if (t_data->num_ports != 0) { 8047 /* Then obtain the member ports info */ 8048 rv = _bcm_th3_trunk_member_info_get(unit, tid, t_data, t_info); 8049 if (BCM_FAILURE(rv)) { 8050 sal_free(t_data); 8051 return rv; 8052 } 8053 for (i = 0; i < num_ports; i++) { 8054 /* Module is 0 for TH3 */ 8055 port = t_data->tp[i]; 8056 sal_memcpy(trunk_scache, &port, sizeof(uint8)); 8057 trunk_scache += sizeof(uint8); 8058 8059 /* Truncate the flags to 1 byte, as there are only 8 flags */ 8060 mflags = t_data->member_flags[i]; 8061 sal_memcpy(trunk_scache, &mflags, sizeof(mflags)); 8062 trunk_scache += sizeof(uint8); 8063 } 8064 sal_free(t_data->tp); 8065 sal_free(t_data->tm); 8066 sal_free(t_data->member_flags); 8067 sal_free(t_data->dynamic_scaling_factor); 8068 sal_free(t_data->dynamic_load_weight); 8069 sal_free(t_data->dynamic_queue_size_weight); 8070 } /* if num_ports */ 8071 sal_free(t_data); 8072 8073 } else 8074 #endif /* BCM_TOMAHAWK3_SUPPORT */ 8075 #ifdef BCM_XGS3_SWITCH_SUPPORT 8076 { 8077 uint8 num_ports; 8078 uint16 modport[BCM_XGS3_TRUNK_MAX_PORTCNT]; 8079 uint32 member_flags[BCM_XGS3_TRUNK_MAX_PORTCNT]; 8080 uint8 truncated_flags; 8081 int i; 8082 8083 _bcm_xgs3_trunk_member_info_get(unit, tid, &num_ports, 8084 modport, member_flags); 8085 sal_memcpy(trunk_scache, &num_ports, sizeof(uint8)); 8086 trunk_scache += sizeof(uint8); 8087 for (i = 0; i < num_ports; i++) { 8088 sal_memcpy(trunk_scache, &modport[i], sizeof(uint16)); 8089 trunk_scache += sizeof(uint16); 8090 8091 /* Truncate the flags to 1 byte, as there are only 4 flags */ 8092 truncated_flags = member_flags[i] & 0xff; 8093 sal_memcpy(trunk_scache, &truncated_flags, sizeof(uint8)); 8094 trunk_scache += sizeof(uint8); 8095 } 8096 } 8097 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 8098 } 8099 /* Store Higig dynamic load balancing info */ 8100 #ifdef BCM_TRIDENT_SUPPORT 8101 if (soc_feature(unit, soc_feature_hg_dlb) && 8102 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 8103 BCM_IF_ERROR_RETURN(bcm_trident_hg_dlb_sync(unit, &trunk_scache)); 8104 } 8105 #endif /* BCM_TRIDENT_SUPPORT */ 8106 8107 /* Store LAG dynamic load balancing info */ 8108 #ifdef BCM_TRIUMPH3_SUPPORT 8109 if (soc_feature(unit, soc_feature_lag_dlb) && 8110 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 8111 BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_sync(unit, &trunk_scache)); 8112 } 8113 #endif /* BCM_TRIUMPH3_SUPPORT */ 8114 8115 #ifdef BCM_TOMAHAWK2_SUPPORT 8116 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 8117 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_sync(unit, &trunk_scache)); 8118 } 8119 #endif /* BCM_TOMAHAWK2_SUPPORT */ 8120 8121 /* Store front-panel trunk psc info */ 8122 #if defined(BCM_TRIDENT_SUPPORT) 8123 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 8124 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 8125 t_info = &TRUNK_INFO(unit, tid); 8126 sal_memcpy(trunk_scache, &t_info->psc, sizeof(int)); 8127 trunk_scache += sizeof(int); 8128 } 8129 } 8130 /*#if defined(BCM_TOMAHAWK3_SUPPORT) Will Revisit why this piece is a problem. */ 8131 #if 0 8132 else { 8133 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 8134 t_info = &TRUNK_INFO(unit, tid); 8135 sal_memcpy(trunk_scache, &t_info->psc, sizeof(int)); 8136 trunk_scache += sizeof(int); 8137 } 8138 } 8139 #endif 8140 #endif /* BCM_TRIDENT_SUPPORT */ 8141 8142 /* Store dlf_index */ 8143 for (tid = 0; tid < TRUNK_CNTL(unit).ngroups_fp; tid++) { 8144 t_info = &TRUNK_INFO(unit, tid); 8145 sal_memcpy(trunk_scache, &t_info->dlf_index_used, sizeof(int)); 8146 trunk_scache += sizeof(int); 8147 } 8148 8149 /* Store bcm_trident_trunk_mbr_zero_rsvd info. */ 8150 #if defined(BCM_TRIDENT_SUPPORT) 8151 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 8152 sal_memcpy(trunk_scache, &bcm_trident_trunk_mbr_zero_rsvd[unit], sizeof(int)); 8153 trunk_scache += sizeof(int); 8154 } 8155 #endif /* BCM_TRIDENT_SUPPORT */ 8156 8157 return BCM_E_NONE; 8158 } 8159 #endif /* BCM_WARM_BOOT_SUPPORT */ 8160 8161 #ifndef BCM_SW_STATE_DUMP_DISABLE 8162 /* 8163 * Function: 8164 * _bcm_trunk_sw_dump 8165 * Purpose: 8166 * Displays trunk information maintained by software. 8167 * Parameters: 8168 * unit - Device unit number 8169 * Returns: 8170 * None 8171 */ 8172 void 8173 _bcm_trunk_sw_dump(int unit) 8174 { 8175 trunk_cntl_t *t_cntl; 8176 trunk_private_t *t_info; 8177 int i; 8178 int print_trunk_info; 8179 8180 t_cntl = &TRUNK_CNTL(unit); 8181 LOG_CLI((BSL_META_U(unit, 8182 "\nSW Information TRUNK - Unit %d\n"), unit)); 8183 LOG_CLI((BSL_META_U(unit, 8184 " Front panel trunk groups : %d\n"), t_cntl->ngroups_fp)); 8185 LOG_CLI((BSL_META_U(unit, 8186 " Front panel trunk max ports : %d\n"), t_cntl->nports_fp)); 8187 LOG_CLI((BSL_META_U(unit, 8188 " Fabric panel trunk groups : %d\n"), t_cntl->ngroups_hg)); 8189 LOG_CLI((BSL_META_U(unit, 8190 " Fabric panel trunk max ports : %d\n"), t_cntl->nports_hg)); 8191 8192 print_trunk_info = TRUE; 8193 for (i = 0; i < TRUNK_NUM_GROUPS(unit); i++) { 8194 t_info = &TRUNK_INFO(unit, i); 8195 #if defined(BCM_TRIDENT_SUPPORT) 8196 if (TRUNK_CNTL(unit).ngroups_fp > 128) { 8197 /* Trident has 1024 front panel trunk groups. 8198 * Print only the ones that are in use. 8199 */ 8200 print_trunk_info = t_info->tid != BCM_TRUNK_INVALID; 8201 } 8202 #endif /* BCM_TRIDENT_SUPPORT */ 8203 if (print_trunk_info) { 8204 LOG_CLI((BSL_META_U(unit, 8205 " Trunk %d\n"), i)); 8206 LOG_CLI((BSL_META_U(unit, 8207 " ID : %d\n"), t_info->tid)); 8208 LOG_CLI((BSL_META_U(unit, 8209 " in use : %d\n"), t_info->in_use)); 8210 LOG_CLI((BSL_META_U(unit, 8211 " psc : 0x%x\n"), t_info->psc)); 8212 LOG_CLI((BSL_META_U(unit, 8213 " ipmc_psc : 0x%x\n"), t_info->ipmc_psc)); 8214 LOG_CLI((BSL_META_U(unit, 8215 " rtag : 0x%x\n"), t_info->rtag)); 8216 LOG_CLI((BSL_META_U(unit, 8217 " flags : 0x%x\n"), t_info->flags)); 8218 if (soc_feature(unit, soc_feature_hg_dlb) || 8219 soc_feature(unit, soc_feature_lag_dlb)) { 8220 LOG_CLI((BSL_META_U(unit, 8221 " dynamic_size : 0x%x\n"), t_info->dynamic_size)); 8222 LOG_CLI((BSL_META_U(unit, 8223 " dynamic_age : 0x%x\n"), t_info->dynamic_age)); 8224 } 8225 if (!SOC_IS_XGS3_SWITCH(unit)) { 8226 /* Unused for XGS3 devices */ 8227 LOG_CLI((BSL_META_U(unit, 8228 " dlf index spec : %d\n"), 8229 t_info->dlf_index_spec)); 8230 LOG_CLI((BSL_META_U(unit, 8231 " dlf index used : %d\n"), 8232 t_info->dlf_index_used)); 8233 LOG_CLI((BSL_META_U(unit, 8234 " dlf port used : %d\n"), 8235 t_info->dlf_port_used)); 8236 LOG_CLI((BSL_META_U(unit, 8237 " mc index spec : %d\n"), 8238 t_info->mc_index_spec)); 8239 LOG_CLI((BSL_META_U(unit, 8240 " mc index used : %d\n"), 8241 t_info->mc_index_used)); 8242 LOG_CLI((BSL_META_U(unit, 8243 " mc port used : %d\n"), 8244 t_info->mc_port_used)); 8245 LOG_CLI((BSL_META_U(unit, 8246 " ipmc index spec : %d\n"), 8247 t_info->ipmc_index_spec)); 8248 LOG_CLI((BSL_META_U(unit, 8249 " ipmc index used : %d\n"), 8250 t_info->ipmc_index_used)); 8251 LOG_CLI((BSL_META_U(unit, 8252 " ipmc port used : %d\n"), 8253 t_info->ipmc_port_used)); 8254 } 8255 } 8256 } 8257 8258 #if defined(BCM_TRIDENT_SUPPORT) 8259 if (soc_feature(unit, soc_feature_shared_trunk_member_table)) { 8260 _bcm_trident_trunk_sw_dump(unit); 8261 } else 8262 #endif /* BCM_TRIDENT_SUPPORT */ 8263 #if defined(BCM_XGS3_SWITCH_SUPPORT) 8264 if (SOC_IS_FBX(unit) && !SOC_IS_RAPTOR(unit)) { 8265 _bcm_xgs3_trunk_sw_dump(unit); 8266 } 8267 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 8268 8269 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 8270 if (soc_feature(unit, soc_feature_vp_lag)) { 8271 bcm_td2_vp_lag_sw_dump(unit); 8272 } 8273 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 8274 8275 return; 8276 } 8277 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 8278 8279 /* 8280 * Function: 8281 * _bcm_esw_trunk_tgid_extended_mem_get 8282 * Purpose: 8283 * Called by the macro TRUNK_CHK_TGID_EXTENDED to fetch the memory 8284 * that will be used to determine the number of trunk group IDs 8285 * Parameters: 8286 * unit - Device unit number 8287 * Returns: 8288 * The memory used to determine the number of trunk group IDs 8289 */ 8290 soc_mem_t 8291 _bcm_esw_trunk_tgid_extended_mem_get(int unit) 8292 { 8293 soc_mem_t ret = TRUNK_GROUPm; 8294 8295 if (soc_feature(unit, soc_feature_fastlag)) { 8296 ret = FAST_TRUNK_GROUPm; 8297 8298 #ifdef BCM_TOMAHAWK3_SUPPORT 8299 if (SOC_IS_TOMAHAWK3(unit)) { 8300 ret = FAST_TRUNK_SIZEm; 8301 } 8302 #endif 8303 } 8304 8305 return ret; 8306 } 8307 8308 /* 8309 * Function: 8310 * _bcm_esw_trunk_lock 8311 * Purpose: 8312 * Lock Trunk module - if module was not initialized NOOP 8313 * 8314 * Parameters: 8315 * unit - (IN) Unit number. 8316 * Returns: 8317 * BCM_E_XXX 8318 * Notes: 8319 */ 8320 int 8321 _bcm_esw_trunk_lock(int unit) 8322 { 8323 if (NULL != TRUNK_CNTL(unit).lock) { 8324 return sal_mutex_take(TRUNK_CNTL(unit).lock, 8325 sal_mutex_FOREVER); 8326 } 8327 return (BCM_E_NONE); 8328 } 8329 /* 8330 * Function: 8331 * _bcm_esw_trunk_unlock 8332 * Purpose: 8333 * Unlock Trunk module - if module was not initialized NOOP 8334 * 8335 * Parameters: 8336 * unit - (IN) Unit number. 8337 * Returns: 8338 * BCM_E_XXX 8339 * Notes: 8340 */ 8341 int 8342 _bcm_esw_trunk_unlock(int unit) 8343 { 8344 if (NULL != TRUNK_CNTL(unit).lock) { 8345 return sal_mutex_give(TRUNK_CNTL(unit).lock); 8346 } 8347 return (BCM_E_NONE); 8348 } 8349 8350 int 8351 _bcm_esw_trunk_group_num(int unit) 8352 { 8353 8354 #if defined(BCM_TRIDENT2_SUPPORT) && defined(INCLUDE_L3) 8355 if (soc_feature(unit, soc_feature_vp_lag)) { 8356 return TRUNK_NUM_GROUPS(unit) + _bcm_esw_num_vp_trunk_groups(unit); 8357 } 8358 #endif /* BCM_TRIDENT2_SUPPORT && INCLUDE_L3 */ 8359 8360 return TRUNK_NUM_GROUPS(unit); 8361 }