stack.c (362245B)
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: stack.c 8 * Purpose: BCM level APIs for stacking applications 9 */ 10 11 #include <shared/bsl.h> 12 #include <sal/core/sync.h> 13 #include <soc/drv.h> 14 #include <soc/scache.h> 15 #include <soc/scache_dictionary.h> 16 #include <soc/profile_mem.h> 17 #include <soc/firebolt.h> 18 #include <bcm/error.h> 19 #include <bcm/stack.h> 20 21 #include <bcm_int/control.h> 22 #include <bcm_int/esw/mbcm.h> 23 #include <bcm_int/esw/port.h> 24 #include <bcm_int/esw/vlan.h> 25 #include <bcm_int/esw/ipmc.h> 26 #include <bcm_int/esw/mcast.h> 27 #include <bcm_int/esw/rx.h> 28 #include <bcm_int/esw/stack.h> 29 #include <bcm_int/esw/trunk.h> 30 #include <bcm_int/esw/trident.h> 31 #include <bcm_int/esw/katana2.h> 32 #include <bcm_int/esw/trx.h> 33 #include <bcm_int/esw/trident2plus.h> 34 35 #include <bcm_int/esw_dispatch.h> 36 37 #include <bcm_int/esw/portctrl.h> 38 39 #ifdef BCM_WARM_BOOT_SUPPORT 40 #include <bcm_int/esw/switch.h> 41 #endif /* BCM_WARM_BOOT_SUPPORT */ 42 #if defined(BROADCOM_DEBUG) 43 #include <bcm_int/rpc/rlink.h> 44 #include <appl/cputrans/atp.h> 45 #endif /* BROADCOM_DEBUG */ 46 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 47 #define BCM_STK_TD2P_NUM_LPORTS (106) 48 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 49 50 #if defined(BCM_MONTEREY_SUPPORT) 51 #define BCM_STK_MONTEREY_NUM_LPORTS (67) 52 #endif /* BCM_MONTEREY_SUPPORT */ 53 54 #if defined(BCM_APACHE_SUPPORT) 55 #define BCM_STK_APACHE_NUM_LPORTS (75) 56 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 57 58 #if defined(BCM_TRIDENT3_SUPPORT) 59 #include <soc/flexport/trident3/trident3_flexport_defines.h> 60 #endif /* BCM_TRIDENT3_SUPPORT */ 61 62 #if defined(BCM_MAVERICK2_SUPPORT) 63 #include <soc/flexport/maverick2/maverick2_flexport_defines.h> 64 #endif /* BCM_MAVERICK2_SUPPORT */ 65 66 #if defined(BCM_HELIX5_SUPPORT) 67 #include <soc/flexport/helix5/helix5_flexport_defines.h> 68 #endif /* BCM_HELIX5_SUPPORT */ 69 70 #if defined(BCM_HERCULES15_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 71 #define LOCAL_MODMAP_SUPPORT 72 STATIC int _bcm_esw_modmap_init(int unit); 73 #endif /* BCM_HERCULES15_SUPPORT */ 74 75 static sal_mutex_t stack_mutex; 76 77 #define ESW_STK_LOCK sal_mutex_take(stack_mutex, sal_mutex_FOREVER) 78 #define ESW_STK_UNLOCK sal_mutex_give(stack_mutex) 79 80 #ifdef _BCM_STK_FLAGS_GET 81 STATIC int _esw_stk_flags_get(int unit, bcm_port_t port, uint32 *flags); 82 #endif 83 84 STATIC int _esw_stk_port_set(int unit, bcm_port_t port, uint32 flags); 85 86 STATIC int _bcm_xgs_fabric_stk_init(int unit); 87 STATIC int _bcm_xgs3_stk_init(int unit); 88 STATIC int _bcm_xgs3_ignore_my_modid(int unit); 89 90 #if defined(BCM_TRX_SUPPORT) 91 STATIC int _bcm_stk_modport_profile_init(int unit); 92 STATIC soc_profile_mem_t *modport_profile[BCM_MAX_NUM_UNITS]; 93 94 /* Software modport map entry data structure */ 95 typedef struct bcmi_trx_modport_map_entry_s { 96 uint8 dest_istrunk[SOC_MAX_NUM_PORTS]; 97 uint8 dest[SOC_MAX_NUM_PORTS]; 98 } bcmi_trx_modport_map_entry_t; 99 100 /* Software modport map profile data structure */ 101 typedef struct bcmi_trx_modport_map_profile_s { 102 int ref_count; 103 int num_entries; 104 bcmi_trx_modport_map_entry_t *entry_array; 105 } bcmi_trx_modport_map_profile_t; 106 107 /* Software modport map info data structure */ 108 typedef struct bcmi_trx_modport_map_info_s { 109 int num_profiles; 110 bcmi_trx_modport_map_profile_t *profile_array; 111 } bcmi_trx_modport_map_info_t; 112 113 STATIC bcmi_trx_modport_map_info_t * 114 bcmi_trx_modport_map_info[BCM_MAX_NUM_UNITS]; 115 116 /* Global initialized parameter for software modport map */ 117 STATIC uint8 trx_modport_map_initialized = 0; 118 119 #define TRX_MODPORT_MAP_INFO(unit) bcmi_trx_modport_map_info[unit] 120 #define TRX_MODPORT_MAP_PROFILE(unit, index) \ 121 bcmi_trx_modport_map_info[unit]->profile_array[index] 122 123 STATIC int bcmi_trx_modport_map_detach(int unit); 124 #endif /* BCM_TRX_SUPPORT */ 125 126 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 127 src_modid_base_index_bookkeeping_t *src_modid_base_index_bk[BCM_MAX_NUM_UNITS]; 128 #define _BCM_SRC_MOD_PORT_TABLE_USED_GET(_u_, _idx_) \ 129 SHR_BITGET(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_) 130 #define _BCM_SRC_MOD_PORT_TABLE_USED_SET(_u_, _idx_) \ 131 SHR_BITSET(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_) 132 #define _BCM_SRC_MOD_PORT_TABLE_USED_CLR(_u_, _idx_) \ 133 SHR_BITCLR(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_) 134 #define _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(_u_, _idx_, _count_) \ 135 SHR_BITSET_RANGE(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_, _count_) 136 #define _BCM_SRC_MOD_PORT_TABLE_USED_CLR_RANGE(_u_, _idx_, _count_) \ 137 SHR_BITCLR_RANGE(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_, _count_) 138 #define _BCM_SRC_MOD_PORT_TABLE_TEST_RANGE(_u_, _idx_, _count_, _result_) \ 139 SHR_BITTEST_RANGE(src_modid_base_index_bk[_u_]->src_mod_port_table_bitmap, _idx_, _count_, _result_) 140 141 STATIC soc_mem_t src_modbase_mems[] = { 142 SOURCE_TRUNK_MAP_MODBASEm, 143 EGR_GPP_ATTRIBUTES_MODBASEm, 144 #ifdef BCM_TRIDENT2PLUS_SUPPORT 145 EGR_DGPP_TO_NHI_MODBASEm, 146 MODID_BASE_PTRm, 147 #endif 148 }; 149 150 STATIC soc_mem_t src_mod_port_mems[] = { 151 SOURCE_TRUNK_MAP_TABLEm, 152 EGR_GPP_ATTRIBUTESm, 153 #ifdef BCM_TRIDENT2PLUS_SUPPORT 154 EGR_DGPP_TO_NHIm, 155 MODPORT_MAP_SUBPORTm, 156 #endif 157 }; 158 159 STATIC void _src_modid_base_index_bk_detach(int unit); 160 STATIC int _src_modid_base_index_free(int unit, bcm_module_t modid, int nports); 161 162 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 163 164 #if defined(BCM_TOMAHAWK3_SUPPORT) 165 #define BCM_STK_API_TH3_SUPPORT_CHECK(_unit_) \ 166 if (SOC_IS_TOMAHAWK3(_unit_)) { \ 167 return BCM_E_UNAVAIL; \ 168 } 169 #else 170 #define BCM_STK_API_TH3_SUPPORT_CHECK(_unit_) 171 #endif 172 173 #if defined(LOCAL_MODMAP_SUPPORT) 174 #define _NUM_SL_MOD 64 175 #define _MAX_SPORT 31 176 #define _XGS3_MODMAP_GROUPS_MAX 1 177 #define _XGS3_MODMAP_FMOD_MAX 127 178 #define _XGS4_FABRIC_MODMAP_FMOD_MAX 255 179 #define FMOD_MAX(unit) \ 180 ((SOC_IS_SC_CQ(unit) || SOC_IS_HURRICANE3(unit) || \ 181 SOC_IS_GREYHOUND2(unit)) ? \ 182 _XGS4_FABRIC_MODMAP_FMOD_MAX : _XGS3_MODMAP_FMOD_MAX) 183 #define FMOD_RANGE_CHECK(a) \ 184 if (((a) < 0) || ((a) > FMOD_MAX(unit))) return(BCM_E_PARAM) 185 #define LMOD_RANGE_CHECK(a) if (((a) < 0) || ((a) > 63)) return(BCM_E_PARAM) 186 #define SMOD_RANGE_CHECK(a) if (((a) < 0) || ((a) > 63)) return(BCM_E_PARAM) 187 #define FMOD_LMOD_CHECK(fm, lm) if (fm < lm) return(BCM_E_PARAM) 188 #define SPORT_RANGE_CHECK(a) if ((a) > _MAX_SPORT) return(BCM_E_PARAM) 189 #define BCM_MODMAP_FEATURE_CHECK(unit, f) \ 190 do { \ 191 if (!soc_feature(unit, soc_feature_modmap)) { \ 192 return BCM_E_UNAVAIL; \ 193 } \ 194 } while(0) 195 #define MOD_MAP_DATA_CHECK(unit) \ 196 if (mod_map_data[unit] == NULL) return(BCM_E_INIT) 197 /* 198 * One entry for each SOC device containing modmap information 199 * for that device. 200 */ 201 typedef struct mod_map_ctrl { 202 int l_modid[SOC_MAX_NUM_PORTS]; 203 int thresh_d[_NUM_SL_MOD]; 204 int fmod0[SOC_MAX_NUM_PORTS]; 205 } mod_map_ctrl_t; 206 207 STATIC mod_map_ctrl_t *mod_map_data[BCM_MAX_NUM_UNITS]; 208 209 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 210 211 typedef struct modid_mask_num_mods_s { 212 int num_mods; /* number of extra modules */ 213 uint32 mod_mask; /* module mask for extra modules */ 214 } modid_mask_num_mods_t; 215 216 #define BCM_MAX_NUM_MODID_MASK 7 217 STATIC modid_mask_num_mods_t modid_mask_data[BCM_MAX_NUM_MODID_MASK] = { 218 {1, 0xFF}, 219 {2, 0xFE}, 220 {4, 0xFC}, 221 {8, 0xF8}, 222 {16, 0xF0}, 223 {32, 0xE0}, 224 {64, 0xC0}, 225 }; 226 227 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 228 229 #define STACK_INIT(unit) \ 230 if (stack_mutex == NULL) { return BCM_E_INIT; } 231 232 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 233 234 _bcm_stk_trident_linkflap_trunk_map_t _bcm_stk_trident_linkflap_trunk_map[BCM_MAX_NUM_UNITS]; 235 236 /* 237 * Function: 238 * _bcm_stk_modport_map_linkscan_handler 239 * Purpose: 240 * Called from linkscan handler when port toggles. 241 * Enables and Disables the port in MODPORT_MAP_SW. 242 * Parameters: 243 * unit - SOC unit # 244 * info - port info 245 * Returns: 246 * None 247 */ 248 void 249 _bcm_stk_modport_map_linkscan_handler(int unit, 250 bcm_port_t port, bcm_port_info_t *info) 251 { 252 int rv; 253 SOC_LINKSCAN_MODPORT_MAP_LOCK(unit); 254 rv = _bcm_td_stk_modport_map_linkscan_handler(unit, port, info); 255 SOC_LINKSCAN_MODPORT_MAP_UNLOCK(unit); 256 if (BCM_FAILURE(rv)) { 257 LOG_WARN(BSL_LS_BCM_STK, 258 (BSL_META_U(unit, 259 "linkscan handler error: Unit %d, port %d, rv %d\n"), 260 unit, port, rv)); 261 } 262 } 263 #endif /*defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)*/ 264 265 266 267 STATIC int 268 _bcm_esw_modmap_init(int unit) 269 { 270 if (NULL == mod_map_data[unit]) { 271 mod_map_data[unit] = 272 sal_alloc (sizeof (mod_map_ctrl_t), "modmap_state"); 273 } 274 if (NULL == mod_map_data[unit]) { 275 return (BCM_E_MEMORY); 276 } 277 278 sal_memset(mod_map_data[unit], 0, sizeof (mod_map_ctrl_t)); 279 280 return BCM_E_NONE; 281 } 282 283 STATIC int 284 _bcm_esw_modmap_detach(int unit) 285 { 286 if (NULL == mod_map_data[unit]) { 287 return (BCM_E_NONE); 288 } 289 sal_free(mod_map_data[unit]); 290 291 mod_map_data[unit] = NULL; 292 return BCM_E_NONE; 293 } 294 #endif /* MODMAP_SUPPORT */ 295 296 297 /* 298 * Internal init (alloc the mutex). Unit is ignored (for now) 299 */ 300 301 STATIC int 302 _bcm_esw_stk_init(void) 303 { 304 if (stack_mutex == NULL) { 305 if ((stack_mutex = sal_mutex_create("bcm_esw_lock")) == NULL) { 306 return BCM_E_MEMORY; 307 } 308 } 309 310 return BCM_E_NONE; 311 } 312 313 314 /* 315 * Function: 316 * _bcm_esw_stk_detach 317 * Purpose: 318 * De-initialize device stacking 319 * Parameters: 320 * unit - (IN) BCM device number. 321 * Returns: 322 * BCM_E_XXX 323 */ 324 325 int 326 _bcm_esw_stk_detach(int unit) 327 { 328 if (stack_mutex != NULL) { 329 sal_mutex_destroy(stack_mutex); 330 stack_mutex = NULL; 331 } 332 333 BCM_IF_ERROR_RETURN(bcm_esw_stk_modmap_unregister(unit)); 334 335 #if defined(LOCAL_MODMAP_SUPPORT) 336 if (soc_feature(unit, soc_feature_modmap)) { 337 SOC_IF_ERROR_RETURN(_bcm_esw_modmap_detach(unit)); 338 } 339 #endif /* MODMAP_SUPPORT */ 340 341 #if defined(BCM_TRX_SUPPORT) 342 if (modport_profile[unit]) { 343 soc_profile_mem_destroy(unit, modport_profile[unit]); 344 sal_free(modport_profile[unit]); 345 modport_profile[unit] = NULL; 346 } 347 348 if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) { 349 BCM_IF_ERROR_RETURN(bcmi_trx_modport_map_detach(unit)); 350 } 351 #endif /* BCM_TRX_SUPPORT */ 352 353 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 354 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 355 _src_modid_base_index_bk_detach(unit); 356 } 357 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 358 #if defined(BCM_TRIDENT_SUPPORT) 359 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 360 BCM_IF_ERROR_RETURN(bcm_td_modport_map_detach(unit)); 361 } 362 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 363 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 364 bcm_esw_linkscan_unregister(unit, _bcm_stk_modport_map_linkscan_handler); 365 } 366 #endif 367 #endif /* BCM_TRIDENT_SUPPORT */ 368 return BCM_E_NONE; 369 } 370 371 #if defined(BCM_TRX_SUPPORT) 372 /* 373 * Function: 374 * bcmi_trx_modport_map_free_resources 375 * Purpose: 376 * Free resources of software modport map profiles. 377 * Parameters: 378 * unit - (IN) Unit number 379 * Returns: 380 * None 381 */ 382 STATIC void 383 bcmi_trx_modport_map_free_resources(int unit) 384 { 385 int i; 386 387 if (bcmi_trx_modport_map_info[unit]) { 388 if (TRX_MODPORT_MAP_INFO(unit)->profile_array) { 389 for (i = 0; i < TRX_MODPORT_MAP_INFO(unit)->num_profiles; i++) { 390 if (TRX_MODPORT_MAP_PROFILE(unit, i).entry_array) { 391 sal_free(TRX_MODPORT_MAP_PROFILE(unit, i).entry_array); 392 TRX_MODPORT_MAP_PROFILE(unit, i).entry_array = NULL; 393 } 394 } 395 sal_free(TRX_MODPORT_MAP_INFO(unit)->profile_array); 396 TRX_MODPORT_MAP_INFO(unit)->profile_array = NULL; 397 } 398 sal_free(bcmi_trx_modport_map_info[unit]); 399 bcmi_trx_modport_map_info[unit] = NULL; 400 } 401 } 402 403 /* 404 * Function: 405 * bcmi_trx_modport_map_detach 406 * Purpose: 407 * Detach software modport map profiles. 408 * Parameters: 409 * unit - (IN) Unit number 410 * Returns: 411 * BCM_E_xxx 412 */ 413 STATIC int 414 bcmi_trx_modport_map_detach(int unit) 415 { 416 bcmi_trx_modport_map_free_resources(unit); 417 418 return BCM_E_NONE; 419 } 420 421 /* 422 * Function: 423 * bcmi_trx_modport_map_init 424 * Purpose: 425 * Initialize software modport map profiles. 426 * Parameters: 427 * unit - (IN) Unit number 428 * Returns: 429 * BCM_E_xxx 430 */ 431 STATIC int 432 bcmi_trx_modport_map_init(int unit) 433 { 434 int rv = BCM_E_NONE; 435 int i; 436 437 LOG_VERBOSE(BSL_LS_BCM_STK, 438 (BSL_META_U(unit, 439 "bcmi_trx_modport_map_init\n"))); 440 441 /* Global initialization flag setup */ 442 if (trx_modport_map_initialized == 0) { 443 for (i = 0; i < BCM_MAX_NUM_UNITS; i++) { 444 bcmi_trx_modport_map_info[i] = NULL; 445 } 446 trx_modport_map_initialized = 1; 447 } 448 449 /* Clean up the modport map profiles related resources */ 450 if (bcmi_trx_modport_map_info[unit] != NULL) { 451 bcmi_trx_modport_map_detach(unit); 452 } 453 454 /* Allocate modport map profiles resource for this unit. */ 455 bcmi_trx_modport_map_info[unit] = 456 sal_alloc(sizeof(bcmi_trx_modport_map_info_t), "modport map info"); 457 if (NULL == bcmi_trx_modport_map_info[unit]) { 458 return BCM_E_MEMORY; 459 } 460 sal_memset(TRX_MODPORT_MAP_INFO(unit), 0, 461 sizeof(bcmi_trx_modport_map_info_t)); 462 463 TRX_MODPORT_MAP_INFO(unit)->num_profiles = 464 (soc_mem_index_count(unit, MODPORT_MAP_SWm) / 465 (SOC_MODID_MAX(unit) + 1)); 466 467 if (NULL == TRX_MODPORT_MAP_INFO(unit)->profile_array) { 468 TRX_MODPORT_MAP_INFO(unit)->profile_array = 469 sal_alloc(sizeof(bcmi_trx_modport_map_profile_t) * 470 TRX_MODPORT_MAP_INFO(unit)->num_profiles, 471 "trx modport map profiles"); 472 if (NULL == TRX_MODPORT_MAP_INFO(unit)->profile_array) { 473 bcmi_trx_modport_map_free_resources(unit); 474 return BCM_E_MEMORY; 475 } 476 } 477 sal_memset(TRX_MODPORT_MAP_INFO(unit)->profile_array, 0, 478 sizeof(bcmi_trx_modport_map_profile_t) * 479 TRX_MODPORT_MAP_INFO(unit)->num_profiles); 480 481 for (i = 0; i < TRX_MODPORT_MAP_INFO(unit)->num_profiles; i++) { 482 TRX_MODPORT_MAP_PROFILE(unit, i).num_entries = 483 (SOC_MODID_MAX(unit) + 1); 484 if (NULL == TRX_MODPORT_MAP_PROFILE(unit, i).entry_array) { 485 TRX_MODPORT_MAP_PROFILE(unit, i).entry_array = 486 sal_alloc(sizeof(bcmi_trx_modport_map_entry_t) * 487 TRX_MODPORT_MAP_PROFILE(unit, i).num_entries, 488 "trx modport map entries"); 489 if (NULL == TRX_MODPORT_MAP_PROFILE(unit, i).entry_array) { 490 bcmi_trx_modport_map_free_resources(unit); 491 return BCM_E_MEMORY; 492 } 493 } 494 sal_memset(TRX_MODPORT_MAP_PROFILE(unit, i).entry_array, 0, 495 sizeof(bcmi_trx_modport_map_entry_t) * 496 TRX_MODPORT_MAP_PROFILE(unit, i).num_entries); 497 } 498 499 return rv; 500 } 501 #endif /* BCM_TRX_SUPPORT */ 502 503 #ifdef BCM_WARM_BOOT_SUPPORT 504 505 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 506 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 507 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 508 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 509 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 510 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 511 #define BCM_WB_VERSION_1_6 SOC_SCACHE_VERSION(1,6) 512 #define BCM_WB_VERSION_1_7 SOC_SCACHE_VERSION(1,7) 513 #define BCM_WB_VERSION_1_8 SOC_SCACHE_VERSION(1,8) 514 #define BCM_WB_VERSION_1_9 SOC_SCACHE_VERSION(1,9) 515 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_9 516 517 #if defined(BCM_TRX_SUPPORT) 518 /* 519 * Function: 520 * bcmi_trx_modport_map_scache_size_get 521 * Purpose: 522 * Get scache size needed to store software modport map profile state. 523 * Parameters: 524 * unit - (IN) Unit number 525 * max_num_ports - (IN) Maximum number ports 526 * size - (OUT) Scache size needed. 527 * Returns: 528 * None 529 */ 530 STATIC int 531 bcmi_trx_modport_map_scache_size_get(int unit, int max_num_ports, int *size) 532 { 533 /* For each modport map profile entry, max_num_ports bytes of internal 534 * state need to be stored: 535 * - First byte to n (n = max_num_ports): 536 * bit 7 = dest_istrunk[n], bits 6-0 = dest[n]. 537 */ 538 *size = (max_num_ports * sizeof(uint8)) * 539 soc_mem_index_count(unit, MODPORT_MAP_SWm); 540 541 return BCM_E_NONE; 542 } 543 544 /* 545 * Function: 546 * bcmi_trx_modport_map_sync 547 * Purpose: 548 * Store software modport map profile state to scache. 549 * Parameters: 550 * unit - (IN) Unit number 551 * scache_ptr - Scache pointer. 552 * Returns: 553 * None 554 */ 555 STATIC int 556 bcmi_trx_modport_map_sync(int unit, uint8 **scache_ptr) 557 { 558 int i, j, k; 559 bcmi_trx_modport_map_profile_t profile; 560 int istrunk, dest; 561 uint8 dest_byte; 562 563 for (i = 0; i < TRX_MODPORT_MAP_INFO(unit)->num_profiles; i++) { 564 profile = TRX_MODPORT_MAP_PROFILE(unit, i); 565 for (j = 0; j < profile.num_entries; j++) { 566 for (k = 0; k < SOC_MAX_NUM_PORTS; k++) { 567 istrunk = profile.entry_array[j].dest_istrunk[k]; 568 dest = profile.entry_array[j].dest[k]; 569 570 dest_byte = ((istrunk & 0x1) << 7) | (dest & 0x7f); 571 sal_memcpy(*scache_ptr, &dest_byte, sizeof(dest_byte)); 572 *scache_ptr += sizeof(dest_byte); 573 } 574 } 575 } 576 577 return BCM_E_NONE; 578 } 579 580 /* 581 * Function: 582 * bcmi_trx_modport_map_reinit 583 * Purpose: 584 * Retrieve software modport map profile state from scache. 585 * Parameters: 586 * unit - (IN) Unit number 587 * max_num_ports - (IN) Maximum number ports 588 * scache_ptr - Scache pointer. 589 * Returns: 590 * None 591 */ 592 STATIC int 593 bcmi_trx_modport_map_reinit(int unit, int max_num_ports, uint8 **scache_ptr) 594 { 595 int rv = BCM_E_NONE; 596 bcm_port_t ing_port; 597 uint32 val; 598 int profile_index; 599 int i, j, k; 600 soc_mem_t mem; 601 bcmi_trx_modport_map_profile_t profile; 602 int modport_map_entry_dw, modport_map_entry_sz; 603 int modport_map_buf_size; 604 uint8 *modport_map_buf = NULL; 605 int index_min, index_max; 606 modport_map_entry_t *entry_p; 607 pbmp_t pbmp; 608 uint8 dest_byte; 609 bcm_pbmp_t all_pbmp; 610 611 BCM_PBMP_CLEAR(all_pbmp); 612 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 613 614 /* Recover each profile's reference count */ 615 PBMP_ITER(all_pbmp, ing_port) { 616 BCM_IF_ERROR_RETURN( 617 READ_MODPORT_MAP_SELr(unit, ing_port, &val)); 618 profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val, 619 MODPORT_MAP_INDEX_UPPERf); 620 TRX_MODPORT_MAP_PROFILE(unit, profile_index).ref_count++; 621 } 622 623 mem = MODPORT_MAP_SWm; 624 for (i = 0; i < TRX_MODPORT_MAP_INFO(unit)->num_profiles; i++) { 625 profile = TRX_MODPORT_MAP_PROFILE(unit, i); 626 if (profile.ref_count == 0) { 627 /* Skip the scache region containing the state of this profile */ 628 if (*scache_ptr != NULL) { 629 *scache_ptr += profile.num_entries * 630 (max_num_ports * sizeof(dest_byte)); 631 } 632 continue; 633 } 634 635 /* Read profile from MODPOR_MAP_SWm */ 636 modport_map_entry_dw = soc_mem_entry_words(unit, mem); 637 modport_map_entry_sz = modport_map_entry_dw * sizeof(uint32); 638 modport_map_buf_size = profile.num_entries * modport_map_entry_sz; 639 modport_map_buf = soc_cm_salloc(unit, modport_map_buf_size, 640 "modport map buffer"); 641 if (NULL == modport_map_buf) { 642 return BCM_E_MEMORY; 643 } 644 645 index_min = i * profile.num_entries; 646 index_max = index_min + profile.num_entries - 1; 647 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 648 index_min, index_max, modport_map_buf); 649 if (BCM_FAILURE(rv)) { 650 soc_cm_sfree(unit, modport_map_buf); 651 return rv; 652 } 653 654 /* Recover profile state */ 655 for (j = 0; j < profile.num_entries; j++) { 656 entry_p = soc_mem_table_idx_to_pointer(unit, mem, 657 modport_map_entry_t *, 658 modport_map_buf, j); 659 soc_mem_pbmp_field_get(unit, mem, entry_p, 660 HIGIG_PORT_BITMAPf, &pbmp); 661 for (k = 0; k < max_num_ports; k++) { 662 if (*scache_ptr != NULL) { 663 sal_memcpy(&dest_byte, *scache_ptr, sizeof(dest_byte)); 664 *scache_ptr += sizeof(dest_byte); 665 profile.entry_array[j].dest_istrunk[k] = 666 (dest_byte >> 7) & 0x1; 667 profile.entry_array[j].dest[k] = dest_byte & 0x7f; 668 } else { 669 if (BCM_PBMP_MEMBER(pbmp, k)) { 670 profile.entry_array[j].dest_istrunk[k] = 0; 671 profile.entry_array[j].dest[k] = k; 672 } 673 } 674 } 675 } 676 677 soc_cm_sfree(unit, modport_map_buf); 678 } 679 680 return rv; 681 } 682 #endif /* BCM_TRX_SUPPORT */ 683 684 /* 685 * Function: 686 * _bcm_esw_stk_sync 687 * Purpose: 688 * Record STACK module persisitent info for Level 2 Warm Boot 689 * Parameters: 690 * unit - Unit number. 691 * Returns: 692 * BCM_E_XXX 693 */ 694 int 695 _bcm_esw_stk_sync(int unit) 696 { 697 soc_scache_handle_t scache_handle; 698 uint8 *stk_scache_ptr; 699 int rv = BCM_E_NONE; 700 int auto_include_disable = 0; 701 702 #if defined(LOCAL_MODMAP_SUPPORT) 703 STACK_INIT(unit); 704 #endif 705 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_STACK, 0); 706 BCM_IF_ERROR_RETURN 707 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 708 0, &stk_scache_ptr, 709 BCM_WB_DEFAULT_VERSION, NULL)); 710 /* Stack port bitmaps */ 711 sal_memcpy(stk_scache_ptr, &SOC_PBMP_STACK_CURRENT(unit), 712 sizeof(soc_pbmp_t)); 713 stk_scache_ptr += sizeof(soc_pbmp_t); 714 sal_memcpy(stk_scache_ptr, &SOC_PBMP_STACK_INACTIVE(unit), 715 sizeof(soc_pbmp_t)); 716 stk_scache_ptr += sizeof(soc_pbmp_t); 717 sal_memcpy(stk_scache_ptr, &SOC_PBMP_STACK_PREVIOUS(unit), 718 sizeof(soc_pbmp_t)); 719 stk_scache_ptr += sizeof(soc_pbmp_t); 720 721 #if defined(LOCAL_MODMAP_SUPPORT) 722 /* Modmap */ 723 if (soc_feature(unit, soc_feature_modmap)) { 724 int i; 725 int port; 726 int max_group; 727 uint8 val; 728 729 for (port = 0; port < SOC_MAX_NUM_PORTS; port++) { 730 val = mod_map_data[unit]->l_modid[port]; 731 sal_memcpy(stk_scache_ptr, &val, sizeof(val)); 732 stk_scache_ptr += sizeof(val); 733 } 734 735 for (i = 0; i < _NUM_SL_MOD; i++) { 736 val = mod_map_data[unit]->thresh_d[i]; 737 sal_memcpy(stk_scache_ptr, &val, sizeof(val)); 738 stk_scache_ptr += sizeof(val); 739 } 740 741 BCM_IF_ERROR_RETURN 742 (bcm_esw_stk_port_modmap_group_max_get(unit, &max_group)); 743 for (i = 0; i <= max_group; i++) { 744 val = mod_map_data[unit]->fmod0[i]; 745 sal_memcpy(stk_scache_ptr, &val, sizeof(val)); 746 stk_scache_ptr += sizeof(val); 747 } 748 } 749 #endif /* LOCAL_MODMAP_SUPPORT */ 750 751 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 752 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 753 int i, modid; 754 uint8 val; 755 soc_info_t *si = &SOC_INFO(unit); 756 757 for (i = 0; i <= SOC_MODID_MAX(unit); i++) { 758 /* num_ports is uint16, here store the low 8bits, 759 * the high 8bits see below. */ 760 val = src_modid_base_index_bk[unit]->num_ports[i] & 0xff; 761 sal_memcpy(stk_scache_ptr, &val, sizeof(val)); 762 stk_scache_ptr += sizeof(val); 763 } 764 765 if(soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 766 for (i = 0; i < si->num_coe_modules; i++) { 767 modid = src_modid_base_index_bk[unit]-> 768 coe_module_id_list[i]; 769 sal_memcpy(stk_scache_ptr, &modid, sizeof(modid)); 770 stk_scache_ptr += sizeof(modid); 771 } 772 } 773 774 /* Version_1_4 -> Version_1_5: 775 * module_id_range is introduced by Version_1_5 776 * Store src_modid_base_index_bk[unit]->module_id_range to scache. */ 777 if(soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 778 int mod_base = 0; 779 uint32 mod_mask = 0; 780 781 mod_base = src_modid_base_index_bk[unit]->module_id_range.mod_base; 782 sal_memcpy(stk_scache_ptr, &mod_base, sizeof(mod_base)); 783 stk_scache_ptr += sizeof(mod_base); 784 mod_mask = src_modid_base_index_bk[unit]->module_id_range.mod_mask; 785 sal_memcpy(stk_scache_ptr, &mod_mask, sizeof(mod_mask)); 786 stk_scache_ptr += sizeof(mod_mask); 787 } 788 } 789 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 790 791 #if defined(BCM_TRIDENT_SUPPORT) 792 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 793 BCM_IF_ERROR_RETURN(bcm_td_modport_map_sync(unit, &stk_scache_ptr)); 794 } 795 #endif /* BCM_TRIDENT_SUPPORT */ 796 797 #if defined(BCM_TRX_SUPPORT) 798 if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) { 799 BCM_IF_ERROR_RETURN( 800 bcmi_trx_modport_map_sync(unit, &stk_scache_ptr)); 801 } 802 #endif /* BCM_TRX_SUPPORT */ 803 804 rv = bcm_esw_switch_control_get(unit, 805 bcmSwitchFabricTrunkAutoIncludeDisable, &auto_include_disable); 806 if (BCM_E_UNAVAIL == rv) { 807 auto_include_disable = 0; 808 } else if (BCM_FAILURE(rv)) { 809 return rv; 810 } 811 sal_memcpy(stk_scache_ptr, &auto_include_disable, sizeof(int)); 812 stk_scache_ptr += sizeof(int); 813 814 #if defined(BCM_TRIDENT_SUPPORT) 815 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 816 BCM_IF_ERROR_RETURN( 817 bcm_td_stk_trunk_override_hi_sync(unit, &stk_scache_ptr)); 818 } 819 #endif /* BCM_TRIDENT_SUPPORT */ 820 #if defined(BCM_TRIUMPH3_SUPPORT) 821 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 822 BCM_IF_ERROR_RETURN( 823 bcm_td_modport_map_enable_sync(unit, &stk_scache_ptr)); 824 } 825 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */ 826 827 /* Version_1_5 -> Version_1_6: 828 * uint8 is not enough for src_modid_base_index_bk[unit]->num_ports 829 * Store the High-unit8 to scache */ 830 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 831 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 832 int i; 833 uint8 val; 834 for (i = 0; i <= SOC_MODID_MAX(unit); i++) { 835 val = (src_modid_base_index_bk[unit]->num_ports[i] >> 8); 836 sal_memcpy(stk_scache_ptr, &val, sizeof(val)); 837 stk_scache_ptr += sizeof(val); 838 } 839 } 840 #endif 841 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 842 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 843 BCM_IF_ERROR_RETURN( 844 bcm_td_linkflap_trunk_map_sync(unit, &stk_scache_ptr)); 845 } 846 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */ 847 848 /* Version_1_8 -> Version_1_9: 849 * module_id_type_list & multi_nexthop_module_id_list are introduced by Version_1_9 850 * Store src_modid_base_index_bk[unit]->module_id_type_list and 851 * src_modid_base_index_bk[unit]->multi_nexthop_module_id_list to scache. */ 852 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 853 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 854 int i, val; 855 soc_info_t *si = &SOC_INFO(unit); 856 for (i = 0; i < si->num_modules; i++) { 857 val = src_modid_base_index_bk[unit]->module_id_type_list[i]; 858 sal_memcpy(stk_scache_ptr, &val, sizeof(val)); 859 stk_scache_ptr += sizeof(val); 860 } 861 862 for (i = 0; i < si->num_modules; i++) { 863 val = src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i]; 864 sal_memcpy(stk_scache_ptr, &val, sizeof(val)); 865 stk_scache_ptr += sizeof(val); 866 } 867 } 868 #endif 869 870 return BCM_E_NONE; 871 } 872 873 /* 874 * Function: 875 * _bcm_stk_reinit 876 * Purpose: 877 * Recover STACK software state. 878 * Parameters: 879 * unit - Unit number. 880 * Returns: 881 * BCM_E_XXX 882 */ 883 STATIC int 884 _bcm_stk_reinit(int unit) 885 { 886 int rv; 887 soc_scache_handle_t scache_handle; 888 uint8 *stk_scache_ptr; 889 uint16 recovered_ver; 890 int auto_include_disable; 891 int realloc_sz; 892 #if defined(LOCAL_MODMAP_SUPPORT) 893 int max_num_ports = SOC_MAX_NUM_PORTS; 894 #endif /* LOCAL_MODMAP_SUPPORT */ 895 896 realloc_sz = 0; 897 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_STACK, 0); 898 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 899 0, &stk_scache_ptr, 900 BCM_WB_DEFAULT_VERSION, &recovered_ver); 901 902 if (rv == BCM_E_NOT_FOUND) { 903 stk_scache_ptr = NULL; 904 } else if (BCM_FAILURE(rv)) { 905 return rv; 906 } 907 908 #if defined(LOCAL_MODMAP_SUPPORT) 909 if (stk_scache_ptr != NULL) { 910 max_num_ports = soc_scache_dictionary_entry_get(unit, 911 ssden_SOC_MAX_NUM_PORTS, 912 SOC_MAX_NUM_PORTS); 913 } 914 #endif /* LOCAL_MODMAP_SUPPORT */ 915 916 if (stk_scache_ptr != NULL) { 917 /* Stack port bitmaps */ 918 sal_memcpy(&SOC_PBMP_STACK_CURRENT(unit), stk_scache_ptr, 919 sizeof(soc_pbmp_t)); 920 stk_scache_ptr += sizeof(soc_pbmp_t); 921 sal_memcpy(&SOC_PBMP_STACK_INACTIVE(unit), stk_scache_ptr, 922 sizeof(soc_pbmp_t)); 923 stk_scache_ptr += sizeof(soc_pbmp_t); 924 sal_memcpy(&SOC_PBMP_STACK_PREVIOUS(unit), stk_scache_ptr, 925 sizeof(soc_pbmp_t)); 926 stk_scache_ptr += sizeof(soc_pbmp_t); 927 } else { 928 BCM_PBMP_CLEAR(SOC_PBMP_STACK_CURRENT(unit)); 929 BCM_PBMP_CLEAR(SOC_PBMP_STACK_INACTIVE(unit)); 930 BCM_PBMP_CLEAR(SOC_PBMP_STACK_PREVIOUS(unit)); 931 } 932 933 BCM_IF_ERROR_RETURN(_bcm_esw_stk_init()); 934 935 #if defined(LOCAL_MODMAP_SUPPORT) 936 /* Modmap */ 937 if (soc_feature(unit, soc_feature_modmap)) { 938 int i; 939 int port; 940 int max_group; 941 uint8 val; 942 943 BCM_IF_ERROR_RETURN(_bcm_esw_modmap_init(unit)); 944 945 /* Recover l_modid, thresh_d, and fmod0 */ 946 if (stk_scache_ptr != NULL) { 947 for (port = 0; port < max_num_ports; port++) { 948 if (port < SOC_MAX_NUM_PORTS) { 949 sal_memcpy(&val, stk_scache_ptr, sizeof(val)); 950 mod_map_data[unit]->l_modid[port] = val; 951 } 952 stk_scache_ptr += sizeof(val); 953 } 954 realloc_sz += (SOC_MAX_NUM_PORTS - max_num_ports) * sizeof(val); 955 956 for (i = 0; i < _NUM_SL_MOD; i++) { 957 sal_memcpy(&val, stk_scache_ptr, sizeof(val)); 958 mod_map_data[unit]->thresh_d[i] = val; 959 stk_scache_ptr += sizeof(val); 960 } 961 962 BCM_IF_ERROR_RETURN 963 (bcm_esw_stk_port_modmap_group_max_get(unit, &max_group)); 964 for (i = 0; i <= max_group; i++) { 965 sal_memcpy(&val, stk_scache_ptr, sizeof(val)); 966 mod_map_data[unit]->fmod0[i] = val; 967 stk_scache_ptr += sizeof(val); 968 } 969 } 970 } 971 #endif /* LOCAL_MODMAP_SUPPORT */ 972 973 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 974 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 975 int i, modId; 976 uint8 val; 977 uint8 *stm_modoffset_buf = NULL; 978 source_trunk_map_modbase_entry_t *stm_modoffset_entry; 979 int start, end, offset, offset_max; 980 soc_info_t *si = &SOC_INFO(unit); 981 982 BCM_IF_ERROR_RETURN(bcmi_esw_src_modid_base_index_bk_init(unit)); 983 984 stm_modoffset_buf = soc_cm_salloc(unit, 985 SOC_MEM_TABLE_BYTES(unit, SOURCE_TRUNK_MAP_MODBASEm), 986 "SOURCE_TRUNK_MAP_MODBASE buffer"); 987 if (NULL == stm_modoffset_buf) { 988 return BCM_E_MEMORY; 989 } 990 991 start = soc_mem_index_min(unit, SOURCE_TRUNK_MAP_MODBASEm); 992 end = soc_mem_index_max(unit, SOURCE_TRUNK_MAP_MODBASEm); 993 rv = soc_mem_read_range(unit, SOURCE_TRUNK_MAP_MODBASEm, 994 MEM_BLOCK_ANY, start, end, stm_modoffset_buf); 995 if (SOC_FAILURE(rv)) { 996 soc_cm_sfree(unit, stm_modoffset_buf); 997 return rv; 998 } 999 1000 if (stk_scache_ptr != NULL) { 1001 1002 /* Recover low-8bits of src_modid_base_index_bk[unit]->num_ports array */ 1003 for (i = 0; i <= SOC_MODID_MAX(unit); i++) { 1004 sal_memcpy(&val, stk_scache_ptr, sizeof(val)); 1005 src_modid_base_index_bk[unit]->num_ports[i] = val; 1006 stk_scache_ptr += sizeof(val); 1007 } 1008 1009 if(soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 1010 for (i = 0; i < si->num_coe_modules; i++) { 1011 sal_memcpy(&modId, stk_scache_ptr, sizeof(modId)); 1012 src_modid_base_index_bk[unit]->coe_module_id_list[i] = modId; 1013 stk_scache_ptr += sizeof(modId); 1014 } 1015 } 1016 1017 /* Version_1_4 -> Version_1_5: 1018 * module_id_range is introduced by Version_1_5 1019 * Recover src_modid_base_index_bk[unit]->module_id_range from scache. */ 1020 if(soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 1021 int mod_base = 0; 1022 uint32 mod_mask = 0; 1023 1024 sal_memcpy(&mod_base, stk_scache_ptr, sizeof(mod_base)); 1025 src_modid_base_index_bk[unit]->module_id_range.mod_base = mod_base; 1026 stk_scache_ptr += sizeof(mod_base); 1027 sal_memcpy(&mod_mask, stk_scache_ptr, sizeof(mod_mask)); 1028 src_modid_base_index_bk[unit]->module_id_range.mod_mask = mod_mask; 1029 stk_scache_ptr += sizeof(mod_mask); 1030 } 1031 } else { 1032 /* In Level 1 recovery of src_modid_base_index_bk[unit]-> 1033 * src_mod_port_table_bitmap, it's not known how many 1034 * SOURCE_TRUNK_MAP entries each module ID occupies. 1035 * Hence, we conservatively assume that all 1036 * SOURCE_TRUNK_MAP entries from index 0 to (highest 1037 * SOURCE_TRUNK_MAP_MODBASE.BASE + SOC_PORT_ADDR_MAX) 1038 * are used. 1039 */ 1040 offset_max = 0; 1041 for (i = start; i <= end; i++) { 1042 stm_modoffset_entry = soc_mem_table_idx_to_pointer 1043 (unit, SOURCE_TRUNK_MAP_MODBASEm, 1044 source_trunk_map_modbase_entry_t *, stm_modoffset_buf, i); 1045 offset = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit, 1046 stm_modoffset_entry, BASEf); 1047 if (offset > offset_max) { 1048 offset_max = offset; 1049 } 1050 } 1051 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, 0, 1052 (offset_max + SOC_PORT_ADDR_MAX(unit) + 1)); 1053 } 1054 1055 soc_cm_sfree(unit, stm_modoffset_buf); 1056 } 1057 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 1058 1059 #if defined(BCM_TRX_SUPPORT) 1060 /* Modport profile */ 1061 #ifdef BCM_TRIDENT_SUPPORT 1062 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 1063 BCM_IF_ERROR_RETURN(bcm_td_modport_map_init(unit)); 1064 if (stk_scache_ptr != NULL) { 1065 if (recovered_ver >= BCM_WB_VERSION_1_1) { 1066 /* Retrieve modport map profile info from scache */ 1067 BCM_IF_ERROR_RETURN(bcm_td_modport_map_reinit(unit, 1068 &stk_scache_ptr)); 1069 } else { 1070 uint8 *null_scache_ptr = NULL; 1071 int modport_map_scache_size; 1072 1073 /* Retrieve modport map profile info from hardware */ 1074 BCM_IF_ERROR_RETURN(bcm_td_modport_map_reinit(unit, 1075 &null_scache_ptr)); 1076 BCM_IF_ERROR_RETURN(bcm_td_modport_map_scache_size_get(unit, 1077 &modport_map_scache_size)); 1078 realloc_sz += modport_map_scache_size; 1079 } 1080 } else { /* Level 1 warm boot */ 1081 uint8 *null_scache_ptr = NULL; 1082 1083 /* Retrieve modport map profile info from hardware */ 1084 BCM_IF_ERROR_RETURN(bcm_td_modport_map_reinit(unit, 1085 &null_scache_ptr)); 1086 } 1087 } else 1088 #endif /* BCM_TRIDENT_SUPPORT */ 1089 if (SOC_IS_TR_VL(unit)) { 1090 BCM_IF_ERROR_RETURN(_bcm_stk_modport_profile_init(unit)); 1091 } 1092 1093 if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) { 1094 BCM_IF_ERROR_RETURN(bcmi_trx_modport_map_init(unit)); 1095 if (stk_scache_ptr != NULL) { 1096 if (recovered_ver >= BCM_WB_VERSION_1_1) { 1097 /* Retrieve modport map profile info from scache */ 1098 BCM_IF_ERROR_RETURN( 1099 bcmi_trx_modport_map_reinit(unit, max_num_ports, 1100 &stk_scache_ptr)); 1101 } else { 1102 uint8 *null_scache_ptr = NULL; 1103 int modport_map_scache_size; 1104 1105 /* Retrieve modport map profile info from hardware */ 1106 BCM_IF_ERROR_RETURN( 1107 bcmi_trx_modport_map_reinit(unit, max_num_ports, 1108 &null_scache_ptr)); 1109 BCM_IF_ERROR_RETURN( 1110 bcmi_trx_modport_map_scache_size_get 1111 (unit, max_num_ports, &modport_map_scache_size)); 1112 realloc_sz += modport_map_scache_size; 1113 } 1114 } else { /* Level 1 warm boot */ 1115 uint8 *null_scache_ptr = NULL; 1116 1117 /* Retrieve modport map profile info from hardware */ 1118 BCM_IF_ERROR_RETURN( 1119 bcmi_trx_modport_map_reinit(unit, max_num_ports, 1120 &null_scache_ptr)); 1121 } 1122 } 1123 #endif /* BCM_TRX_SUPPORT */ 1124 1125 auto_include_disable = 0; 1126 if (stk_scache_ptr != NULL) { 1127 if (recovered_ver >= BCM_WB_VERSION_1_2) { 1128 /* Retrieve bcmSwitchFabricTrunkAutoIncludeDisable value */ 1129 sal_memcpy(&auto_include_disable, stk_scache_ptr, sizeof(int)); 1130 stk_scache_ptr += sizeof(int); 1131 } else { 1132 realloc_sz += sizeof(int); 1133 } 1134 } 1135 rv = bcm_esw_switch_control_set(unit, bcmSwitchFabricTrunkAutoIncludeDisable, 1136 auto_include_disable); 1137 if (BCM_FAILURE(rv) && (BCM_E_UNAVAIL != rv)) { 1138 return rv; 1139 } 1140 #ifdef BCM_TRIDENT_SUPPORT 1141 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 1142 if (stk_scache_ptr != NULL) { 1143 if (recovered_ver >= BCM_WB_VERSION_1_3) { 1144 /* Retrieve modport map profile info from scache */ 1145 BCM_IF_ERROR_RETURN(bcm_td_stk_trunk_override_hi_reinit(unit, 1146 &stk_scache_ptr)); 1147 } else { 1148 int higig_trunk_override_hi_scache_size; 1149 BCM_IF_ERROR_RETURN 1150 (bcm_td_stk_trunk_override_hi_scache_size_get(unit, 1151 &higig_trunk_override_hi_scache_size)); 1152 realloc_sz += higig_trunk_override_hi_scache_size; 1153 } 1154 } 1155 } 1156 #endif /* BCM_TRIDENT_SUPPORT */ 1157 1158 #if defined(BCM_TRIUMPH3_SUPPORT) 1159 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 1160 if (stk_scache_ptr != NULL) { 1161 if (recovered_ver >= BCM_WB_VERSION_1_4) { 1162 BCM_IF_ERROR_RETURN(bcm_td_modport_map_enable_reinit(unit, 1163 &stk_scache_ptr)); 1164 } else { 1165 int modport_map_enable_size; 1166 BCM_IF_ERROR_RETURN( 1167 bcm_td_modport_map_enable_scache_size_get(unit, 1168 &modport_map_enable_size)); 1169 realloc_sz += modport_map_enable_size; 1170 } 1171 } 1172 } 1173 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */ 1174 1175 /* Version_1_5 -> Version_1_6: 1176 * uint8 is not enough for src_modid_base_index_bk[unit]->num_ports 1177 * Store the High-unit8 to scache */ 1178 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 1179 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 1180 int i; 1181 uint8 val; 1182 uint8 *stm_modbase_buf = NULL; 1183 source_trunk_map_modbase_entry_t *stm_modbase_entry; 1184 int index_min, index_max, base, num_ports; 1185 1186 #ifdef BCM_TRIDENT2PLUS_SUPPORT 1187 bcm_module_t my_modid = 0; 1188 int skip_base_idx = 0; 1189 #endif 1190 1191 stm_modbase_buf = soc_cm_salloc(unit, 1192 SOC_MEM_TABLE_BYTES(unit, SOURCE_TRUNK_MAP_MODBASEm), 1193 "SOURCE_TRUNK_MAP_MODBASE buffer"); 1194 if (NULL == stm_modbase_buf) { 1195 return BCM_E_MEMORY; 1196 } 1197 1198 index_min = soc_mem_index_min(unit, SOURCE_TRUNK_MAP_MODBASEm); 1199 index_max = soc_mem_index_max(unit, SOURCE_TRUNK_MAP_MODBASEm); 1200 rv = soc_mem_read_range(unit, SOURCE_TRUNK_MAP_MODBASEm, 1201 MEM_BLOCK_ANY, index_min, index_max, stm_modbase_buf); 1202 if (SOC_FAILURE(rv)) { 1203 soc_cm_sfree(unit, stm_modbase_buf); 1204 return rv; 1205 } 1206 1207 /* Recover high-8bits of num_ports */ 1208 if (stk_scache_ptr != NULL) { 1209 if (recovered_ver >= BCM_WB_VERSION_1_6) { 1210 for (i = 0; i <= SOC_MODID_MAX(unit); i++) { 1211 sal_memcpy(&val, stk_scache_ptr, sizeof(val)); 1212 src_modid_base_index_bk[unit]->num_ports[i] |= (val << 8); 1213 stk_scache_ptr += sizeof(val); 1214 } 1215 } else { 1216 for (i = 0; i <= SOC_MODID_MAX(unit); i++) { 1217 realloc_sz += sizeof(val); 1218 } 1219 } 1220 } 1221 1222 #ifdef BCM_TRIDENT2PLUS_SUPPORT 1223 if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit)) { 1224 BCM_IF_ERROR_RETURN( 1225 bcm_esw_stk_my_modid_get(unit, &my_modid)); 1226 } 1227 #endif 1228 1229 /* Recover src_modid_base_index_bk[unit]->src_mod_port_table_bitmap */ 1230 for (i = index_min; i <= index_max; i++) { 1231 stm_modbase_entry = soc_mem_table_idx_to_pointer 1232 (unit, SOURCE_TRUNK_MAP_MODBASEm, 1233 source_trunk_map_modbase_entry_t *, stm_modbase_buf, i); 1234 1235 base = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit, 1236 stm_modbase_entry, BASEf); 1237 num_ports = src_modid_base_index_bk[unit]->num_ports[i]; 1238 #ifdef BCM_TRIDENT2PLUS_SUPPORT 1239 if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || 1240 SOC_IS_TRIDENT3X(unit)) { 1241 skip_base_idx = 1242 src_modid_base_index_bk[unit]->default_base_idx; 1243 if (((base < skip_base_idx) && 1244 ((base + num_ports) >= skip_base_idx)) || 1245 ((base >= skip_base_idx) && 1246 (base <= (SOC_PORT_ADDR_MAX(unit) + skip_base_idx)))) { 1247 /* If the retrieved base index lies in between the range 1248 * of entries blocked for non-configured MOD IDs then 1249 * skip learning those. This should only happen in cases 1250 * if upgrading from older version which did not have 1251 * support for blocking explicit entries for non 1252 * configured MOD IDs. It is highly unlikely that this 1253 * range i.e base index of 8K-128 will be used for valid 1254 * MOD IDs in older version. Although it is possible but 1255 * chances are truly very low. If such scenario exists 1256 * we will just lose that MOD ID configuration. 1257 */ 1258 continue; 1259 } else if ((0==base) && 1260 (recovered_ver<=BCM_WB_VERSION_1_6) && (i!=my_modid)) { 1261 /* Older versions shared base index 0 for 1262 * non-configured MOD IDs and local Mod ID 1263 */ 1264 continue; 1265 } 1266 } else 1267 #endif 1268 { 1269 if (0 == base) { 1270 continue; 1271 } 1272 } 1273 1274 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, base, num_ports); 1275 1276 /* Recover source trunk mapping cache and trunk members 1277 * that have EGRESS_DISABLE flags set. 1278 */ 1279 #ifdef BCM_HURRICANE3_SUPPORT 1280 if (SOC_IS_HURRICANE3(unit)) { 1281 rv = _bcm_xgs3_trunk_mod_port_map_reinit(unit, i, base, 1282 num_ports); 1283 } else 1284 #endif /* BCM_HURRICANE3_SUPPORT */ 1285 { 1286 #ifdef BCM_TRIDENT_SUPPORT 1287 rv = _bcm_trident_trunk_mod_port_map_reinit(unit, i, base, 1288 num_ports); 1289 #endif /* BCM_TRIDENT_SUPPORT */ 1290 } 1291 if (SOC_FAILURE(rv)) { 1292 soc_cm_sfree(unit, stm_modbase_buf); 1293 return rv; 1294 } 1295 } 1296 1297 soc_cm_sfree(unit, stm_modbase_buf); 1298 } 1299 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 1300 1301 /* Version_1_7 -> Version_1_8*/ 1302 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 1303 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 1304 if (stk_scache_ptr != NULL) { 1305 if (recovered_ver >= BCM_WB_VERSION_1_8) { 1306 BCM_IF_ERROR_RETURN(bcm_td_linkflap_trunk_map_reinit(unit, 1307 &stk_scache_ptr)); 1308 } else { 1309 int linkflap_trunk_map_size; 1310 BCM_IF_ERROR_RETURN( 1311 bcm_td_linkflap_trunk_map_scache_size_get(unit, 1312 &linkflap_trunk_map_size)); 1313 realloc_sz += linkflap_trunk_map_size; 1314 } 1315 } 1316 } 1317 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */ 1318 1319 /* Version_1_8 -> Version_1_9: 1320 * module_id_type_list & multi_nexthop_module_id_list are introduced by Version_1_9 1321 * Recover src_modid_base_index_bk[unit]->module_id_type_list and 1322 * src_modid_base_index_bk[unit]->multi_nexthop_module_id_list from scache. */ 1323 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1324 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 1325 int i, val; 1326 soc_info_t *si = &SOC_INFO(unit); 1327 1328 if (stk_scache_ptr != NULL) { 1329 if (recovered_ver >= BCM_WB_VERSION_1_9) { 1330 for (i = 0; i < si->num_modules; i++) { 1331 sal_memcpy(&val, stk_scache_ptr, sizeof(val)); 1332 src_modid_base_index_bk[unit]->module_id_type_list[i] = val; 1333 stk_scache_ptr += sizeof(val); 1334 } 1335 1336 for (i = 0; i < si->num_modules; i++) { 1337 sal_memcpy(&val, stk_scache_ptr, sizeof(val)); 1338 src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] = val; 1339 stk_scache_ptr += sizeof(val); 1340 } 1341 } else { 1342 for (i = 0; i <= si->num_modules; i++) { 1343 realloc_sz += sizeof(val) * 2; 1344 } 1345 } 1346 } 1347 } 1348 #endif 1349 1350 if (realloc_sz > 0) { 1351 BCM_IF_ERROR_RETURN( 1352 soc_scache_realloc(unit, scache_handle, realloc_sz)); 1353 } 1354 1355 return BCM_E_NONE; 1356 } 1357 #endif /* BCM_WARM_BOOT_SUPPORT */ 1358 1359 /* 1360 * Function: 1361 * _bcm_esw_stk_prepare 1362 * Purpose: 1363 * prepare initialize device stacking 1364 * no need to prepare _src_modid_base_index_bk 1365 * as it is already initialized during common init 1366 * Parameters: 1367 * unit - (IN) BCM device number. 1368 * Returns: 1369 * BCM_E_XXX 1370 */ 1371 1372 STATIC int 1373 _bcm_esw_stk_init_prepare(int unit) 1374 { 1375 if (stack_mutex != NULL) { 1376 sal_mutex_destroy(stack_mutex); 1377 stack_mutex = NULL; 1378 } 1379 1380 BCM_IF_ERROR_RETURN(bcm_esw_stk_modmap_unregister(unit)); 1381 1382 #if defined(LOCAL_MODMAP_SUPPORT) 1383 if (soc_feature(unit, soc_feature_modmap)) { 1384 SOC_IF_ERROR_RETURN(_bcm_esw_modmap_detach(unit)); 1385 } 1386 #endif /* MODMAP_SUPPORT */ 1387 1388 #if defined(BCM_TRX_SUPPORT) 1389 if (modport_profile[unit]) { 1390 soc_profile_mem_destroy(unit, modport_profile[unit]); 1391 sal_free(modport_profile[unit]); 1392 modport_profile[unit] = NULL; 1393 } 1394 1395 if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) { 1396 BCM_IF_ERROR_RETURN(bcmi_trx_modport_map_detach(unit)); 1397 } 1398 #endif /* BCM_TRX_SUPPORT */ 1399 1400 #if defined(BCM_TRIDENT_SUPPORT) 1401 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 1402 BCM_IF_ERROR_RETURN(bcm_td_modport_map_detach(unit)); 1403 } 1404 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 1405 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 1406 bcm_esw_linkscan_unregister(unit, _bcm_stk_modport_map_linkscan_handler); 1407 } 1408 #endif 1409 #endif /* BCM_TRIDENT_SUPPORT */ 1410 return BCM_E_NONE; 1411 } 1412 1413 1414 /* 1415 * Function: 1416 * bcm_stk_init 1417 * Purpose: 1418 * Initialize device stacking 1419 * Parameters: 1420 * unit - SOC unit # 1421 * Returns: 1422 * BCM_E_XXX 1423 */ 1424 1425 int 1426 bcm_esw_stk_init(int unit) 1427 { 1428 int rv; 1429 #ifdef BCM_WARM_BOOT_SUPPORT 1430 soc_scache_handle_t scache_handle; 1431 uint32 stk_scache_size; 1432 uint8 *stk_scache_ptr; 1433 #endif /* BCM_WARM_BOOT_SUPPORT */ 1434 1435 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 1436 1437 LOG_VERBOSE(BSL_LS_BCM_STK, 1438 (BSL_META_U(unit, 1439 "STK %d: Init\n"), 1440 unit)); 1441 1442 if (SOC_IS_SHADOW(unit)) { 1443 return BCM_E_UNAVAIL; 1444 } 1445 1446 1447 #ifdef BCM_WARM_BOOT_SUPPORT 1448 /* Warm boot level 2 cache size */ 1449 /* Stack ports current, inactive, previous */ 1450 stk_scache_size = sizeof(soc_pbmp_t) * 3; 1451 1452 #if defined(LOCAL_MODMAP_SUPPORT) 1453 /* Modmap */ 1454 if (soc_feature(unit, soc_feature_modmap)) { 1455 int max_group; 1456 1457 BCM_IF_ERROR_RETURN 1458 (bcm_esw_stk_port_modmap_group_max_get(unit, &max_group)); 1459 1460 /* Max values for l_modid, thresh_d, fmod0 fits in uint8 */ 1461 stk_scache_size += (sizeof(uint8) * SOC_MAX_NUM_PORTS); /* l_modid */ 1462 stk_scache_size += (sizeof(uint8) * _NUM_SL_MOD); /* thresh_d */ 1463 stk_scache_size += (sizeof(uint8) * (max_group + 1)); /* fmod0 */ 1464 } 1465 #endif /* LOCAL_MODMAP_SUPPORT */ 1466 1467 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 1468 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 1469 /* Allocate space for src_modid_base_index_bk[unit]->num_ports array */ 1470 stk_scache_size += (sizeof(uint8) * (SOC_MODID_MAX(unit) + 1)); 1471 if(soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 1472 stk_scache_size += (sizeof(int) * (SOC_MODID_MAX(unit) + 1)); 1473 } 1474 1475 /* Version_1_4 -> Version_1_5: 1476 * module_id_range is introduced by Version_1_5 1477 * Allocate space for src_modid_base_index_bk[unit]->module_id_range */ 1478 if(soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 1479 stk_scache_size += sizeof(module_id_mask_t); 1480 } 1481 } 1482 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 1483 #if defined(BCM_TRIDENT_SUPPORT) 1484 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 1485 int modport_map_scache_size; 1486 BCM_IF_ERROR_RETURN 1487 (bcm_td_modport_map_scache_size_get(unit, &modport_map_scache_size)); 1488 stk_scache_size += modport_map_scache_size; 1489 } 1490 #endif /* BCM_TRIDENT_SUPPORT */ 1491 1492 #if defined(BCM_TRX_SUPPORT) 1493 if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) { 1494 int modport_map_scache_size; 1495 BCM_IF_ERROR_RETURN( 1496 bcmi_trx_modport_map_scache_size_get(unit, SOC_MAX_NUM_PORTS, 1497 &modport_map_scache_size)); 1498 stk_scache_size += modport_map_scache_size; 1499 } 1500 #endif /* BCM_TRX_SUPPORT */ 1501 1502 /* Allocate space for the bcmSwitchFabricTrunkAutoIncludeDisable value */ 1503 stk_scache_size += sizeof(int); 1504 1505 #if defined(BCM_TRIDENT_SUPPORT) 1506 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 1507 int higig_trunk_override_hi_scache_size; 1508 BCM_IF_ERROR_RETURN 1509 (bcm_td_stk_trunk_override_hi_scache_size_get(unit, 1510 &higig_trunk_override_hi_scache_size)); 1511 stk_scache_size += higig_trunk_override_hi_scache_size; 1512 } 1513 #endif /* BCM_TRIDENT_SUPPORT */ 1514 1515 #if defined(BCM_TRIUMPH3_SUPPORT) 1516 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 1517 int modport_map_enable_size; 1518 BCM_IF_ERROR_RETURN( 1519 bcm_td_modport_map_enable_scache_size_get(unit, 1520 &modport_map_enable_size)); 1521 stk_scache_size += modport_map_enable_size; 1522 } 1523 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */ 1524 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 1525 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 1526 /* Version_1_5 -> Version_1_6: 1527 * Allocate space for hi 8bits of src_modid_base_index_bk[unit]->num_ports array */ 1528 stk_scache_size += (sizeof(uint8) * (SOC_MODID_MAX(unit) + 1)); 1529 } 1530 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 1531 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 1532 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 1533 int linkflap_trunk_map_size; 1534 BCM_IF_ERROR_RETURN( 1535 bcm_td_linkflap_trunk_map_scache_size_get(unit, 1536 &linkflap_trunk_map_size)); 1537 stk_scache_size += linkflap_trunk_map_size; 1538 } 1539 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */ 1540 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1541 /* Version_1_8 -> Version_1_9: 1542 * module_id_type_list & multi_nexthop_module_id_list are introduced by Version_1_9 1543 * Allocate space for src_modid_base_index_bk[unit]->module_id_type_list and 1544 * src_modid_base_index_bk[unit]->multi_nexthop_module_id_list. */ 1545 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 1546 stk_scache_size += (sizeof(int) * (SOC_MODID_MAX(unit) + 1)) * 2; 1547 } 1548 #endif 1549 1550 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_STACK, 0); 1551 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 1552 (0 == SOC_WARM_BOOT(unit)), 1553 stk_scache_size, &stk_scache_ptr, 1554 BCM_WB_DEFAULT_VERSION, NULL); 1555 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1556 return rv; 1557 } 1558 #endif /* BCM_WARM_BOOT_SUPPORT */ 1559 rv = _bcm_esw_stk_init_prepare(unit); 1560 BCM_IF_ERROR_RETURN(rv); 1561 1562 if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) { 1563 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 1564 SOC_IF_ERROR_RETURN 1565 (soc_mem_clear(unit, MODPORT_MAP_SWm, MEM_BLOCK_ALL, 0)); 1566 SOC_IF_ERROR_RETURN 1567 (soc_mem_clear(unit, MODPORT_MAP_MIRRORm, MEM_BLOCK_ALL, 0)); 1568 } else if (SOC_IS_TR_VL(unit) && SOC_MEM_IS_VALID(unit, MODPORT_MAPm)) { 1569 SOC_IF_ERROR_RETURN 1570 (soc_mem_clear(unit, MODPORT_MAPm, MEM_BLOCK_ALL, 0)); 1571 } else { 1572 BCM_IF_ERROR_RETURN(bcm_esw_stk_modport_clear_all(unit)); 1573 } 1574 } 1575 1576 rv = _bcm_esw_stk_init(); 1577 if (BCM_FAILURE(rv)) { 1578 _bcm_esw_stk_detach(unit); 1579 return (rv); 1580 } 1581 1582 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 1583 if (soc_feature(unit, soc_feature_epc_linkflap_recover)) { 1584 bcm_port_t p; 1585 PBMP_PORT_ITER(unit, p) { 1586 _BCM_PORT_TRUNK_LINKFLAP_CLEAR(unit, p); 1587 } 1588 BCM_IF_ERROR_RETURN( 1589 bcm_esw_linkscan_register(unit, _bcm_stk_modport_map_linkscan_handler)); 1590 } 1591 #endif 1592 1593 SOC_DEFAULT_DMA_SRCPORT_SET(unit, CMIC_PORT(unit)); 1594 1595 if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) { 1596 /* Blank slate for stack info */ 1597 BCM_PBMP_CLEAR(SOC_PBMP_STACK_CURRENT(unit)); 1598 BCM_PBMP_CLEAR(SOC_PBMP_STACK_INACTIVE(unit)); 1599 BCM_PBMP_CLEAR(SOC_PBMP_STACK_PREVIOUS(unit)); 1600 1601 switch (BCM_CHIP_FAMILY(unit)) { 1602 1603 case BCM_FAMILY_HERCULES: 1604 rv = _bcm_xgs_fabric_stk_init(unit); 1605 break; 1606 case BCM_FAMILY_HUMV: 1607 case BCM_FAMILY_CONQUEROR: 1608 case BCM_FAMILY_TITAN: 1609 rv = _bcm_xgs3_ignore_my_modid(unit); 1610 if (BCM_FAILURE(rv)) { 1611 break; 1612 } 1613 /* fall through */ 1614 case BCM_FAMILY_BRADLEY: 1615 case BCM_FAMILY_FIREBOLT: 1616 case BCM_FAMILY_TRIUMPH: 1617 case BCM_FAMILY_SCORPION: 1618 case BCM_FAMILY_TRIUMPH2: 1619 case BCM_FAMILY_TRIDENT: 1620 case BCM_FAMILY_KATANA: 1621 rv = _bcm_xgs3_stk_init(unit); 1622 break; 1623 default: 1624 rv = BCM_E_UNAVAIL; 1625 break; 1626 1627 } 1628 1629 if (BCM_FAILURE(rv)) { 1630 _bcm_esw_stk_detach(unit); 1631 return (rv); 1632 } 1633 } 1634 1635 #ifdef BCM_WARM_BOOT_SUPPORT 1636 if (SOC_WARM_BOOT(unit)) { 1637 rv = _bcm_stk_reinit(unit); 1638 if (BCM_FAILURE(rv)) { 1639 _bcm_esw_stk_detach(unit); 1640 return (rv); 1641 } 1642 } 1643 #endif /* BCM_WARM_BOOT_SUPPORT */ 1644 1645 return rv; 1646 } 1647 1648 /**************************************************************** 1649 * 1650 * Per device stacking initialization 1651 * Clears stacking configuration 1652 */ 1653 1654 STATIC int 1655 _bcm_xgs_fabric_stk_init(int unit) 1656 { 1657 #if defined(BCM_HERCULES_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 1658 int port; 1659 1660 PBMP_HG_ITER(unit, port) { 1661 BCM_IF_ERROR_RETURN 1662 (bcm_esw_port_stp_set(unit, port, BCM_STG_STP_FORWARD)); 1663 } 1664 1665 #if defined(LOCAL_MODMAP_SUPPORT) 1666 if (soc_feature(unit, soc_feature_modmap)) { 1667 BCM_IF_ERROR_RETURN(_bcm_esw_modmap_init(unit)); 1668 } 1669 #endif /* MODMAP_SUPPORT */ 1670 #endif 1671 1672 return BCM_E_NONE; 1673 } 1674 1675 1676 STATIC int 1677 _bcm_xgs3_ignore_my_modid(int unit) 1678 { 1679 int rv = BCM_E_UNAVAIL; 1680 #if defined(BCM_BRADLEY_SUPPORT) 1681 #if defined(BCM_SCORPION_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 1682 if (SOC_IS_SC_CQ(unit) || SOC_IS_TD_TT(unit)) { 1683 uint64 config, oconfig; 1684 1685 SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, &config)); 1686 oconfig = config; 1687 soc_reg64_field32_set(unit, ING_CONFIG_64r, &config, 1688 IGNORE_MY_MODIDf, 1); 1689 if (COMPILER_64_NE(config, oconfig)) { 1690 SOC_IF_ERROR_RETURN(WRITE_ING_CONFIG_64r(unit, config)); 1691 } 1692 1693 rv = BCM_E_NONE; 1694 } else 1695 #endif 1696 { 1697 uint32 config, oconfig; 1698 1699 SOC_IF_ERROR_RETURN(READ_ING_CONFIGr(unit, &config)); 1700 oconfig = config; 1701 soc_reg_field_set(unit, ING_CONFIGr, &config, 1702 IGNORE_MY_MODIDf, 1); 1703 if (config != oconfig) { 1704 SOC_IF_ERROR_RETURN(WRITE_ING_CONFIGr(unit, config)); 1705 } 1706 1707 rv = BCM_E_NONE; 1708 } 1709 #endif 1710 return rv; 1711 } 1712 1713 STATIC int 1714 _bcm_xgs3_stk_init(int unit) 1715 { 1716 #if defined(BCM_XGS3_SWITCH_SUPPORT) 1717 int pbm_len; 1718 bcm_port_t port; 1719 uint32 cpu_pbm, obm_reg; 1720 uint64 obm_reg_64; 1721 soc_pbmp_t pbmp; 1722 1723 /* Set modid to 0 */ 1724 if (!SOC_WARM_BOOT(unit) && !SOC_IS_RCPU_ONLY(unit)) { 1725 BCM_IF_ERROR_RETURN(bcm_esw_stk_modid_set(unit, 0)); 1726 } 1727 1728 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) || 1729 SOC_IS_TRIUMPH3(unit)) { 1730 SOC_PBMP_CLEAR(pbmp); 1731 SOC_PBMP_PORT_SET(pbmp, CMIC_PORT(unit)); 1732 } else if (SOC_IS_TR_VL(unit) && !SOC_IS_TRIUMPH2(unit) 1733 && !SOC_IS_APOLLO(unit) && !SOC_IS_VALKYRIE2(unit)) { 1734 SOC_IF_ERROR_RETURN 1735 (soc_xgs3_port_to_higig_bitmap(unit, CMIC_PORT(unit), 1736 &cpu_pbm)); 1737 } else if (CMIC_PORT(unit)) { 1738 pbm_len = soc_reg_field_length(unit, ICONTROL_OPCODE_BITMAPr, BITMAPf); 1739 if (pbm_len >= 1) { 1740 cpu_pbm = 1 << (pbm_len - 1); 1741 } else { 1742 cpu_pbm = 1; 1743 } 1744 } else { 1745 cpu_pbm = 1; 1746 } 1747 1748 PBMP_ST_ITER(unit, port) { 1749 /* HG ports to forwarding */ 1750 BCM_IF_ERROR_RETURN(bcm_esw_port_stp_set(unit, port, 1751 BCM_STG_STP_FORWARD)); 1752 1753 /* Set HG ingress CPU Opcode map to the CPU */ 1754 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) || 1755 SOC_IS_TRIUMPH3(unit)) { 1756 icontrol_opcode_bitmap_entry_t entry; 1757 SOC_IF_ERROR_RETURN 1758 (READ_ICONTROL_OPCODE_BITMAPm(unit, MEM_BLOCK_ANY, port, 1759 &entry)); 1760 soc_mem_pbmp_field_set(unit, ICONTROL_OPCODE_BITMAPm, &entry, 1761 BITMAPf, &pbmp); 1762 SOC_IF_ERROR_RETURN 1763 (WRITE_ICONTROL_OPCODE_BITMAPm(unit, MEM_BLOCK_ANY, port, 1764 &entry)); 1765 } else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1766 SOC_IS_VALKYRIE2(unit)) { 1767 uint64 cpu_pbm_64; 1768 COMPILER_64_ZERO(cpu_pbm_64); 1769 COMPILER_64_SET(cpu_pbm_64, 0, cpu_pbm); 1770 SOC_IF_ERROR_RETURN(READ_ICONTROL_OPCODE_BITMAP_64r(unit, port, 1771 &obm_reg_64)); 1772 soc_reg64_field_set(unit, ICONTROL_OPCODE_BITMAP_64r, &obm_reg_64, 1773 BITMAPf, cpu_pbm_64); 1774 SOC_IF_ERROR_RETURN(WRITE_ICONTROL_OPCODE_BITMAP_64r(unit, port, 1775 obm_reg_64)); 1776 } else if (SOC_IS_GREYHOUND2(unit)) { 1777 uint64 cpu_pbm_64; 1778 COMPILER_64_ZERO(cpu_pbm_64); 1779 COMPILER_64_SET(cpu_pbm_64, 0, cpu_pbm); 1780 SOC_IF_ERROR_RETURN(READ_ICONTROL_OPCODE_BITMAP_LOr(unit, port, 1781 &obm_reg_64)); 1782 soc_reg64_field_set(unit, ICONTROL_OPCODE_BITMAP_LOr, &obm_reg_64, 1783 BITMAPf, cpu_pbm_64); 1784 SOC_IF_ERROR_RETURN(WRITE_ICONTROL_OPCODE_BITMAP_LOr(unit, port, 1785 obm_reg_64)); 1786 #ifdef BCM_SHADOW_SUPPORT 1787 } else if (SOC_IS_SHADOW(unit)) { 1788 SOC_IF_ERROR_RETURN(READ_ICONTROL_OPCODEr(unit, port, &obm_reg)); 1789 soc_reg_field_set(unit, ICONTROL_OPCODEr, &obm_reg, PORT_NUMf, 0); 1790 SOC_IF_ERROR_RETURN(WRITE_ICONTROL_OPCODEr(unit, port, obm_reg)); 1791 #endif 1792 } else { 1793 SOC_IF_ERROR_RETURN(READ_ICONTROL_OPCODE_BITMAPr(unit, port, 1794 &obm_reg)); 1795 soc_reg_field_set(unit, ICONTROL_OPCODE_BITMAPr, &obm_reg, 1796 BITMAPf, cpu_pbm); 1797 SOC_IF_ERROR_RETURN(WRITE_ICONTROL_OPCODE_BITMAPr(unit, port, 1798 obm_reg)); 1799 } 1800 } 1801 #if defined(LOCAL_MODMAP_SUPPORT) 1802 if (soc_feature(unit, soc_feature_modmap)) { 1803 SOC_IF_ERROR_RETURN(_bcm_esw_modmap_init(unit)); 1804 } 1805 #endif 1806 1807 #ifdef BCM_TRIDENT_SUPPORT 1808 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 1809 BCM_IF_ERROR_RETURN(bcm_td_modport_map_init(unit)); 1810 } 1811 #endif 1812 1813 #ifdef BCM_TRX_SUPPORT 1814 if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) { 1815 BCM_IF_ERROR_RETURN(bcmi_trx_modport_map_init(unit)); 1816 } 1817 #endif /* BCM_TRX_SUPPORT */ 1818 1819 #ifdef BCM_TRIUMPH3_SUPPORT 1820 /* Setting ESM eligibility is done here because 1821 * the ESM offset and priority fields are located 1822 * in SOURCE_TRUNK_MAP table, and the index to the 1823 * SOURCE_TRUNK_MAP table can be computed only after 1824 * my_modid is set. 1825 */ 1826 if (soc_feature(unit, soc_feature_etu_support)) { 1827 pbmp_t esm_eligible_pbmp, default_pbmp; 1828 bcm_port_t esm_port; 1829 1830 BCM_PBMP_ASSIGN(default_pbmp, PBMP_E_ALL(unit)); 1831 esm_eligible_pbmp = soc_property_get_pbmp_default(unit, 1832 spn_PBMP_ESM_ELIGIBLE, default_pbmp); 1833 BCM_PBMP_ITER(esm_eligible_pbmp, esm_port) { 1834 BCM_IF_ERROR_RETURN(bcm_esw_port_control_set(unit, 1835 esm_port, bcmPortControlEsmEligibility, TRUE)); 1836 } 1837 } 1838 #endif /* BCM_TRIUMPH3_SUPPORT */ 1839 1840 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1841 if ((SOC_IS_TD2P_TT2P(unit) || SOC_IS_TRIDENT3X(unit) || SOC_IS_APACHE(unit)) && 1842 soc_feature(unit, soc_feature_src_modid_base_index)) { 1843 /* If the default base index and local modid's base index is 1844 * different then replicate the configuration of local MODID's 1845 * base index to default base index. This is needed as the 1846 * corresponding entries in the src_mod_port_mems has to be 1847 * configured to some default correct working values. At this 1848 * point in code, all configuration for local MODID has been 1849 * done and instead of creating another set of default values 1850 * we can just use the local MODID's configuration to beginwith. 1851 */ 1852 int i; 1853 int rv; 1854 int entry_size; 1855 void *entry_buffer; 1856 int src_base_index; 1857 int local_modid = SOC_BASE_MODID(unit); 1858 int entry_cnt = BCM_STK_TD2P_NUM_LPORTS; 1859 source_trunk_map_modbase_entry_t stm_modbase_entry; 1860 int dst_base_index = src_modid_base_index_bk[unit]->default_base_idx; 1861 1862 if (SOC_MODID_ADDRESSABLE(unit, local_modid)) { 1863 /* Retrieve the local MODID's base index from memory */ 1864 SOC_IF_ERROR_RETURN( 1865 READ_SOURCE_TRUNK_MAP_MODBASEm( 1866 unit, MEM_BLOCK_ANY, local_modid, &stm_modbase_entry)); 1867 1868 src_base_index = 1869 soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get( 1870 unit, &stm_modbase_entry, BASEf); 1871 } else { 1872 /* If local MODID is not accessible use base index 0 */ 1873 src_base_index = 0; 1874 } 1875 #if defined(BCM_APACHE_SUPPORT) 1876 if (SOC_IS_APACHE(unit)) { 1877 entry_cnt = BCM_STK_APACHE_NUM_LPORTS; 1878 } 1879 #endif 1880 #if defined(BCM_MONTEREY_SUPPORT) 1881 if (SOC_IS_MONTEREY(unit)) { 1882 entry_cnt = BCM_STK_MONTEREY_NUM_LPORTS; 1883 } 1884 #endif 1885 #if defined(BCM_TRIDENT3_SUPPORT) 1886 if (SOC_IS_TRIDENT3X(unit)) { 1887 if (SOC_IS_TRIDENT3(unit)) { 1888 entry_cnt = TRIDENT3_DEV_PORTS_PER_DEV; 1889 } 1890 1891 #if defined(BCM_MAVERICK2_SUPPORT) 1892 if (SOC_IS_MAVERICK2(unit)) { 1893 entry_cnt = MAVERICK2_DEV_PORTS_PER_DEV; 1894 } 1895 #endif 1896 1897 #if defined(BCM_HELIX5_SUPPORT) 1898 if (SOC_IS_HELIX5(unit)) { 1899 entry_cnt = HELIX5_DEV_PORTS_PER_DEV; 1900 } 1901 #endif 1902 } 1903 #endif 1904 /* Only replicate if base index differ */ 1905 if (src_base_index != dst_base_index) { 1906 1907 for (i = 0; i < COUNTOF(src_mod_port_mems); i++) { 1908 if(!soc_mem_is_valid(unit, src_mod_port_mems[i])) { 1909 continue; 1910 } 1911 /* Get a buffer to hold the data worth of mutliple entries */ 1912 entry_size = 1913 WORDS2BYTES(soc_mem_entry_words(unit, src_mod_port_mems[i])); 1914 entry_buffer = soc_cm_salloc(unit, 1915 (entry_size * entry_cnt), "mod table entry block"); 1916 if (!entry_buffer) { 1917 return BCM_E_MEMORY; 1918 } 1919 1920 /* Clear the buffer to begin-with */ 1921 sal_memset(entry_buffer, 0x0, entry_size * entry_cnt); 1922 1923 /* Read the entire range of entries starting from local MODID's 1924 * base index till the number of ports supported in one shot 1925 */ 1926 rv = soc_mem_read_range(unit, 1927 src_mod_port_mems[i], 1928 MEM_BLOCK_ANY, 1929 src_base_index, 1930 src_base_index + entry_cnt - 1, 1931 entry_buffer); 1932 1933 /* Write the entire range at default base index at once */ 1934 if (BCM_SUCCESS(rv)) { 1935 rv = soc_mem_write_range(unit, 1936 src_mod_port_mems[i], 1937 MEM_BLOCK_ANY, 1938 dst_base_index, 1939 dst_base_index + entry_cnt - 1, 1940 entry_buffer); 1941 } 1942 1943 /* Deallocate the buffer as it is not needed now */ 1944 soc_cm_sfree(unit, entry_buffer); 1945 1946 /* Bail out on error */ 1947 SOC_IF_ERROR_RETURN(rv); 1948 } 1949 } 1950 } 1951 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 1952 1953 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1954 1955 return BCM_E_NONE; 1956 } 1957 1958 /**************************************************************** 1959 * 1960 * Stack port set calls: 1961 * 1962 * Callback into BCM layer for notification 1963 * Callback to application for notification 1964 */ 1965 1966 1967 /* Linked list of callback registrants */ 1968 typedef struct _esw_stk_callback_s { 1969 struct _esw_stk_callback_s *next; 1970 bcm_stk_cb_f fn; 1971 void *cookie; 1972 } _esw_stk_callback_t; 1973 1974 /* 1975 * Function: 1976 * bcm_esw_stk_update_callback_register/unregister 1977 * Purpose: 1978 * (Un)register an application function for calbacks from stack port set 1979 * Parameters: 1980 * unit - ignored 1981 * cb - callback function 1982 * cookie - anonymous data passed to callback 1983 * Returns: 1984 * BCM_E_XXX 1985 * Notes: 1986 * Will only register a given (callback, cookie) pair once. 1987 * On unregister, both the callback and cookie must match. 1988 * Callbacks are made in the order they are registered. Enqueue 1989 * new registrants at the end of the linked list. 1990 */ 1991 1992 static _esw_stk_callback_t *_esw_stk_cb; 1993 static _esw_stk_callback_t *_esw_stk_cb_tail; 1994 1995 /* Register stack update callback at end of list */ 1996 1997 int 1998 bcm_esw_stk_update_callback_register(int unit, bcm_stk_cb_f cb, void *cookie) 1999 { 2000 _esw_stk_callback_t *node; 2001 int rv = BCM_E_NONE; 2002 2003 COMPILER_REFERENCE(unit); 2004 2005 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 2006 2007 BCM_IF_ERROR_RETURN(_bcm_esw_stk_init()); 2008 2009 ESW_STK_LOCK; 2010 /* See if already present */ 2011 node = _esw_stk_cb; 2012 while (node != NULL) { 2013 if (node->fn == cb && node->cookie == cookie) { 2014 break; /* Found it */ 2015 } 2016 node = node->next; 2017 } 2018 2019 if (node == NULL) { /* Not there yet */ 2020 node = sal_alloc(sizeof(*node), "bcm_esw_stk_cb"); 2021 if (node != NULL) { 2022 node->fn = cb; 2023 node->cookie = cookie; 2024 node->next = NULL; 2025 2026 /* Enqueue at tail */ 2027 if (_esw_stk_cb_tail == NULL) { 2028 _esw_stk_cb = node; 2029 } else { 2030 _esw_stk_cb_tail->next = node; 2031 } 2032 _esw_stk_cb_tail = node; 2033 } else { 2034 rv = BCM_E_MEMORY; 2035 } 2036 } 2037 ESW_STK_UNLOCK; 2038 2039 return rv; 2040 } 2041 2042 int 2043 bcm_esw_stk_update_callback_unregister(int unit, bcm_stk_cb_f cb, void *cookie) 2044 { 2045 _esw_stk_callback_t *node; 2046 _esw_stk_callback_t *prev; 2047 int rv; 2048 2049 COMPILER_REFERENCE(unit); 2050 2051 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 2052 2053 BCM_IF_ERROR_RETURN(_bcm_esw_stk_init()); 2054 2055 ESW_STK_LOCK; 2056 node = _esw_stk_cb; 2057 prev = NULL; 2058 2059 /* Scan list for match of both function and cookie */ 2060 while (node != NULL) { 2061 if ((node->fn == cb) && (node->cookie == cookie)) { 2062 break; /* Found it */ 2063 } 2064 prev = node; 2065 node = node->next; 2066 } 2067 2068 if (node != NULL) { /* Found */ 2069 if (prev == NULL) { /* First on list */ 2070 _esw_stk_cb = node->next; 2071 } else { /* Update previous */ 2072 prev->next = node->next; 2073 } 2074 if (_esw_stk_cb_tail == node) { /* Was last on list */ 2075 _esw_stk_cb_tail = prev; 2076 } 2077 rv = BCM_E_NONE; 2078 } else { 2079 rv = BCM_E_NOT_FOUND; 2080 } 2081 ESW_STK_UNLOCK; 2082 2083 if (node != NULL) { 2084 sal_free(node); 2085 } 2086 2087 return (rv); 2088 } 2089 2090 /* 2091 * Force stack ports into ptable tagged bitmap and out of untagged bitmap 2092 * Note that if a device has no ethernet ports, this will just return. 2093 */ 2094 STATIC int 2095 _bcm_stk_ptable_update(int unit) 2096 { 2097 bcm_port_cfg_t pcfg; 2098 int port; 2099 bcm_pbmp_t old_pbm, old_upbm; 2100 2101 PBMP_E_ITER(unit, port) { 2102 SOC_IF_ERROR_RETURN( 2103 mbcm_driver[unit]->mbcm_port_cfg_get(unit, port, &pcfg)); 2104 SOC_PBMP_ASSIGN(old_pbm, pcfg.pc_pbm); 2105 SOC_PBMP_ASSIGN(old_upbm, pcfg.pc_ut_pbm); 2106 SOC_PBMP_OR(pcfg.pc_pbm, SOC_PBMP_STACK_CURRENT(unit)); 2107 SOC_PBMP_REMOVE(pcfg.pc_ut_pbm, SOC_PBMP_STACK_CURRENT(unit)); 2108 2109 if (SOC_PBMP_NEQ(old_pbm, pcfg.pc_pbm) || 2110 SOC_PBMP_NEQ(old_upbm, pcfg.pc_ut_pbm)) { 2111 SOC_IF_ERROR_RETURN( 2112 mbcm_driver[unit]->mbcm_port_cfg_set(unit, port, &pcfg)); 2113 } 2114 } 2115 2116 return BCM_E_NONE; 2117 } 2118 2119 STATIC int 2120 _esw_stk_update_callbacks(int unit, 2121 bcm_port_t port, 2122 uint32 flags, 2123 int inactiveChkReqd) 2124 { 2125 _esw_stk_callback_t *node; 2126 2127 /* Internal port-table update (for untagged port setting */ 2128 BCM_IF_ERROR_RETURN(_bcm_stk_ptable_update(unit)); 2129 2130 if ( (SOC_PBMP_NEQ(SOC_PBMP_STACK_CURRENT(unit), 2131 SOC_PBMP_STACK_PREVIOUS(unit))) || inactiveChkReqd ) { 2132 /* Make internal callbacks if stack ports have changed */ 2133 BCM_IF_ERROR_RETURN(_bcm_esw_vlan_stk_update(unit, flags)); 2134 BCM_IF_ERROR_RETURN(_bcm_esw_mcast_stk_update(unit, flags)); 2135 BCM_IF_ERROR_RETURN(_bcm_esw_ipmc_stk_update(unit, flags)); 2136 } 2137 2138 /* Make registered callbacks. Assumes lock is held by caller. */ 2139 node = _esw_stk_cb; 2140 while (node != NULL) { 2141 (node->fn)(unit, port, flags, node->cookie); 2142 node = node->next; 2143 } 2144 2145 return BCM_E_NONE; 2146 } 2147 2148 /* 2149 * Function: 2150 * bcm_esw_stk_port_set 2151 * Purpose: 2152 * Set stacking mode for a port 2153 * Parameters: 2154 * unit BCM device number 2155 * port BCM port number on device 2156 * flags See bcm/stack.h 2157 * Returns: 2158 * BCM_E_XXX 2159 * Notes: 2160 * If neither simplex or duplex is specified, port should be 2161 * considered "unresolved"; for example, if discovery has not 2162 * completed yet. In general, this should not change a port's 2163 * settings, but it may affect the port's setup. 2164 * 2165 * If port < 0, use the unique IPIC_PORT if present 2166 * 2167 * If flags == 0, then the port does not have to be a stack port. 2168 */ 2169 2170 int 2171 bcm_esw_stk_port_set(int unit, bcm_port_t port, uint32 flags) 2172 { 2173 int rv = BCM_E_NONE; 2174 int txp, rxp; 2175 2176 if ((!SOC_UNIT_VALID(unit)) || (!BCM_IS_LOCAL(unit))) { 2177 LOG_WARN(BSL_LS_BCM_STK, 2178 (BSL_META_U(unit, 2179 "STK: %s unit %d\n"), 2180 SOC_UNIT_VALID(unit)?"Invalid":"Remote", unit)); 2181 return BCM_E_UNIT; 2182 } 2183 2184 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 2185 2186 LOG_VERBOSE(BSL_LS_BCM_STK, 2187 (BSL_META_U(unit, 2188 "STK %d: Port set: p %d. flags 0x%x\n"), 2189 unit, port, flags)); 2190 2191 if (BCM_GPORT_INVALID == port) { 2192 port = IPIC_PORT(unit); 2193 } else if (BCM_GPORT_IS_SET(port)) { 2194 BCM_IF_ERROR_RETURN( 2195 bcm_esw_port_local_get(unit, port, &port)); 2196 } 2197 2198 if (!IS_PORT(unit, port)) { 2199 LOG_WARN(BSL_LS_BCM_STK, 2200 (BSL_META_U(unit, 2201 "STK: invalid port (%d,%d)\n"), 2202 unit, port)); 2203 return BCM_E_PARAM; 2204 } 2205 2206 rv = _bcm_esw_stk_init(); 2207 if (BCM_FAILURE(rv)) { 2208 LOG_WARN(BSL_LS_BCM_STK, 2209 (BSL_META_U(unit, 2210 "STK: init failure (%d)\n"), 2211 rv)); 2212 return rv; 2213 } 2214 2215 if (flags & (BCM_STK_ENABLE | BCM_STK_CAPABLE)) { 2216 if (!IS_ST_PORT(unit, port)) { 2217 2218 /* Setting a non-HG port to stacking implies SL mode */ 2219 if ((flags & BCM_STK_HG) || !IS_GE_PORT(unit, port)) { 2220 LOG_WARN(BSL_LS_BCM_STK, 2221 (BSL_META_U(unit, 2222 "STK: Invalid SL stk cfg. unit %d, port %d\n"), 2223 unit, port)); 2224 return BCM_E_PARAM; 2225 } 2226 flags |= BCM_STK_SL; /* Set courtesy flag for callbacks */ 2227 2228 /* Turn pause off on SL stack ports */ 2229 rv = bcm_esw_port_pause_get(unit, port, &txp, &rxp); 2230 if (BCM_FAILURE(rv)) { 2231 LOG_WARN(BSL_LS_BCM_STK, 2232 (BSL_META_U(unit, 2233 "STK: bcm_port_pause_get failure (%d)\n"), 2234 rv)); 2235 return rv; 2236 } 2237 2238 if ((txp != 0) || (rxp != 0)) { 2239 rv = bcm_esw_port_pause_set(unit, port, 0, 0); 2240 if (BCM_FAILURE(rv)) { 2241 LOG_WARN(BSL_LS_BCM_STK, 2242 (BSL_META_U(unit, 2243 "STK: bcm_port_pause_set failure (%d)\n"), 2244 rv)); 2245 return rv; 2246 } 2247 } 2248 } else { /* HG port/HG2 over GE port */ 2249 if (flags & BCM_STK_SL) { 2250 LOG_WARN(BSL_LS_BCM_STK, 2251 (BSL_META_U(unit, 2252 "STK: Invalid HG stk cfg. unit %d, port %d\n"), 2253 unit, port)); 2254 return BCM_E_PARAM; 2255 } 2256 flags |= BCM_STK_HG; /* Set courtesy flag for callbacks */ 2257 } 2258 2259 if ((flags & BCM_STK_SIMPLEX) && (flags & BCM_STK_DUPLEX)) { 2260 LOG_WARN(BSL_LS_BCM_STK, 2261 (BSL_META_U(unit, 2262 "STK: Dimplex not supported. unit %d, port %d\n"), 2263 unit, port)); 2264 return BCM_E_PARAM; 2265 } 2266 } 2267 2268 if ((flags & BCM_STK_CUT) && (flags & BCM_STK_SL)) { 2269 flags |= BCM_STK_INACTIVE; 2270 } 2271 2272 ESW_STK_LOCK; 2273 rv = _esw_stk_port_set(unit, port, flags); 2274 ESW_STK_UNLOCK; 2275 2276 #ifdef BCM_WARM_BOOT_SUPPORT 2277 SOC_CONTROL_LOCK(unit); 2278 SOC_CONTROL(unit)->scache_dirty = 1; 2279 SOC_CONTROL_UNLOCK(unit); 2280 #endif 2281 2282 return rv; 2283 } 2284 2285 /* 2286 * Function: 2287 * bcm_esw_stk_pbmp_get 2288 * Purpose: 2289 * Expose the current enabled and inactive ports 2290 * Parameters: 2291 * 2292 * Returns: 2293 * BCM_E_XXX 2294 * Notes: 2295 */ 2296 2297 int 2298 bcm_esw_stk_pbmp_get(int unit, bcm_pbmp_t *cur_pbm, 2299 bcm_pbmp_t *inactive_pbm) 2300 { 2301 if ((!SOC_UNIT_VALID(unit)) || (!BCM_IS_LOCAL(unit))) { 2302 return BCM_E_UNIT; 2303 } 2304 2305 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 2306 2307 if (cur_pbm != NULL) { 2308 BCM_PBMP_ASSIGN(*cur_pbm, SOC_PBMP_STACK_CURRENT(unit)); 2309 } 2310 2311 if (inactive_pbm != NULL) { 2312 BCM_PBMP_ASSIGN(*inactive_pbm, SOC_PBMP_STACK_INACTIVE(unit)); 2313 } 2314 2315 return BCM_E_NONE; 2316 } 2317 2318 2319 /* 2320 * Function: 2321 * bcm_esw_stk_mode_get 2322 * Purpose: 2323 * Returns current stack mode 2324 * Parameters: 2325 * unit BCM device number 2326 * flags (OUT) Indication of stack mode 2327 * Returns: 2328 * BCM_E_XXX 2329 * Notes: 2330 * Currently should only return one bit set, but that may 2331 * change in the future. SL has precedence; if that mode is 2332 * active on the device, that's what gets returned. Then, if 2333 * the device has any HG ports, HG mode is returned. Then 2334 * "NONE" is returned. Note that some bit will always be set; 2335 * that is, the routine will not return 0. 2336 */ 2337 2338 int 2339 bcm_esw_stk_mode_get(int unit, uint32 *flags) 2340 { 2341 if ((!SOC_UNIT_VALID(unit)) || (!BCM_IS_LOCAL(unit))) { 2342 return BCM_E_UNIT; 2343 } 2344 2345 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 2346 2347 if (SOC_SL_MODE(unit)) { 2348 *flags = BCM_STK_SL; 2349 } else if (BCM_PBMP_NOT_NULL(PBMP_ST_ALL(unit))) { 2350 /* HG/HG2 stacking */ 2351 *flags = BCM_STK_HG; 2352 } else { 2353 *flags = BCM_STK_NONE; 2354 } 2355 2356 return BCM_E_NONE; 2357 } 2358 2359 /* 2360 * Function: 2361 * bcm_esw_stk_mode_set 2362 * Purpose: 2363 * Set the current stack mode 2364 * Parameters: 2365 * unit BCM device number 2366 * flags Indication of stack mode 2367 * Returns: 2368 * BCM_E_XXX 2369 * Notes: 2370 * The main use of this is to put a chip supporting SL 2371 * stacking into SL mode before other things are started. 2372 * 2373 * Only BCM_STK_SL, BCM_STK_HG and BCM_STK_NONE are checked. 2374 * 2375 * Currently only turning on SL stacking is supported. 2376 */ 2377 2378 int 2379 bcm_esw_stk_mode_set(int unit, uint32 flags) 2380 { 2381 if ((!SOC_UNIT_VALID(unit)) || (!BCM_IS_LOCAL(unit))) { 2382 return BCM_E_UNIT; 2383 } 2384 2385 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 2386 2387 LOG_VERBOSE(BSL_LS_BCM_STK, 2388 (BSL_META_U(unit, 2389 "STK %d: Mode set: flags 0x%x\n"), 2390 unit, flags)); 2391 2392 if (flags & BCM_STK_SL) { 2393 return BCM_E_UNAVAIL; 2394 } 2395 2396 if (flags & BCM_STK_NONE) { 2397 if (SOC_SL_MODE(unit)) { 2398 return BCM_E_UNAVAIL; /* Not currently supported */ 2399 } 2400 return BCM_E_NONE; 2401 } 2402 2403 return BCM_E_NONE; 2404 } 2405 2406 /* 2407 * Function: 2408 * bcm_esw_stk_port_get 2409 * Purpose: 2410 * Get stack port mode information 2411 * Parameters: 2412 * unit BCM device number 2413 * port BCM port number on device 2414 * flags (OUT) flags related to stacking 2415 * Returns: 2416 * BCM_E_XXX 2417 * Notes: 2418 */ 2419 2420 int 2421 bcm_esw_stk_port_get(int unit, bcm_port_t port, uint32 *flags) 2422 { 2423 *flags = 0; 2424 2425 if ((!SOC_UNIT_VALID(unit)) || (!BCM_IS_LOCAL(unit))) { 2426 return BCM_E_UNIT; 2427 } 2428 2429 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 2430 2431 if (BCM_GPORT_INVALID == port) { /* BCM_STK_USE_HG_IF */ 2432 port = IPIC_PORT(unit); 2433 } else if (BCM_GPORT_IS_SET(port)) { 2434 BCM_IF_ERROR_RETURN( 2435 bcm_esw_port_local_get(unit, port, &port)); 2436 } 2437 2438 if (!IS_PORT(unit, port)) { 2439 return BCM_E_PARAM; 2440 } 2441 2442 if (BCM_PBMP_MEMBER(SOC_PBMP_STACK_CURRENT(unit), port)) { 2443 *flags |= BCM_STK_ENABLE; 2444 if (BCM_PBMP_MEMBER(SOC_PBMP_STACK_INACTIVE(unit), port)) { 2445 *flags |= BCM_STK_INACTIVE; 2446 } 2447 if (IS_ST_PORT(unit, port)) { 2448 *flags |= BCM_STK_HG; 2449 } else { 2450 *flags |= BCM_STK_SL; 2451 } 2452 } else { 2453 *flags |= BCM_STK_NONE; 2454 } 2455 2456 return BCM_E_NONE; 2457 } 2458 2459 /**************************************************************** 2460 * The ugly details of adding stack ports 2461 */ 2462 2463 STATIC int 2464 _xgs3_stk_port_set(int unit, bcm_port_t port, uint32 flags) 2465 { 2466 if (SOC_IS_XGS3_SWITCH(unit)) { 2467 #if defined(BCM_XGS3_SWITCH_SUPPORT) 2468 if (IS_ST_PORT(unit, port) || flags == 0) { 2469 /* Only stack ports may be set (flags != 0), but any port 2470 may be unset (flags == 0) */ 2471 return BCM_E_NONE; 2472 } 2473 #endif 2474 } 2475 2476 return BCM_E_UNAVAIL; 2477 } 2478 2479 2480 STATIC int 2481 _esw_soc_stk_port_set(int unit, bcm_port_t port, uint32 flags) 2482 { 2483 2484 /* SL, HG, simplex and duplex are determined per-device */ 2485 switch (BCM_CHIP_FAMILY(unit)) { 2486 case BCM_FAMILY_FIREBOLT: 2487 case BCM_FAMILY_BRADLEY: 2488 case BCM_FAMILY_HUMV: 2489 case BCM_FAMILY_TRIUMPH: 2490 case BCM_FAMILY_SCORPION: 2491 case BCM_FAMILY_CONQUEROR: 2492 case BCM_FAMILY_TRIUMPH2: 2493 case BCM_FAMILY_TITAN: 2494 case BCM_FAMILY_TRIDENT: 2495 case BCM_FAMILY_KATANA: 2496 return _xgs3_stk_port_set(unit, port, flags); 2497 2498 default: 2499 break; 2500 } 2501 2502 return BCM_E_NONE; 2503 } 2504 2505 2506 STATIC int 2507 _esw_stk_port_set(int unit, bcm_port_t port, uint32 flags) 2508 { 2509 int rv = BCM_E_NONE; 2510 int isPrevInactiveSet = 0; 2511 int inactiveChkReqd = 0; 2512 2513 /* Check if SL stacking should be enabled on the device */ 2514 if ((!SOC_SL_MODE(unit)) && (flags & BCM_STK_ENABLE) && 2515 (flags & BCM_STK_SL)) { 2516 return BCM_E_UNAVAIL; 2517 } 2518 2519 if (SOC_PBMP_MEMBER(SOC_PBMP_STACK_INACTIVE(unit), port)) 2520 isPrevInactiveSet = 1; 2521 2522 /* Program the port appropriately */ 2523 BCM_IF_ERROR_RETURN(_esw_soc_stk_port_set(unit, port, flags)); 2524 2525 /* Record old stack port states; make changes to current */ 2526 BCM_PBMP_ASSIGN(SOC_PBMP_STACK_PREVIOUS(unit), SOC_PBMP_STACK_CURRENT(unit)); 2527 2528 if (flags & BCM_STK_ENABLE) { 2529 SOC_PBMP_PORT_ADD(SOC_PBMP_STACK_CURRENT(unit), port); 2530 if (flags & BCM_STK_INACTIVE) { 2531 SOC_PBMP_PORT_ADD(SOC_PBMP_STACK_INACTIVE(unit), port); 2532 if (!isPrevInactiveSet) 2533 inactiveChkReqd = 1; 2534 } else { 2535 SOC_PBMP_PORT_REMOVE(SOC_PBMP_STACK_INACTIVE(unit), port); 2536 if (isPrevInactiveSet) 2537 inactiveChkReqd = 1; 2538 } 2539 } else { 2540 SOC_PBMP_PORT_REMOVE(SOC_PBMP_STACK_CURRENT(unit), port); 2541 SOC_PBMP_PORT_REMOVE(SOC_PBMP_STACK_INACTIVE(unit), port); 2542 } 2543 2544 /* Always make callbacks; callbacks are responsible for determining 2545 * whether or not anything needs to be done. 2546 */ 2547 rv = _esw_stk_update_callbacks(unit, port, flags, inactiveChkReqd); 2548 2549 return rv; 2550 } 2551 2552 /* 2553 * Function: 2554 * bcm_stk_modid_set 2555 * Purpose: 2556 * Set the module id of a unit 2557 * Parameters: 2558 * unit - device number 2559 * modid - module id 2560 * Returns: 2561 * BCM_E_XXX 2562 * Notes: 2563 * calls bcm_stk_modmap_map (my_modid_set does not) 2564 */ 2565 int 2566 bcm_esw_stk_modid_set(int unit, int modid) 2567 { 2568 bcm_module_t mod_out; 2569 bcm_port_t port_out; 2570 2571 BCM_IF_ERROR_RETURN 2572 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 2573 modid, -1, 2574 &mod_out, &port_out)); 2575 2576 LOG_INFO(BSL_LS_BCM_STK, 2577 (BSL_META_U(unit, 2578 "STK %d: modid set to %d; mapped %d\n"), 2579 unit, 2580 modid, mod_out)); 2581 return bcm_esw_stk_my_modid_set(unit, mod_out); 2582 } 2583 2584 /* 2585 * Function: 2586 * bcm_stk_modid_get 2587 * Purpose: 2588 * Get the module id of a unit 2589 * Parameters: 2590 * unit - device number 2591 * modid - module id 2592 * Returns: 2593 * BCM_E_XXX 2594 * Notes: 2595 * calls bcm_stk_modmap_map (my_modid_set does not) 2596 */ 2597 int 2598 bcm_esw_stk_modid_get(int unit, int *modid) 2599 { 2600 bcm_module_t mod_out; 2601 bcm_port_t port_out; 2602 2603 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, modid)); 2604 2605 BCM_IF_ERROR_RETURN 2606 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, 2607 *modid, -1, 2608 &mod_out, &port_out)); 2609 *modid = mod_out; 2610 return BCM_E_NONE; 2611 } 2612 2613 /* 2614 * Function: 2615 * bcm_stk_modid_count 2616 * Purpose: 2617 * The number of module identifiers (fabric IDs) needed by the unit 2618 * Parameters: 2619 * unit - SOC unit# 2620 * num_modid - (out)# of MODIDs 2621 * Returns: 2622 * BCM_E_XXX 2623 */ 2624 int 2625 bcm_esw_stk_modid_count(int unit, int *num_modid) 2626 { 2627 soc_control_t *soc = SOC_CONTROL(unit); 2628 2629 *num_modid = soc->info.modid_count; 2630 2631 return BCM_E_NONE; 2632 } 2633 2634 /* 2635 * Function: 2636 * _bcm_stk_my_modid_set 2637 * Purpose: 2638 * Sets the module-id in the Port block 2639 * Parameters: 2640 * unit - SOC unit# 2641 * port - port # 2642 * my_modid - the value to set 2643 * Returns: 2644 * BCM_E_XXX 2645 */ 2646 STATIC int 2647 _bcm_stk_my_modid_set(int unit, int port, int my_modid) 2648 { 2649 uint32 config; 2650 2651 if (SOC_USE_PORTCTRL(unit)) { 2652 return bcmi_esw_portctrl_stk_my_modid_set(unit, port, my_modid); 2653 } 2654 2655 #ifdef BCM_TRIDENT_SUPPORT 2656 if (IS_HG_PORT(unit, port) && IS_XL_PORT(unit, port) && 2657 SOC_IS_TD_TT(unit)) { 2658 /* The XLPORT_CONFIG.MY_MODID field is used to fill the module 2659 * ID field of E2ECC messages. In Trident, this field is 2660 * limited to 7 bits. 2661 */ 2662 BCM_IF_ERROR_RETURN 2663 (READ_XLPORT_CONFIGr(unit, port, &config)); 2664 if (my_modid < (1 << soc_reg_field_length(unit, 2665 XLPORT_CONFIGr, MY_MODIDf))) { 2666 soc_reg_field_set(unit, XLPORT_CONFIGr, &config, 2667 MY_MODIDf, my_modid); 2668 } else { 2669 soc_reg_field_set(unit, XLPORT_CONFIGr, &config, 2670 MY_MODIDf, 0); 2671 } 2672 BCM_IF_ERROR_RETURN 2673 (WRITE_XLPORT_CONFIGr(unit, port, config)); 2674 } else 2675 #endif /* BCM_TRIDENT_SUPPORT */ 2676 if ((IS_HG_PORT(unit, port) && 2677 !(SOC_IS_KATANAX(unit) || 2678 SOC_IS_TRIUMPH3(unit) || 2679 SOC_IS_HURRICANE2(unit) || 2680 SOC_IS_TD2_TT2(unit) || 2681 SOC_IS_GREYHOUND(unit) || 2682 SOC_IS_HURRICANE3(unit) || 2683 SOC_IS_GREYHOUND2(unit))) || 2684 (IS_HL_PORT(unit, port) && 2685 ((SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit))))) { 2686 2687 2688 BCM_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, port, &config)); 2689 soc_reg_field_set(unit, XPORT_CONFIGr, &config, 2690 MY_MODIDf, my_modid); 2691 BCM_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, config)); 2692 #if 0 2693 2694 if (SOC_REG_IS_VALID(unit, XPORT_CONFIGr)) { 2695 BCM_IF_ERROR_RETURN 2696 (READ_XPORT_CONFIGr(unit, port, &config)); 2697 soc_reg_field_set(unit, XPORT_CONFIGr, &config, 2698 MY_MODIDf, my_modid); 2699 BCM_IF_ERROR_RETURN 2700 (WRITE_XPORT_CONFIGr(unit, port, config)); 2701 } else if (SOC_REG_IS_VALID(unit, XLPORT_CONFIGr)) { 2702 BCM_IF_ERROR_RETURN 2703 (READ_XLPORT_CONFIGr(unit, port, &config)); 2704 soc_reg_field_set(unit, XLPORT_CONFIGr, &config, 2705 MY_MODIDf, my_modid); 2706 BCM_IF_ERROR_RETURN 2707 (WRITE_XLPORT_CONFIGr(unit, port, config)); 2708 } 2709 #endif 2710 } 2711 2712 return BCM_E_NONE; 2713 } 2714 2715 /* 2716 * Function: 2717 * bcm_stk_my_modid_set 2718 * Purpose: 2719 * Set the MY_MODID field 2720 * Parameters: 2721 * unit - SOC unit# 2722 * my_modid - the value to set 2723 * Returns: 2724 * BCM_E_XXX 2725 */ 2726 int 2727 bcm_esw_stk_my_modid_set(int unit, int my_modid) 2728 { 2729 soc_mem_t port_tab = PORT_TABm; 2730 2731 LOG_VERBOSE(BSL_LS_BCM_STK, 2732 (BSL_META_U(unit, 2733 "STK %d: Set my modid %d\n"), 2734 unit, my_modid)); 2735 2736 if ((BCM_MODID_INVALID != my_modid) && !SOC_MODID_ADDRESSABLE(unit, my_modid)) { 2737 return BCM_E_BADID; 2738 } 2739 2740 if (BCM_MODID_INVALID != my_modid) { 2741 SOC_DEFAULT_DMA_SRCMOD_SET(unit, my_modid); 2742 } 2743 2744 if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) { 2745 port_tab = ING_DEVICE_PORTm; 2746 } 2747 2748 switch (BCM_CHIP_FAMILY(unit)) { 2749 2750 #if defined(BCM_FIREBOLT_SUPPORT) 2751 case BCM_FAMILY_FIREBOLT: 2752 case BCM_FAMILY_BRADLEY: 2753 case BCM_FAMILY_HUMV: 2754 case BCM_FAMILY_TRIUMPH: 2755 case BCM_FAMILY_SCORPION: 2756 case BCM_FAMILY_CONQUEROR: 2757 case BCM_FAMILY_TRIUMPH2: 2758 case BCM_FAMILY_TITAN: 2759 case BCM_FAMILY_TRIDENT: 2760 case BCM_FAMILY_KATANA: 2761 { 2762 int port; 2763 int cpu_hg_index = 0; 2764 2765 port_tab_entry_t pte; 2766 if (BCM_MODID_INVALID == my_modid) { 2767 return BCM_E_BADID; 2768 } 2769 2770 #ifdef BCM_TRIUMPH_SUPPORT 2771 if ((BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TRIUMPH || 2772 BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TRIUMPH2) && 2773 NUM_MODID(unit) > 1) { 2774 /* Dual-modid is enabled (32-port module mode). The my_modid 2775 * value specified here needs to be an even number. 2776 */ 2777 if (my_modid & 0x1) { 2778 return BCM_E_BADID; 2779 } 2780 } 2781 #endif 2782 2783 2784 PBMP_E_ITER(unit, port) { 2785 BCM_IF_ERROR_RETURN 2786 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte)); 2787 if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) { 2788 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid); 2789 } 2790 BCM_IF_ERROR_RETURN 2791 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, port, &pte)); 2792 } 2793 #ifdef BCM_TRIUMPH2_SUPPORT 2794 if (soc_feature(unit, soc_feature_wlan) || 2795 (soc_feature(unit, soc_feature_mim)) || 2796 (soc_feature(unit, soc_feature_proxy_port_property))) { 2797 soc_info_t *si; 2798 int i, min, max; 2799 lport_tab_entry_t lport_profile; 2800 2801 si = &SOC_INFO(unit); 2802 /* Do it for the loopback port */ 2803 port = SOC_IS_ENDURO(unit)? 1 : si->lb_port; 2804 BCM_IF_ERROR_RETURN 2805 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte)); 2806 if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) { 2807 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid); 2808 } 2809 BCM_IF_ERROR_RETURN 2810 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, port, &pte)); 2811 2812 /* Update modid for LPORT profiles */ 2813 #if defined(BCM_TRX_SUPPORT) 2814 if (soc_feature(unit, soc_feature_lport_tab_profile)) { 2815 if(SOC_MEM_FIELD_VALID(unit, LPORT_TABm, MY_MODIDf)) { 2816 BCM_IF_ERROR_RETURN 2817 (_bcm_lport_profile_field32_modify 2818 (unit, LPORT_PROFILE_LPORT_TAB, MY_MODIDf, my_modid)); 2819 } 2820 } else 2821 #endif /* BCM_TRX_SUPPORT */ 2822 { 2823 min = soc_mem_index_min(unit, LPORT_TABm); 2824 max = soc_mem_index_max(unit, LPORT_TABm); 2825 for (i = min; i <= max; i++) { 2826 BCM_IF_ERROR_RETURN 2827 (READ_LPORT_TABm(unit, MEM_BLOCK_ANY, i, 2828 &lport_profile)); 2829 if (soc_mem_field_valid(unit, LPORT_TABm, 2830 SRC_SYS_PORT_IDf)) { 2831 if (soc_mem_field32_get(unit, LPORT_TABm, 2832 &lport_profile, 2833 SRC_SYS_PORT_IDf) != 2834 si->lb_port) { 2835 continue; 2836 } 2837 } else if (soc_mem_field_valid(unit, LPORT_TABm, 2838 MIM_MC_TERM_ENABLEf)) { 2839 if (!soc_mem_field32_get(unit, LPORT_TABm, 2840 &lport_profile, 2841 MIM_MC_TERM_ENABLEf)) { 2842 continue; 2843 } 2844 } 2845 if (soc_mem_field_valid(unit, LPORT_TABm, MY_MODIDf)) { 2846 soc_LPORT_TABm_field32_set(unit, &lport_profile, 2847 MY_MODIDf, my_modid); 2848 } 2849 BCM_IF_ERROR_RETURN 2850 (WRITE_LPORT_TABm(unit, MEM_BLOCK_ALL, i, 2851 &lport_profile)); 2852 } 2853 } 2854 } 2855 #endif 2856 PBMP_ST_ITER(unit, port) { 2857 BCM_IF_ERROR_RETURN 2858 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte)); 2859 if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) { 2860 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid); 2861 } 2862 BCM_IF_ERROR_RETURN 2863 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, port, &pte)); 2864 2865 BCM_IF_ERROR_RETURN 2866 (_bcm_stk_my_modid_set(unit, port, my_modid)); 2867 } 2868 port = CMIC_PORT(unit); 2869 BCM_IF_ERROR_RETURN 2870 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte)); 2871 if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) { 2872 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid); 2873 } 2874 BCM_IF_ERROR_RETURN 2875 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, port, &pte)); 2876 if (!SOC_IS_TD_TT(unit) && !SOC_IS_KATANAX(unit) && 2877 !SOC_IS_TRIUMPH3(unit)) { 2878 BCM_IF_ERROR_RETURN 2879 (soc_mem_read(unit, IPORT_TABLEm, MEM_BLOCK_ANY, port, &pte)); 2880 soc_IPORT_TABLEm_field32_set(unit, &pte, MY_MODIDf, my_modid); 2881 BCM_IF_ERROR_RETURN 2882 (soc_mem_write(unit, IPORT_TABLEm, MEM_BLOCK_ALL, port, &pte)); 2883 } 2884 2885 /* FAE port */ 2886 if (soc_feature(unit, soc_feature_flex_flowtracker_ver_1)) { 2887 port = SOC_INFO(unit).fae_port; 2888 BCM_IF_ERROR_RETURN 2889 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte)); 2890 if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) { 2891 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid); 2892 } 2893 BCM_IF_ERROR_RETURN 2894 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, port, &pte)); 2895 } 2896 2897 /* UPdate the PORT_TABm of cpu_hg_index if relevant */ 2898 cpu_hg_index = SOC_IS_KATANA2(unit) ? 2899 SOC_INFO(unit).cpu_hg_pp_port_index : 2900 SOC_INFO(unit).cpu_hg_index; 2901 if (cpu_hg_index != -1) { 2902 BCM_IF_ERROR_RETURN 2903 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, cpu_hg_index, &pte)); 2904 if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) { 2905 soc_mem_field32_set(unit, port_tab, &pte, MY_MODIDf, my_modid); 2906 } 2907 BCM_IF_ERROR_RETURN 2908 (soc_mem_write(unit, port_tab, MEM_BLOCK_ALL, cpu_hg_index, &pte)); 2909 } 2910 2911 /* Mirroring across stack */ 2912 if (soc_feature(unit, soc_feature_src_modid_blk) && 2913 !SOC_IS_SHADOW(unit)) { 2914 soc_field_t field = MY_MODIDf; 2915 #ifdef BCM_TRIDENT_SUPPORT 2916 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) || 2917 SOC_IS_TRIUMPH3(unit)) { 2918 if(soc_mem_field_valid(unit,EGR_PORTm,MY_MODIDf)) { 2919 PBMP_ALL_ITER(unit, port) { 2920 BCM_IF_ERROR_RETURN 2921 (soc_mem_field32_modify(unit, EGR_PORTm, port, 2922 MY_MODIDf, my_modid)); 2923 } 2924 port = SOC_INFO(unit).cpu_hg_index; 2925 if (soc_mem_index_max(unit, EGR_PORTm) == port) { 2926 BCM_IF_ERROR_RETURN 2927 (soc_mem_field32_modify(unit, EGR_PORTm, port, 2928 MY_MODIDf, my_modid)); 2929 } 2930 } 2931 } else 2932 #endif /* BCM_TRIDENT_SUPPORT */ 2933 { 2934 soc_reg_t egr_port_reg, iegr_port_reg; 2935 egr_port_reg = SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 2936 SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND(unit) || 2937 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit) ? 2938 EGR_PORT_64r : EGR_PORTr; 2939 iegr_port_reg = SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 2940 SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND(unit) || 2941 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)? 2942 IEGR_PORT_64r : IEGR_PORTr; 2943 PBMP_ALL_ITER(unit, port) { 2944 BCM_IF_ERROR_RETURN 2945 (soc_reg_fields32_modify(unit, egr_port_reg, port, 1, 2946 &field, (uint32*)&my_modid)); 2947 } 2948 port = CMIC_PORT(unit); 2949 BCM_IF_ERROR_RETURN 2950 (soc_reg_fields32_modify(unit, iegr_port_reg, port, 1, 2951 &field, (uint32*)&my_modid)); 2952 } 2953 } 2954 #if defined(BCM_RAPTOR_SUPPORT) 2955 if (soc_feature(unit, soc_feature_mac_learn_limit) && 2956 SOC_REG_IS_VALID(unit, MAC_LIMIT_CONFIGr)) { 2957 uint32 limit_config; 2958 /* Configure the MODID for MAC learn limit */ 2959 BCM_IF_ERROR_RETURN(READ_MAC_LIMIT_CONFIGr(unit, &limit_config)); 2960 soc_reg_field_set(unit, MAC_LIMIT_CONFIGr, &limit_config, 2961 MY_MODIDf, my_modid); 2962 BCM_IF_ERROR_RETURN(WRITE_MAC_LIMIT_CONFIGr(unit, limit_config)); 2963 } 2964 #endif /* BCM_RAPTOR_SUPPORT */ 2965 #ifdef BCM_KATANA2_SUPPORT 2966 2967 /* If not running in the coe stackig mode, setup the second module 2968 as the default one to host all pp_ports, else, the user will 2969 create the necessary modules with separate APIs */ 2970 if (SOC_IS_KATANA2(unit)) { 2971 2972 int my_modid_list[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 2973 int my_modid_valid[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 2974 int my_modport_base_ptr[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 2975 2976 BCM_IF_ERROR_RETURN( 2977 bcm_kt2_modid_get_all(unit, my_modid_list, my_modid_valid, 2978 my_modport_base_ptr)); 2979 2980 /* If 'coe_stacking_mode' is not-enabled, default to setting up 2981 the modules like usual, wherein the my_mod+1 is reserved for 2982 pp_ports, else just setup the needed config for 'my_modid' */ 2983 if(!SOC_INFO(unit).coe_stacking_mode) { 2984 2985 int num_modid = 1; 2986 2987 /* reserve my_modid+1 for channelized ports. 2988 * so allow upto my_modid = modid_max -1 */ 2989 if (((soc_feature(unit, soc_feature_linkphy_coe) && 2990 SOC_INFO(unit).linkphy_enabled) || 2991 (soc_feature(unit, soc_feature_subtag_coe) && 2992 SOC_INFO(unit).subtag_enabled)) && 2993 (my_modid == SOC_INFO(unit).modid_max)) { 2994 return BCM_E_BADID; 2995 } 2996 2997 /* PP_PORT_GPP_TRANSLATION_x 2998 * 4 instances one each for icfg, il2lu, isw2 and ipars stages of ipipe 2999 * EGR_PP_PORT_GPP_TRANSLATION_x 3000 * 2 instances one each for evlan and ehcpm stages of epipe 3001 * If LinkPHY/SubTag CoE is enabled then 3002 * all 170 pp_ports cannot be accomodated 3003 * insingle modid. We will use 2 mod_ids. 3004 * All pp_port 0 to 41 mapped to my_modid 3005 * remaining pp_ports 42 to 169 mapped to my_modid+1. 3006 * Do this addition of the second mod addition only if 3007 * the user is has not enabled the stacking module, in 3008 * which case, the needed modules would need to be 3009 * created at run time. 3010 */ 3011 my_modid_list[0] = my_modid; 3012 3013 if (!SOC_IS_METROLITE(unit)) { 3014 if ((soc_feature(unit, soc_feature_linkphy_coe) && 3015 SOC_INFO(unit).linkphy_enabled) || 3016 (soc_feature(unit, soc_feature_subtag_coe) && 3017 SOC_INFO(unit).subtag_enabled)) { 3018 my_modid_list[1] = my_modid + 1; 3019 my_modid_valid[1] = 1; 3020 num_modid = 2; 3021 } 3022 } 3023 3024 BCM_IF_ERROR_RETURN( 3025 bcm_kt2_modid_set_all(unit, my_modid_list, my_modid_valid, 3026 my_modport_base_ptr)); 3027 3028 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 3029 int old_my_modid[2] = {0}, new_my_modid[2] = {0}; 3030 int old_base_index[2] = {0}, base_index[2] = {0}; 3031 int old_num_ports[2] = {0}, num_ports[2] = {0}; 3032 int i, j, k; 3033 source_trunk_map_table_entry_t stm_entry; 3034 source_trunk_map_modbase_entry_t stm_modbase_entry; 3035 3036 for (j = 0; j < num_modid; j++) { 3037 old_my_modid[j] = SOC_BASE_MODID(unit) + j; 3038 new_my_modid[j] = my_modid_list[j]; 3039 } 3040 3041 /* For Katana2 when LinkPHY/CoE is enabled then 2 modids are used 3042 * my_modid for physical ports and my_modid+1 for subports 3043 * When modid is changed, the etries pointed to by base of 3044 * source_trunk_map_modbase table in source_trunk_map table need to be 3045 * copied to new location appropriately. 3046 * When new my_modid == old my_modid+1 then we need to copy the 3047 * entries pointed to by old my_modid+1 to new my_modid+1 first 3048 * followed by old my_modid to new my_modid 3049 */ 3050 j = ((num_modid > 1) && 3051 (new_my_modid[0] == old_my_modid[1])) ? 1 : 0; 3052 3053 for (k = 0; k < num_modid; k++) { 3054 j = ((num_modid > 1) && 3055 (new_my_modid[0] == old_my_modid[1])) ? 3056 (j - k) : (j + k); 3057 3058 /* Allocate a source modid base index for new my_modid */ 3059 BCM_IF_ERROR_RETURN( 3060 _bcm_esw_src_modid_base_index_get(unit, 3061 new_my_modid[j], 1, &base_index[j])); 3062 3063 if (SOC_MODID_ADDRESSABLE(unit, old_my_modid[j]) && 3064 (old_my_modid[j] != new_my_modid[j])) { 3065 SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_MODBASEm(unit, 3066 MEM_BLOCK_ANY, old_my_modid[j], 3067 &stm_modbase_entry)); 3068 3069 old_base_index[j] = 3070 soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit, 3071 &stm_modbase_entry, BASEf); 3072 3073 if (0 != old_base_index[j]) { 3074 /* Transfer port attributes from the SOURCE_TRUNK_MAP 3075 * region of the old my_modid[j] to the SOURCE_TRUNK_MAP 3076 * region of the new my_modid[j]. 3077 */ 3078 old_num_ports[j] = src_modid_base_index_bk[unit]-> 3079 num_ports[old_my_modid[j]]; 3080 num_ports[j] = src_modid_base_index_bk[unit]-> 3081 num_ports[new_my_modid[j]]; 3082 for (i = 0; 3083 i < old_num_ports[j] && i < num_ports[j]; i++) { 3084 SOC_IF_ERROR_RETURN( 3085 READ_SOURCE_TRUNK_MAP_TABLEm(unit, 3086 MEM_BLOCK_ANY, i + old_base_index[j], 3087 &stm_entry)); 3088 SOC_IF_ERROR_RETURN( 3089 WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, 3090 MEM_BLOCK_ALL, i + base_index[j], 3091 &stm_entry)); 3092 } 3093 } 3094 } 3095 } 3096 3097 /* Release old base index */ 3098 if (new_my_modid[0] != old_my_modid[0]) { 3099 if ((num_modid > 1) && 3100 (new_my_modid[0] == old_my_modid[1]) && 3101 (0 != old_base_index[0])) { 3102 BCM_IF_ERROR_RETURN(_src_modid_base_index_free(unit, 3103 old_my_modid[0], old_num_ports[0])); 3104 } else if ((num_modid > 1) && 3105 (new_my_modid[1] == old_my_modid[0]) && 3106 (0 != old_base_index[1])) { 3107 BCM_IF_ERROR_RETURN(_src_modid_base_index_free(unit, 3108 old_my_modid[1], old_num_ports[1])); 3109 } else { 3110 for (j = 0; j < num_modid; j++) { 3111 if (0 != old_base_index[j]) { 3112 BCM_IF_ERROR_RETURN( 3113 _src_modid_base_index_free(unit, 3114 old_my_modid[j], old_num_ports[j])); 3115 } 3116 } 3117 } 3118 } 3119 } 3120 } else { 3121 3122 int old_my_modid = 0; 3123 int old_base_index = 0, base_index = 0; 3124 int old_num_ports = 0, num_ports = 0; 3125 int i; 3126 source_trunk_map_table_entry_t stm_entry; 3127 source_trunk_map_modbase_entry_t stm_modbase_entry; 3128 3129 /* Allocate a source modid base index for the base modid */ 3130 BCM_IF_ERROR_RETURN(_bcm_esw_src_modid_base_index_get(unit, 3131 my_modid, 1, &base_index)); 3132 3133 old_my_modid = SOC_BASE_MODID(unit); 3134 if (SOC_MODID_ADDRESSABLE(unit, old_my_modid) && 3135 (old_my_modid != my_modid)) { 3136 SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_MODBASEm(unit, 3137 MEM_BLOCK_ANY, old_my_modid, &stm_modbase_entry)); 3138 old_base_index = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit, 3139 &stm_modbase_entry, BASEf); 3140 old_num_ports = src_modid_base_index_bk[unit]->num_ports[old_my_modid]; 3141 if ((0 != old_base_index) || (0 != old_num_ports)) { 3142 /* Transfer port attributes from the SOURCE_TRUNK_MAP 3143 * region of the old my_modid to the SOURCE_TRUNK_MAP 3144 * region of the new my_modid. 3145 */ 3146 num_ports = src_modid_base_index_bk[unit]-> 3147 num_ports[my_modid]; 3148 for (i = 0; i < old_num_ports && i < num_ports; i++) { 3149 SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, 3150 MEM_BLOCK_ANY, i + old_base_index, &stm_entry)); 3151 SOC_IF_ERROR_RETURN(WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, 3152 MEM_BLOCK_ALL, i + base_index, &stm_entry)); 3153 } 3154 3155 /* Release old base index */ 3156 BCM_IF_ERROR_RETURN(_src_modid_base_index_free(unit, 3157 old_my_modid, old_num_ports)); 3158 /* Reset the number of ports */ 3159 src_modid_base_index_bk[unit]->num_ports[old_my_modid] = 0; 3160 } 3161 } 3162 3163 /* Assign the mod id being created to the first location, 3164 which is where the default local mod-id lives */ 3165 my_modid_list[0] = my_modid; 3166 3167 /* Write this data back to the hardware */ 3168 BCM_IF_ERROR_RETURN( 3169 bcm_kt2_modid_set_all(unit, my_modid_list, my_modid_valid, 3170 my_modport_base_ptr)); 3171 } 3172 } else 3173 #endif /* BCM_KATANA2_SUPPORT */ 3174 { 3175 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 3176 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 3177 int old_my_modid = 0; 3178 int old_base_index = 0, base_index = 0; 3179 int old_num_ports = 0, num_ports = 0; 3180 int i; 3181 source_trunk_map_table_entry_t stm_entry; 3182 source_trunk_map_modbase_entry_t stm_modbase_entry; 3183 3184 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 3185 if (SOC_IS_TD2P_TT2P(unit)) { 3186 src_modid_base_index_bk[unit]->num_ports[my_modid] = 3187 BCM_STK_TD2P_NUM_LPORTS; 3188 } 3189 #if defined(BCM_MONTEREY_SUPPORT) 3190 else if (SOC_IS_MONTEREY(unit)) { 3191 src_modid_base_index_bk[unit]->num_ports[my_modid] = 3192 BCM_STK_MONTEREY_NUM_LPORTS; 3193 } 3194 #endif /* BCM_MONTEREY_SUPPORT */ 3195 #if defined(BCM_APACHE_SUPPORT) 3196 else if (SOC_IS_APACHE(unit)) { 3197 src_modid_base_index_bk[unit]->num_ports[my_modid] = 3198 BCM_STK_APACHE_NUM_LPORTS; 3199 } 3200 #endif /* BCM_APACHE_SUPPORT */ 3201 #if defined(BCM_TRIDENT3_SUPPORT) 3202 else if (SOC_IS_TRIDENT3X(unit)) { 3203 if (SOC_IS_TRIDENT3(unit)) { 3204 src_modid_base_index_bk[unit]->num_ports[my_modid] = 3205 TRIDENT3_DEV_PORTS_PER_DEV; 3206 } 3207 #if defined(BCM_MAVERICK2_SUPPORT) 3208 if (SOC_IS_MAVERICK2(unit)) { 3209 src_modid_base_index_bk[unit]->num_ports[my_modid] = 3210 MAVERICK2_DEV_PORTS_PER_DEV; 3211 } 3212 #endif 3213 #if defined(BCM_HELIX5_SUPPORT) 3214 if (SOC_IS_HELIX5(unit)) { 3215 src_modid_base_index_bk[unit]->num_ports[my_modid] = 3216 HELIX5_DEV_PORTS_PER_DEV; 3217 } 3218 #endif 3219 } 3220 #endif /* BCM_TRIDENT3_SUPPORT */ 3221 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 3222 3223 /* Allocate a source modid base index for new my_modid */ 3224 BCM_IF_ERROR_RETURN(_bcm_esw_src_modid_base_index_get(unit, 3225 my_modid, 1, &base_index)); 3226 3227 old_my_modid = SOC_BASE_MODID(unit); 3228 if (SOC_MODID_ADDRESSABLE(unit, old_my_modid) && 3229 (old_my_modid != my_modid)) { 3230 SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_MODBASEm(unit, 3231 MEM_BLOCK_ANY, old_my_modid, &stm_modbase_entry)); 3232 old_base_index = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit, 3233 &stm_modbase_entry, BASEf); 3234 old_num_ports = src_modid_base_index_bk[unit]->num_ports[old_my_modid]; 3235 if ((0 != old_base_index) || (0 != old_num_ports)) { 3236 /* Transfer port attributes from the SOURCE_TRUNK_MAP 3237 * region of the old my_modid to the SOURCE_TRUNK_MAP 3238 * region of the new my_modid. 3239 */ 3240 if ((!SOC_IS_TD2P_TT2P(unit) && !SOC_IS_APACHE(unit) && !SOC_IS_TRIDENT3X(unit)) || 3241 old_base_index != base_index) { 3242 /* For TD2P and APACHE 3243 * only transfer if the base idx differs 3244 */ 3245 num_ports = src_modid_base_index_bk[unit]-> 3246 num_ports[my_modid]; 3247 for (i=0; i < old_num_ports && i < num_ports; i++) { 3248 SOC_IF_ERROR_RETURN( 3249 READ_SOURCE_TRUNK_MAP_TABLEm( 3250 unit, MEM_BLOCK_ANY, 3251 i + old_base_index, &stm_entry)); 3252 SOC_IF_ERROR_RETURN( 3253 WRITE_SOURCE_TRUNK_MAP_TABLEm( 3254 unit, MEM_BLOCK_ALL, 3255 i + base_index, &stm_entry)); 3256 } 3257 } 3258 3259 /* Release old base index */ 3260 BCM_IF_ERROR_RETURN( 3261 _src_modid_base_index_free( 3262 unit, old_my_modid, old_num_ports)); 3263 3264 /* Reset the number of ports */ 3265 src_modid_base_index_bk[unit]->num_ports[old_my_modid] = 0; 3266 } 3267 } 3268 } 3269 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 3270 if (soc_feature(unit, soc_feature_td2p_multi_modid)) { 3271 uint64 mod_64; 3272 3273 /* 3274 * Program my module id in MY_MODID_SET_64 and 3275 * MY_MODID_SET_2_64 registers. 3276 */ 3277 COMPILER_64_ZERO(mod_64); 3278 BCM_IF_ERROR_RETURN(READ_MY_MODID_SET_64r(unit, &mod_64)); 3279 soc_reg64_field32_set(unit, MY_MODID_SET_64r, &mod_64, 3280 MODID_0_VALIDf, 1); 3281 soc_reg64_field32_set(unit, MY_MODID_SET_64r, &mod_64, 3282 MODID_0f, my_modid); 3283 BCM_IF_ERROR_RETURN(WRITE_MY_MODID_SET_64r(unit, mod_64)); 3284 3285 COMPILER_64_ZERO(mod_64); 3286 BCM_IF_ERROR_RETURN(READ_MY_MODID_SET_2_64r(unit, &mod_64)); 3287 soc_reg64_field32_set(unit, MY_MODID_SET_2_64r, &mod_64, 3288 MODID_0_VALIDf, 1); 3289 soc_reg64_field32_set(unit, MY_MODID_SET_2_64r, &mod_64, 3290 MODID_0f, my_modid); 3291 3292 BCM_IF_ERROR_RETURN(WRITE_MY_MODID_SET_2_64r(unit, mod_64)); 3293 3294 COMPILER_64_ZERO(mod_64); 3295 BCM_IF_ERROR_RETURN(READ_EGR_MY_MODID_SET_64r(unit, &mod_64)); 3296 soc_reg64_field32_set(unit, EGR_MY_MODID_SET_64r, &mod_64, 3297 MODID_0_VALIDf, 1); 3298 soc_reg64_field32_set(unit, EGR_MY_MODID_SET_64r, &mod_64, 3299 MODID_0f, my_modid); 3300 BCM_IF_ERROR_RETURN(WRITE_EGR_MY_MODID_SET_64r(unit, mod_64)); 3301 3302 if (SOC_REG_IS_VALID(unit, IARB_MY_MODID_SET_64r)) { 3303 COMPILER_64_ZERO(mod_64); 3304 BCM_IF_ERROR_RETURN(READ_IARB_MY_MODID_SET_64r(unit, &mod_64)); 3305 soc_reg64_field32_set(unit, IARB_MY_MODID_SET_64r, &mod_64, 3306 MODID_0_VALIDf, 1); 3307 soc_reg64_field32_set(unit, IARB_MY_MODID_SET_64r, &mod_64, 3308 MODID_0f, my_modid); 3309 BCM_IF_ERROR_RETURN(WRITE_IARB_MY_MODID_SET_64r(unit, mod_64)); 3310 } 3311 } 3312 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 3313 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 3314 } 3315 } 3316 break; 3317 #endif /* BCM_FIREBOLT_SUPPORT */ 3318 3319 #if defined(BCM_HERCULES_SUPPORT) 3320 case BCM_FAMILY_HERCULES: 3321 if (BCM_MODID_INVALID == my_modid) { 3322 SOC_CONTROL(unit)->info.modid_count = 0; 3323 } else { 3324 SOC_CONTROL(unit)->info.modid_count = 1; 3325 } 3326 break; 3327 #endif /* BCM_HERCULES_SUPPORT */ 3328 3329 default: 3330 return BCM_E_UNAVAIL; 3331 } 3332 3333 SOC_BASE_MODID_SET(unit, my_modid); 3334 soc_event_generate(unit, SOC_SWITCH_EVENT_MODID_CHANGE, 0,0,0); 3335 3336 /* Base module id set/get macro */ 3337 3338 return BCM_E_NONE; 3339 } 3340 3341 /* 3342 * Function: 3343 * bcm_stk_my_modid_get 3344 * Purpose: 3345 * Get the MY_MODID field 3346 * Parameters: 3347 * unit - SOC unit# 3348 * my_modid - (out)the value 3349 * Returns: 3350 * BCM_E_XXX 3351 */ 3352 int 3353 bcm_esw_stk_my_modid_get(int unit, int *my_modid) 3354 { 3355 *my_modid = SOC_BASE_MODID(unit); 3356 3357 if (BCM_MODID_INVALID == *my_modid) { 3358 return BCM_E_UNAVAIL; 3359 } 3360 3361 return (BCM_E_NONE); 3362 } 3363 3364 int 3365 bcm_stk_modport_voq_cosq_profile_get(int unit, bcm_port_t ing_port, 3366 bcm_module_t dest_modid, int *profile_id) 3367 { 3368 if (profile_id == NULL) { 3369 return BCM_E_PARAM; 3370 } 3371 3372 #if defined(BCM_TRIDENT_SUPPORT) 3373 if (SOC_IS_TD_TT(unit)) { 3374 *profile_id = -1; 3375 BCM_IF_ERROR_RETURN( 3376 bcm_td_stk_modport_voq_op(unit, ing_port, dest_modid, 3377 profile_id, _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_GET)); 3378 return BCM_E_NONE; 3379 } 3380 #endif /* BCM_TRIDENT_SUPPORT */ 3381 3382 return BCM_E_UNAVAIL; 3383 } 3384 3385 int 3386 bcm_stk_modport_voq_cosq_profile_set(int unit, bcm_port_t ing_port, 3387 bcm_module_t dest_modid, int profile_id) 3388 { 3389 #if defined(BCM_TRIDENT_SUPPORT) 3390 if (SOC_IS_TD_TT(unit)) { 3391 BCM_IF_ERROR_RETURN( 3392 bcm_td_stk_modport_voq_op(unit, ing_port, dest_modid, 3393 &profile_id, _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_SET)); 3394 return BCM_E_NONE; 3395 } 3396 #endif /* BCM_TRIDENT_SUPPORT */ 3397 3398 return BCM_E_UNAVAIL; 3399 } 3400 3401 #if defined(BCM_WARM_BOOT_SUPPORT) 3402 /* 3403 * Function: 3404 * bcm_esw_reload_stk_my_modid_get 3405 * Purpose: 3406 * Get the MY_MODID field 3407 * Parameters: 3408 * unit - SOC unit# 3409 * Returns: 3410 * BCM_E_XXX 3411 * Note: 3412 * This routine is being called by _bcm_modules_init(), so it is not 3413 * not called by the Stack init routine. 3414 */ 3415 int 3416 bcm_esw_reload_stk_my_modid_get(int unit) 3417 { 3418 uint32 config; 3419 int blk, port; 3420 bcm_module_t my_modid = 0; 3421 soc_mem_t port_tab = PORT_TABm; 3422 3423 COMPILER_REFERENCE(config); 3424 COMPILER_REFERENCE(blk); 3425 COMPILER_REFERENCE(port); 3426 3427 if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) { 3428 port_tab = ING_DEVICE_PORTm; 3429 } 3430 3431 switch (BCM_CHIP_FAMILY(unit)) { 3432 3433 #if defined(BCM_FIREBOLT_SUPPORT) 3434 case BCM_FAMILY_FIREBOLT: 3435 case BCM_FAMILY_BRADLEY: 3436 case BCM_FAMILY_HUMV: 3437 case BCM_FAMILY_TRIUMPH: 3438 case BCM_FAMILY_SCORPION: 3439 case BCM_FAMILY_CONQUEROR: 3440 case BCM_FAMILY_TRIUMPH2: 3441 case BCM_FAMILY_TITAN: 3442 case BCM_FAMILY_TRIDENT: 3443 case BCM_FAMILY_KATANA: 3444 PBMP_PORT_ITER(unit, port) { 3445 port_tab_entry_t pte; 3446 BCM_IF_ERROR_RETURN 3447 (soc_mem_read(unit, port_tab, MEM_BLOCK_ANY, port, &pte)); 3448 if (soc_mem_field_valid(unit, port_tab, MY_MODIDf)) { 3449 my_modid = soc_mem_field32_get(unit, port_tab, &pte, MY_MODIDf); 3450 } 3451 break; 3452 } 3453 #endif 3454 #ifdef BCM_KATANA2_SUPPORT 3455 if (SOC_IS_KATANA2(unit)) { 3456 int my_modid_list[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 3457 int my_modid_valid[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 3458 int my_modport_base_ptr[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 3459 3460 BCM_IF_ERROR_RETURN( 3461 bcm_kt2_modid_get_all(unit, my_modid_list, my_modid_valid, 3462 my_modport_base_ptr)); 3463 my_modid = my_modid_list[0]; 3464 } 3465 #endif 3466 break; 3467 3468 #if defined(BCM_HERCULES_SUPPORT) 3469 case BCM_FAMILY_HERCULES: 3470 if (SOC_CONTROL(unit)->info.modid_count > 0) { 3471 my_modid = SOC_DEFAULT_DMA_SRCMOD_GET(unit); 3472 } else { 3473 return BCM_E_UNAVAIL; 3474 } 3475 break; 3476 #endif /* BCM_HERCULES_SUPPORT */ 3477 3478 default: 3479 return BCM_E_UNAVAIL; 3480 } 3481 3482 SOC_BASE_MODID_SET(unit, my_modid); 3483 SOC_DEFAULT_DMA_SRCMOD_SET(unit, my_modid); 3484 return BCM_E_NONE; 3485 } 3486 #endif /* BCM_WARM_BOOT_SUPPORT */ 3487 3488 #if defined(BCM_TRX_SUPPORT) 3489 STATIC int 3490 _bcm_stk_modport_profile_init(int unit) 3491 { 3492 soc_mem_t mem; 3493 int entry_words; 3494 soc_profile_mem_t *profile; 3495 void *entry; 3496 uint32 base_index, index; 3497 int rv, modid_count, port_count, alloc_size, port; 3498 3499 if (modport_profile[unit] == NULL) { 3500 modport_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t), 3501 "ModPort Profile Mem"); 3502 if (modport_profile[unit] == NULL) { 3503 return BCM_E_MEMORY; 3504 } 3505 } else { 3506 soc_profile_mem_destroy(unit, modport_profile[unit]); 3507 } 3508 profile = modport_profile[unit]; 3509 soc_profile_mem_t_init(profile); 3510 3511 mem = MODPORT_MAPm; 3512 entry_words = sizeof(modport_map_entry_t) / sizeof(uint32); 3513 3514 BCM_IF_ERROR_RETURN 3515 (soc_profile_mem_create(unit, &mem, &entry_words, 1, profile)); 3516 3517 modid_count = SOC_MODID_MAX(unit) + 1; 3518 3519 if (SOC_WARM_BOOT(unit) || SOC_IS_RCPU_ONLY(unit)) { /* Warm Boot */ 3520 int i; 3521 uint32 val; 3522 3523 /* Gather reference count for modport map profile table */ 3524 PBMP_ALL_ITER(unit, port) { 3525 SOC_IF_ERROR_RETURN 3526 (READ_MODPORT_MAP_SELr(unit, port, &val)); 3527 index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val, 3528 MODPORT_MAP_INDEX_UPPERf); 3529 index *= modid_count; 3530 for (i = 0; i < modid_count; i++) { 3531 SOC_PROFILE_MEM_REFERENCE(unit, modport_profile[unit], 3532 index + i, 1); 3533 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, 3534 modport_profile[unit], 3535 index + i, 3536 modid_count); 3537 } 3538 } 3539 3540 return BCM_E_NONE; 3541 } 3542 3543 alloc_size = modid_count * entry_words * sizeof(uint32); 3544 entry = sal_alloc(alloc_size, "modport_map_entry"); 3545 if (entry == NULL) { 3546 return BCM_E_MEMORY; 3547 } 3548 sal_memset(entry, 0, alloc_size); 3549 rv = soc_profile_mem_add(unit, profile, &entry, modid_count, &base_index); 3550 sal_free(entry); 3551 if (BCM_FAILURE(rv)) { 3552 return rv; 3553 } 3554 3555 port_count = 0; 3556 PBMP_ALL_ITER(unit, port) { 3557 BCM_IF_ERROR_RETURN 3558 (WRITE_MODPORT_MAP_SELr(unit, port, base_index / modid_count)); 3559 port_count++; 3560 } 3561 3562 for (index = 0; index < modid_count; index++) { 3563 SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + index, 3564 port_count - 1); 3565 } 3566 3567 return BCM_E_NONE; 3568 } 3569 3570 STATIC int 3571 bcmi_trx_stk_port_modport_op(int unit, int op, bcm_port_t ing_port, 3572 bcm_module_t dest_modid, bcm_port_t *dest_port, 3573 int dest_port_count) 3574 { 3575 int rv; 3576 int modid_count, modid_min, modid_max; 3577 pbmp_t pbmp, hg_trunk_pbmp, new_pbmp; 3578 int index; 3579 int tid; 3580 bcm_trunk_chip_info_t chip_info; 3581 bcm_trunk_member_t member; 3582 int member_count; 3583 bcm_port_t local_port; 3584 uint32 base_index, new_base_index; 3585 soc_profile_mem_t *profile; 3586 modport_map_entry_t *entry_array; 3587 void *entries; 3588 uint32 rval; 3589 uint8 istrunk[SOC_MAX_NUM_PORTS]; 3590 uint8 dest[SOC_MAX_NUM_PORTS]; 3591 int old_profile_index, new_profile_index; 3592 bcmi_trx_modport_map_entry_t *trx_entry_array; 3593 int ref_count; 3594 3595 if (!soc_feature(unit, 3596 soc_feature_modport_map_dest_is_hg_port_bitmap)) { 3597 return BCM_E_UNAVAIL; 3598 } 3599 3600 if (op <= 0 || op >= _BCM_STK_PORT_MODPORT_OP_COUNT) { 3601 return BCM_E_PARAM; 3602 } 3603 3604 if (BCM_GPORT_IS_SET(ing_port)) { 3605 BCM_IF_ERROR_RETURN( 3606 bcm_esw_port_local_get(unit, ing_port, &ing_port)); 3607 } 3608 3609 if (!SOC_PORT_VALID(unit, ing_port)) { 3610 return BCM_E_PORT; 3611 } 3612 3613 modid_count = SOC_MODID_MAX(unit) + 1; 3614 if (dest_modid == -1) { 3615 modid_min = 0; 3616 modid_max = modid_count - 1; 3617 } else { 3618 if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) { 3619 return BCM_E_PARAM; 3620 } 3621 modid_min = modid_max = dest_modid; 3622 } 3623 3624 if (dest_port_count > SOC_MAX_NUM_PORTS) { 3625 return BCM_E_INTERNAL; 3626 } 3627 3628 sal_memset(istrunk, 0, (sizeof(uint8) * SOC_MAX_NUM_PORTS)); 3629 sal_memset(dest, 0, (sizeof(uint8) * SOC_MAX_NUM_PORTS)); 3630 3631 BCM_PBMP_CLEAR(pbmp); 3632 for (index = 0; index < dest_port_count; index++) { 3633 if (BCM_GPORT_IS_TRUNK(dest_port[index])) { 3634 tid = SOC_GPORT_TRUNK_GET(dest_port[index]); 3635 3636 BCM_IF_ERROR_RETURN( 3637 bcm_esw_trunk_chip_info_get(unit, &chip_info)); 3638 if (chip_info.trunk_fabric_id_min < 0 || 3639 tid < chip_info.trunk_fabric_id_min || 3640 tid > chip_info.trunk_fabric_id_max) { 3641 return BCM_E_PARAM; 3642 } 3643 3644 /* Get Higig trunk group port bitmap */ 3645 BCM_IF_ERROR_RETURN( 3646 bcm_esw_trunk_get(unit, tid, NULL, 1, &member, &member_count)); 3647 if (member_count == 0) { 3648 /* No ports have been added to the Higig trunk group */ 3649 return BCM_E_PARAM; 3650 } 3651 BCM_IF_ERROR_RETURN( 3652 bcm_esw_port_local_get(unit, member.gport, &local_port)); 3653 BCM_PBMP_PORT_SET(hg_trunk_pbmp, local_port); 3654 BCM_IF_ERROR_RETURN( 3655 bcm_esw_trunk_bitmap_expand(unit, &hg_trunk_pbmp)); 3656 BCM_PBMP_OR(pbmp, hg_trunk_pbmp); 3657 3658 BCM_PBMP_ITER(pbmp, local_port) { 3659 istrunk[local_port] = 1; 3660 dest[local_port] = tid - chip_info.trunk_fabric_id_min; 3661 } 3662 } else { 3663 if (!SOC_PORT_VALID(unit, dest_port[index])) { 3664 return BCM_E_PORT; 3665 } 3666 3667 if (dest_port[index] == CMIC_PORT(unit) && 3668 BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TRIUMPH) { 3669 return BCM_E_PORT; 3670 } 3671 3672 BCM_PBMP_PORT_ADD(pbmp, dest_port[index]); 3673 istrunk[dest_port[index]] = 0; 3674 dest[dest_port[index]] = dest_port[index]; 3675 } 3676 } 3677 3678 /* Profile style MODPORT MAP bitmap table */ 3679 if (modport_profile[unit] == NULL) { 3680 _bcm_stk_modport_profile_init(unit); 3681 } 3682 profile = modport_profile[unit]; 3683 3684 entry_array = sal_alloc(sizeof(modport_map_entry_t) * modid_count, 3685 "modport_map_entry"); 3686 if (entry_array == NULL) { 3687 return BCM_E_MEMORY; 3688 } 3689 3690 trx_entry_array = 3691 sal_alloc((sizeof(bcmi_trx_modport_map_entry_t) * modid_count), 3692 "trx_modport_map_entry"); 3693 if (trx_entry_array == NULL) { 3694 sal_free(entry_array); 3695 return BCM_E_MEMORY; 3696 } 3697 3698 soc_mem_lock(unit, MODPORT_MAPm); 3699 rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval); 3700 if (BCM_FAILURE(rv)) { 3701 soc_mem_unlock(unit, MODPORT_MAPm); 3702 sal_free(entry_array); 3703 sal_free(trx_entry_array); 3704 return rv; 3705 } 3706 3707 old_profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 3708 MODPORT_MAP_INDEX_UPPERf); 3709 base_index = (modid_count * old_profile_index); 3710 3711 for (index = 0; index < modid_count; index++) { 3712 sal_memcpy(&entry_array[index], 3713 SOC_PROFILE_MEM_ENTRY(unit, profile, void *, 3714 base_index + index), 3715 sizeof(modport_map_entry_t)); 3716 sal_memcpy( 3717 &trx_entry_array[index], 3718 &TRX_MODPORT_MAP_PROFILE 3719 (unit, old_profile_index).entry_array[index], 3720 sizeof(bcmi_trx_modport_map_entry_t)); 3721 } 3722 for (index = modid_min; index <= modid_max; index++) { 3723 switch (op) { 3724 case _BCM_STK_PORT_MODPORT_OP_SET: 3725 /* Clear original port bitmap */ 3726 sal_memset(&trx_entry_array[index], 0, 3727 (sizeof(bcmi_trx_modport_map_entry_t))); 3728 /* Set new port bitmap */ 3729 BCM_PBMP_ITER(pbmp, local_port) { 3730 if (istrunk[local_port]) { 3731 trx_entry_array[index].dest_istrunk[local_port] = 1; 3732 } 3733 trx_entry_array[index].dest[local_port] = 3734 dest[local_port]; 3735 } 3736 BCM_PBMP_ASSIGN(new_pbmp, pbmp); 3737 break; 3738 case _BCM_STK_PORT_MODPORT_OP_ADD: 3739 /* Set new port bitmap */ 3740 BCM_PBMP_ITER(pbmp, local_port) { 3741 if (istrunk[local_port]) { 3742 trx_entry_array[index].dest_istrunk[local_port] = 1; 3743 } 3744 trx_entry_array[index].dest[local_port] = 3745 dest[local_port]; 3746 } 3747 soc_mem_pbmp_field_get(unit, MODPORT_MAPm, &entry_array[index], 3748 HIGIG_PORT_BITMAPf, &new_pbmp); 3749 BCM_PBMP_OR(new_pbmp, pbmp); 3750 break; 3751 case _BCM_STK_PORT_MODPORT_OP_DELETE: 3752 /* Remove port bitmap */ 3753 BCM_PBMP_ITER(pbmp, local_port) { 3754 if (istrunk[local_port]) { 3755 trx_entry_array[index].dest_istrunk[local_port] = 0; 3756 } 3757 trx_entry_array[index].dest[local_port] = 0; 3758 } 3759 soc_mem_pbmp_field_get(unit, MODPORT_MAPm, &entry_array[index], 3760 HIGIG_PORT_BITMAPf, &new_pbmp); 3761 BCM_PBMP_REMOVE(new_pbmp, pbmp); 3762 break; 3763 /*default case is must in order to avoid compilatioin error */ 3764 /* coverity[dead_error_begin] */ 3765 default: 3766 soc_mem_unlock(unit, MODPORT_MAPm); 3767 sal_free(entry_array); 3768 sal_free(trx_entry_array); 3769 return BCM_E_INTERNAL; 3770 } 3771 soc_mem_pbmp_field_set(unit, MODPORT_MAPm, &entry_array[index], 3772 HIGIG_PORT_BITMAPf, &new_pbmp); 3773 } 3774 entries = entry_array; 3775 rv = soc_profile_mem_add(unit, profile, &entries, modid_count, 3776 &new_base_index); 3777 if (BCM_SUCCESS(rv)) { 3778 new_profile_index = (new_base_index / modid_count); 3779 soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval, 3780 MODPORT_MAP_INDEX_UPPERf, 3781 new_profile_index); 3782 rv = WRITE_MODPORT_MAP_SELr(unit, ing_port, rval); 3783 } 3784 if (BCM_SUCCESS(rv)) { 3785 sal_memcpy( 3786 TRX_MODPORT_MAP_PROFILE 3787 (unit, new_profile_index).entry_array, 3788 trx_entry_array, 3789 (sizeof(bcmi_trx_modport_map_entry_t) * modid_count)); 3790 TRX_MODPORT_MAP_PROFILE(unit, new_profile_index).ref_count++; 3791 rv = soc_profile_mem_delete(unit, profile, base_index); 3792 if (BCM_SUCCESS(rv)) { 3793 if (TRX_MODPORT_MAP_PROFILE 3794 (unit, old_profile_index).ref_count >= 1) { 3795 TRX_MODPORT_MAP_PROFILE(unit, 3796 old_profile_index).ref_count--; 3797 ref_count = 3798 TRX_MODPORT_MAP_PROFILE 3799 (unit, old_profile_index).ref_count; 3800 /* Clear old profile when ref_count = 0 */ 3801 if (ref_count == 0) { 3802 sal_memset( 3803 TRX_MODPORT_MAP_PROFILE 3804 (unit, old_profile_index).entry_array, 3805 0, 3806 (sizeof(bcmi_trx_modport_map_entry_t) * 3807 modid_count)); 3808 } 3809 } 3810 } 3811 } 3812 soc_mem_unlock(unit, MODPORT_MAPm); 3813 sal_free(entry_array); 3814 sal_free(trx_entry_array); 3815 3816 return rv; 3817 } 3818 3819 STATIC int 3820 bcmi_trx_stk_port_modport_get(int unit, bcm_port_t ing_port, 3821 bcm_module_t dest_modid, int dest_port_max, 3822 bcm_port_t *dest_port_array, 3823 int *dest_port_count) 3824 { 3825 int modid_count, base_index; 3826 soc_profile_mem_t *profile; 3827 modport_map_entry_t *entry_p; 3828 pbmp_t pbmp; 3829 uint32 rval; 3830 int count, port; 3831 bcm_trunk_chip_info_t chip_info; 3832 bcm_trunk_t tid = -1; 3833 int profile_index = 0; 3834 bcmi_trx_modport_map_entry_t *trx_entry_p = NULL; 3835 int istrunk, dest; 3836 3837 if (!soc_feature(unit, 3838 soc_feature_modport_map_dest_is_hg_port_bitmap)) { 3839 return BCM_E_UNAVAIL; 3840 } 3841 3842 if (BCM_GPORT_IS_SET(ing_port)) { 3843 BCM_IF_ERROR_RETURN( 3844 bcm_esw_port_local_get(unit, ing_port, &ing_port)); 3845 } 3846 if (!SOC_PORT_VALID(unit, ing_port)) { 3847 return BCM_E_PORT; 3848 } 3849 if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) { 3850 return BCM_E_PARAM; 3851 } 3852 if (dest_port_max < 0 || 3853 ((dest_port_max > 0) && (dest_port_array == NULL)) || 3854 dest_port_count == NULL) { 3855 return BCM_E_PARAM; 3856 } 3857 3858 modid_count = SOC_MODID_MAX(unit) + 1; 3859 3860 if (modport_profile[unit] == NULL) { 3861 *dest_port_count = 0; 3862 return BCM_E_NOT_FOUND; 3863 } 3864 3865 profile = modport_profile[unit]; 3866 3867 BCM_IF_ERROR_RETURN(READ_MODPORT_MAP_SELr(unit, ing_port, &rval)); 3868 profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 3869 MODPORT_MAP_INDEX_UPPERf); 3870 base_index = (modid_count * profile_index); 3871 entry_p = SOC_PROFILE_MEM_ENTRY(unit, profile, modport_map_entry_t *, 3872 base_index + dest_modid); 3873 trx_entry_p = &TRX_MODPORT_MAP_PROFILE 3874 (unit, profile_index).entry_array[dest_modid]; 3875 3876 soc_mem_pbmp_field_get(unit, MODPORT_MAPm, entry_p, 3877 HIGIG_PORT_BITMAPf, &pbmp); 3878 count = 0; 3879 BCM_PBMP_ITER(pbmp, port) { 3880 if (dest_port_max > count) { 3881 istrunk = trx_entry_p->dest_istrunk[port]; 3882 dest = trx_entry_p->dest[port]; 3883 if (istrunk) { 3884 BCM_IF_ERROR_RETURN( 3885 bcm_esw_trunk_chip_info_get(unit, &chip_info)); 3886 tid = dest + chip_info.trunk_fabric_id_min; 3887 BCM_GPORT_TRUNK_SET(dest_port_array[count], tid); 3888 } else { 3889 dest_port_array[count] = dest; 3890 } 3891 } 3892 if ((dest_port_max != 0) && 3893 (count == dest_port_max)) { 3894 break; 3895 } 3896 count++; 3897 } 3898 *dest_port_count = count; 3899 3900 return *dest_port_count ? BCM_E_NONE : BCM_E_NOT_FOUND; 3901 } 3902 #endif /* BCM_TRX_SUPPORT */ 3903 3904 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 3905 3906 STATIC int 3907 _bcm_stk_port_modport_op(int unit, int op, bcm_port_t ing_port, 3908 bcm_module_t dest_modid, bcm_port_t *dest_port, 3909 int dest_port_count) 3910 { 3911 int modid_count, modid_min, modid_max; 3912 pbmp_t pbmp, hg_trunk_pbmp, hg_pbmp; 3913 int index; 3914 int tid; 3915 bcm_trunk_chip_info_t chip_info; 3916 bcm_trunk_member_t member; 3917 int member_count; 3918 bcm_port_t local_port; 3919 modport_map_entry_t entry; 3920 int rv; 3921 uint32 base_index; 3922 uint32 hg_pbmp32, new_hg_pbmp32; 3923 #if defined(BCM_TRX_SUPPORT) 3924 pbmp_t new_pbmp; 3925 soc_profile_mem_t *profile; 3926 modport_map_entry_t *entry_array; 3927 void *entries; 3928 uint32 rval; 3929 uint32 new_base_index; 3930 #endif /* BCM_TRX_SUPPORT */ 3931 3932 #if defined(BCM_TRX_SUPPORT) 3933 if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) { 3934 return bcmi_trx_stk_port_modport_op(unit, op, ing_port, dest_modid, 3935 dest_port, dest_port_count); 3936 } 3937 #endif /* BCM_TRX_SUPPORT */ 3938 3939 if (op <= 0 || op >= _BCM_STK_PORT_MODPORT_OP_COUNT) { 3940 return BCM_E_PARAM; 3941 } 3942 3943 if (BCM_GPORT_IS_SET(ing_port)) { 3944 BCM_IF_ERROR_RETURN( 3945 bcm_esw_port_local_get(unit, ing_port, &ing_port)); 3946 } 3947 3948 if (!SOC_PORT_VALID(unit, ing_port)) { 3949 return BCM_E_PORT; 3950 } 3951 3952 modid_count = SOC_MODID_MAX(unit) + 1; 3953 if (dest_modid == -1) { 3954 modid_min = 0; 3955 modid_max = modid_count - 1; 3956 } else { 3957 if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) { 3958 return BCM_E_PARAM; 3959 } 3960 modid_min = modid_max = dest_modid; 3961 } 3962 3963 if (dest_port_count > SOC_MAX_NUM_PORTS) { 3964 return BCM_E_INTERNAL; 3965 } 3966 3967 BCM_PBMP_CLEAR(pbmp); 3968 for (index = 0; index < dest_port_count; index++) { 3969 3970 if (BCM_GPORT_IS_TRUNK(dest_port[index])) { 3971 tid = SOC_GPORT_TRUNK_GET(dest_port[index]); 3972 3973 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 3974 if (chip_info.trunk_fabric_id_min < 0 || 3975 tid < chip_info.trunk_fabric_id_min || 3976 tid > chip_info.trunk_fabric_id_max) { 3977 return BCM_E_PARAM; 3978 } 3979 3980 /* Get Higig trunk group port bitmap */ 3981 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, tid, NULL, 3982 1, &member, &member_count)); 3983 if (member_count == 0) { 3984 /* No ports have been added to the Higig trunk group */ 3985 return BCM_E_PARAM; 3986 } 3987 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, 3988 member.gport, &local_port)); 3989 BCM_PBMP_PORT_SET(hg_trunk_pbmp, local_port); 3990 BCM_IF_ERROR_RETURN 3991 (bcm_esw_trunk_bitmap_expand(unit, &hg_trunk_pbmp)); 3992 BCM_PBMP_OR(pbmp, hg_trunk_pbmp); 3993 3994 } else { 3995 if (!SOC_PORT_VALID(unit, dest_port[index])) { 3996 return BCM_E_PORT; 3997 } 3998 3999 if (dest_port[index] == CMIC_PORT(unit) && 4000 BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TRIUMPH) { 4001 return BCM_E_PORT; 4002 } 4003 4004 BCM_PBMP_PORT_ADD(pbmp, dest_port[index]); 4005 } 4006 } 4007 4008 #if defined(BCM_TRX_SUPPORT) 4009 4010 if (SOC_IS_TR_VL(unit)) { 4011 /* Profile style MODPORT MAP bitmap table */ 4012 if (modport_profile[unit] == NULL) { 4013 _bcm_stk_modport_profile_init(unit); 4014 } 4015 profile = modport_profile[unit]; 4016 4017 if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit) || 4018 SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit) || 4019 SOC_IS_HURRICANE2(unit)) { 4020 BCM_IF_ERROR_RETURN 4021 (soc_xgs3_bitmap_to_higig_bitmap(unit, pbmp, &hg_pbmp)); 4022 BCM_PBMP_ASSIGN(pbmp, hg_pbmp); 4023 } 4024 4025 entry_array = sal_alloc(sizeof(modport_map_entry_t) * modid_count, 4026 "modport_map_entry"); 4027 if (entry_array == NULL) { 4028 return BCM_E_MEMORY; 4029 } 4030 4031 soc_mem_lock(unit, MODPORT_MAPm); 4032 rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval); 4033 if (BCM_FAILURE(rv)) { 4034 soc_mem_unlock(unit, MODPORT_MAPm); 4035 sal_free(entry_array); 4036 return rv; 4037 } 4038 base_index = modid_count * 4039 soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 4040 MODPORT_MAP_INDEX_UPPERf); 4041 for (index = 0; index < modid_count; index++) { 4042 sal_memcpy(&entry_array[index], 4043 SOC_PROFILE_MEM_ENTRY(unit, profile, void *, 4044 base_index + index), 4045 sizeof(modport_map_entry_t)); 4046 } 4047 for (index = modid_min; index <= modid_max; index++) { 4048 switch (op) { 4049 case _BCM_STK_PORT_MODPORT_OP_SET: 4050 BCM_PBMP_ASSIGN(new_pbmp, pbmp); 4051 break; 4052 case _BCM_STK_PORT_MODPORT_OP_ADD: 4053 soc_mem_pbmp_field_get(unit, MODPORT_MAPm, &entry_array[index], 4054 HIGIG_PORT_BITMAPf, &new_pbmp); 4055 BCM_PBMP_OR(new_pbmp, pbmp); 4056 break; 4057 case _BCM_STK_PORT_MODPORT_OP_DELETE: 4058 soc_mem_pbmp_field_get(unit, MODPORT_MAPm, &entry_array[index], 4059 HIGIG_PORT_BITMAPf, &new_pbmp); 4060 BCM_PBMP_REMOVE(new_pbmp, pbmp); 4061 break; 4062 /*default case is must in order to avoid compilatioin error */ 4063 /* coverity[dead_error_begin] */ 4064 default: 4065 soc_mem_unlock(unit, MODPORT_MAPm); 4066 sal_free(entry_array); 4067 return BCM_E_INTERNAL; 4068 } 4069 soc_mem_pbmp_field_set(unit, MODPORT_MAPm, &entry_array[index], 4070 HIGIG_PORT_BITMAPf, &new_pbmp); 4071 } 4072 entries = entry_array; 4073 rv = soc_profile_mem_add(unit, profile, &entries, modid_count, 4074 &new_base_index); 4075 if (BCM_SUCCESS(rv)) { 4076 soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval, 4077 MODPORT_MAP_INDEX_UPPERf, 4078 new_base_index / modid_count); 4079 rv = WRITE_MODPORT_MAP_SELr(unit, ing_port, rval); 4080 } 4081 if (BCM_SUCCESS(rv)) { 4082 rv = soc_profile_mem_delete(unit, profile, base_index); 4083 } 4084 soc_mem_unlock(unit, MODPORT_MAPm); 4085 sal_free(entry_array); 4086 } else 4087 #endif /* BCM_TRX_SUPPORT */ 4088 4089 if (SOC_IS_HBX(unit)) { 4090 /* Per port style MODPORT MAP bitmap table */ 4091 BCM_IF_ERROR_RETURN 4092 (soc_xgs3_bitmap_to_higig_bitmap(unit, pbmp, &hg_pbmp)); 4093 hg_pbmp32 = SOC_PBMP_WORD_GET(hg_pbmp, 0); 4094 base_index = ing_port * modid_count; 4095 4096 rv = BCM_E_NONE; 4097 soc_mem_lock(unit, MODPORT_MAPm); 4098 for (index = modid_min; index <= modid_max; index++) { 4099 rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, base_index + index, 4100 &entry); 4101 if (BCM_FAILURE(rv)) { 4102 soc_mem_unlock(unit, MODPORT_MAPm); 4103 return rv; 4104 } 4105 switch (op) { 4106 case _BCM_STK_PORT_MODPORT_OP_SET: 4107 new_hg_pbmp32 = hg_pbmp32; 4108 break; 4109 case _BCM_STK_PORT_MODPORT_OP_ADD: 4110 new_hg_pbmp32 = 4111 soc_mem_field32_get(unit, MODPORT_MAPm, &entry, 4112 HIGIG_PORT_BITMAPf); 4113 new_hg_pbmp32 |= hg_pbmp32; 4114 break; 4115 case _BCM_STK_PORT_MODPORT_OP_DELETE: 4116 new_hg_pbmp32 = 4117 soc_mem_field32_get(unit, MODPORT_MAPm, &entry, 4118 HIGIG_PORT_BITMAPf); 4119 new_hg_pbmp32 &= ~hg_pbmp32; 4120 break; 4121 /*default case is must in order to avoid compilatioin error */ 4122 /* coverity[dead_error_begin] */ 4123 default: 4124 soc_mem_unlock(unit, MODPORT_MAPm); 4125 return BCM_E_INTERNAL; 4126 } 4127 soc_mem_field32_set(unit, MODPORT_MAPm, &entry, 4128 HIGIG_PORT_BITMAPf, new_hg_pbmp32); 4129 rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ANY, base_index + index, 4130 &entry); 4131 } 4132 soc_mem_unlock(unit, MODPORT_MAPm); 4133 4134 } else { 4135 rv = BCM_E_UNAVAIL; 4136 } 4137 4138 return rv; 4139 } 4140 4141 STATIC int 4142 _bcm_stk_port_modport_get(int unit, bcm_port_t ing_port, 4143 bcm_module_t dest_modid, int dest_port_max, 4144 bcm_port_t *dest_port_array, 4145 int *dest_port_count) 4146 { 4147 uint32 hg_pbmp; 4148 modport_map_entry_t entry; 4149 int modid_count, base_index; 4150 #if defined(BCM_TRX_SUPPORT) 4151 soc_profile_mem_t *profile; 4152 modport_map_entry_t *entry_p; 4153 pbmp_t pbmp; 4154 uint32 rval; 4155 int count, port; 4156 #endif /* BCM_TRX_SUPPORT */ 4157 4158 #if defined(BCM_TRX_SUPPORT) 4159 if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) { 4160 return bcmi_trx_stk_port_modport_get(unit, ing_port, dest_modid, 4161 dest_port_max, dest_port_array, 4162 dest_port_count); 4163 } 4164 #endif /* BCM_TRX_SUPPORT */ 4165 4166 if (BCM_GPORT_IS_SET(ing_port)) { 4167 BCM_IF_ERROR_RETURN( 4168 bcm_esw_port_local_get(unit, ing_port, &ing_port)); 4169 } 4170 if (!SOC_PORT_VALID(unit, ing_port)) { 4171 return BCM_E_PORT; 4172 } 4173 if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) { 4174 return BCM_E_PARAM; 4175 } 4176 if (dest_port_max < 0 || 4177 ((dest_port_max > 0) && (dest_port_array == NULL)) || 4178 dest_port_count == NULL) { 4179 return BCM_E_PARAM; 4180 } 4181 4182 modid_count = SOC_MODID_MAX(unit) + 1; 4183 4184 #if defined(BCM_TRX_SUPPORT) 4185 4186 if (SOC_IS_TR_VL(unit)) { 4187 if (modport_profile[unit] == NULL) { 4188 *dest_port_count = 0; 4189 return BCM_E_NOT_FOUND; 4190 } 4191 4192 profile = modport_profile[unit]; 4193 4194 BCM_IF_ERROR_RETURN(READ_MODPORT_MAP_SELr(unit, ing_port, &rval)); 4195 base_index = modid_count * 4196 soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 4197 MODPORT_MAP_INDEX_UPPERf); 4198 entry_p = SOC_PROFILE_MEM_ENTRY(unit, profile, modport_map_entry_t *, 4199 base_index + dest_modid); 4200 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 4201 SOC_IS_VALKYRIE2(unit)) { 4202 soc_mem_pbmp_field_get(unit, MODPORT_MAPm, entry_p, 4203 HIGIG_PORT_BITMAPf, &pbmp); 4204 count = 0; 4205 BCM_PBMP_ITER(pbmp, port) { 4206 if (dest_port_max > count) { 4207 dest_port_array[count] = port; 4208 } 4209 if ((dest_port_max != 0) && 4210 (count == dest_port_max)) { 4211 break; 4212 } 4213 count++; 4214 } 4215 *dest_port_count = count; 4216 } else { 4217 hg_pbmp = soc_mem_field32_get(unit, MODPORT_MAPm, entry_p, 4218 HIGIG_PORT_BITMAPf); 4219 BCM_IF_ERROR_RETURN 4220 (soc_xgs3_higig_bitmap_to_port_all(unit, hg_pbmp, 4221 dest_port_max, 4222 dest_port_array, 4223 dest_port_count)); 4224 } 4225 } else 4226 #endif /* BCM_TRX_SUPPORT */ 4227 4228 if (SOC_IS_HBX(unit)) { 4229 base_index = ing_port * modid_count; 4230 BCM_IF_ERROR_RETURN 4231 (READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, base_index + dest_modid, 4232 &entry)); 4233 hg_pbmp = soc_mem_field32_get(unit, MODPORT_MAPm, &entry, 4234 HIGIG_PORT_BITMAPf); 4235 BCM_IF_ERROR_RETURN 4236 (soc_xgs3_higig_bitmap_to_port_all(unit, hg_pbmp, dest_port_max, 4237 dest_port_array, 4238 dest_port_count)); 4239 } else { 4240 return BCM_E_UNAVAIL; 4241 } 4242 4243 return *dest_port_count ? BCM_E_NONE : BCM_E_NOT_FOUND; 4244 } 4245 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 4246 4247 #ifdef BCM_TRIUMPH_SUPPORT 4248 /* 4249 * Function: 4250 * _bcm_esw_tr_trunk_override_ucast_set 4251 * Purpose: 4252 * Use the memory profile mechanish to set/clear 4253 * HiGig Trunk Override bit. 4254 * Parameters: 4255 * unit - SOC unit 4256 * port - Ingress Port 4257 * tgid - Trunk ID 4258 * modid - Module ID 4259 * enable - HighGig Trunk Override set/clear flag. 4260 * Returns: 4261 * BCM_E_XXX 4262 */ 4263 int 4264 _bcm_esw_tr_trunk_override_ucast_set(int unit, bcm_port_t port, 4265 bcm_trunk_t hgtid, int modid, int enable) 4266 { 4267 int i, rv = BCM_E_NONE; 4268 soc_profile_mem_t *profile; 4269 modport_map_entry_t *modport_entry; 4270 uint32 profile_index_old, profile_index_new, rval, hgo_bitmap, hgo_bit; 4271 int modid_count; 4272 uint32 base_index_old, base_index_new; 4273 #if defined(BCM_TRX_SUPPORT) 4274 bcmi_trx_modport_map_entry_t *trx_entry_array = NULL; 4275 int ref_count; 4276 int dest_is_hg_pbmp = 0; 4277 #endif /* BCM_TRX_SUPPORT */ 4278 4279 if (modport_profile[unit] == NULL) { 4280 _bcm_stk_modport_profile_init(unit); 4281 } 4282 profile = modport_profile[unit]; 4283 4284 modid_count = SOC_MODID_MAX(unit) + 1; 4285 modport_entry = sal_alloc(sizeof(modport_map_entry_t) * modid_count, "modport_map_entry"); 4286 if (modport_entry == NULL) { 4287 return BCM_E_MEMORY; 4288 } 4289 4290 #if defined(BCM_TRX_SUPPORT) 4291 if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) { 4292 trx_entry_array = 4293 sal_alloc((sizeof(bcmi_trx_modport_map_entry_t) * modid_count), 4294 "trx_modport_map_entry"); 4295 if (trx_entry_array == NULL) { 4296 sal_free(modport_entry); 4297 return BCM_E_MEMORY; 4298 } 4299 dest_is_hg_pbmp = 1; 4300 } 4301 #endif /* BCM_TRX_SUPPORT */ 4302 4303 soc_mem_lock(unit, MODPORT_MAPm); 4304 4305 rv = READ_MODPORT_MAP_SELr(unit, port, &rval); 4306 if (BCM_FAILURE(rv)) { 4307 soc_mem_unlock(unit, MODPORT_MAPm); 4308 sal_free(modport_entry); 4309 #if defined(BCM_TRX_SUPPORT) 4310 if (dest_is_hg_pbmp) { 4311 sal_free(trx_entry_array); 4312 } 4313 #endif /* BCM_TRX_SUPPORT */ 4314 return rv; 4315 } 4316 4317 profile_index_old = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 4318 MODPORT_MAP_INDEX_UPPERf); 4319 base_index_old = modid_count * profile_index_old; 4320 for (i = 0; i < modid_count; i++) { 4321 sal_memcpy(&modport_entry[i], 4322 SOC_PROFILE_MEM_ENTRY(unit, profile, void *, 4323 base_index_old + i), 4324 sizeof(modport_map_entry_t)); 4325 #if defined(BCM_TRX_SUPPORT) 4326 if (dest_is_hg_pbmp) { 4327 sal_memcpy(&trx_entry_array[i], 4328 &TRX_MODPORT_MAP_PROFILE 4329 (unit, profile_index_old).entry_array[i], 4330 sizeof(bcmi_trx_modport_map_entry_t)); 4331 } 4332 #endif /* BCM_TRX_SUPPORT */ 4333 } 4334 4335 hgo_bitmap = soc_MODPORT_MAPm_field32_get(unit, &modport_entry[modid], HIGIG_TRUNK_OVERRIDEf); 4336 hgo_bit = 1 << hgtid; 4337 if (enable) { 4338 hgo_bitmap |= hgo_bit; 4339 } else { 4340 hgo_bitmap &= ~hgo_bit; 4341 } 4342 soc_MODPORT_MAPm_field32_set(unit, &modport_entry[modid], 4343 HIGIG_TRUNK_OVERRIDEf, 4344 hgo_bitmap); 4345 4346 rv = soc_profile_mem_add(unit, profile, 4347 (void *)&modport_entry, modid_count, 4348 &base_index_new); 4349 if (BCM_SUCCESS(rv)) { 4350 profile_index_new = (base_index_new / modid_count); 4351 soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval, 4352 MODPORT_MAP_INDEX_UPPERf, 4353 profile_index_new); 4354 rv = WRITE_MODPORT_MAP_SELr(unit, port, rval); 4355 } 4356 if (BCM_SUCCESS(rv)) { 4357 #if defined(BCM_TRX_SUPPORT) 4358 if (dest_is_hg_pbmp) { 4359 sal_memcpy( 4360 TRX_MODPORT_MAP_PROFILE 4361 (unit, profile_index_new).entry_array, 4362 trx_entry_array, 4363 (sizeof(bcmi_trx_modport_map_entry_t) * modid_count)); 4364 TRX_MODPORT_MAP_PROFILE(unit, profile_index_new).ref_count++; 4365 } 4366 #endif /* BCM_TRX_SUPPORT */ 4367 rv = soc_profile_mem_delete(unit, profile, base_index_old); 4368 #if defined(BCM_TRX_SUPPORT) 4369 if (dest_is_hg_pbmp) { 4370 if (BCM_SUCCESS(rv)) { 4371 if (TRX_MODPORT_MAP_PROFILE 4372 (unit, profile_index_old).ref_count >= 1) { 4373 TRX_MODPORT_MAP_PROFILE(unit, 4374 profile_index_old).ref_count--; 4375 ref_count = 4376 TRX_MODPORT_MAP_PROFILE 4377 (unit, profile_index_old).ref_count; 4378 /* Clear old profile when ref_count = 0 */ 4379 if (ref_count == 0) { 4380 sal_memset( 4381 TRX_MODPORT_MAP_PROFILE 4382 (unit, profile_index_old).entry_array, 4383 0, 4384 (sizeof(bcmi_trx_modport_map_entry_t) * 4385 modid_count)); 4386 } 4387 } 4388 } 4389 } 4390 } 4391 #endif /* BCM_TRX_SUPPORT */ 4392 soc_mem_unlock(unit, MODPORT_MAPm); 4393 sal_free(modport_entry); 4394 #if defined(BCM_TRX_SUPPORT) 4395 if (dest_is_hg_pbmp) { 4396 sal_free(trx_entry_array); 4397 } 4398 #endif /* BCM_TRX_SUPPORT */ 4399 4400 return rv; 4401 } 4402 4403 /* 4404 * Function: 4405 * _bcm_esw_tr_trunk_override_ucast_get 4406 * Purpose: 4407 * Use the memory profile mechanish to get 4408 * HiGig Trunk Override bit. 4409 * Parameters: 4410 * unit - SOC unit 4411 * port - Ingress Port 4412 * tgid - Trunk ID 4413 * modid - Module ID 4414 * enable - HighGig Trunk Override set/clear flag. 4415 * Returns: 4416 * BCM_E_XXX 4417 */ 4418 int 4419 _bcm_esw_tr_trunk_override_ucast_get(int unit, bcm_port_t port, 4420 bcm_trunk_t hgtid, int modid, int *enable) 4421 { 4422 int rv = BCM_E_NONE; 4423 soc_profile_mem_t *profile; 4424 modport_map_entry_t *modport_entry; 4425 uint32 profile_index, rval, hgo_bitmap, hgo_bit; 4426 int modid_count; 4427 4428 if (modport_profile[unit] == NULL) { 4429 return BCM_E_NOT_FOUND; 4430 } 4431 4432 profile = modport_profile[unit]; 4433 modid_count = SOC_MODID_MAX(unit) + 1; 4434 modport_entry = sal_alloc(sizeof(modport_map_entry_t), "modport_map_entry"); 4435 if (modport_entry == NULL) { 4436 return BCM_E_MEMORY; 4437 } 4438 4439 rv = READ_MODPORT_MAP_SELr(unit, port, &rval); 4440 if (BCM_FAILURE(rv)) { 4441 soc_mem_unlock(unit, MODPORT_MAPm); 4442 sal_free(modport_entry); 4443 return rv; 4444 } 4445 4446 profile_index = modid_count * 4447 soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 4448 MODPORT_MAP_INDEX_UPPERf); 4449 4450 sal_memcpy(modport_entry, SOC_PROFILE_MEM_ENTRY(unit, profile, void *, 4451 profile_index + modid), sizeof(modport_map_entry_t)); 4452 4453 hgo_bitmap = soc_MODPORT_MAPm_field32_get(unit, modport_entry, 4454 HIGIG_TRUNK_OVERRIDEf); 4455 hgo_bit = 1 << hgtid; 4456 *enable = (hgo_bitmap & hgo_bit) ? 1 : 0; 4457 4458 sal_free(modport_entry); 4459 4460 return rv; 4461 } 4462 #endif /* BCM_TRIUMPH_SUPPORT */ 4463 4464 4465 /* 4466 * Function: 4467 * bcm_stk_modport_set 4468 * Purpose: 4469 * Set the port in MODPORT entry for modid 4470 * Parameters: 4471 * unit - SOC unit# 4472 * modid - module id 4473 * port - port number 4474 * Returns: 4475 * BCM_E_XXX 4476 * Note: 4477 * Supported by all devices except Strata 4478 */ 4479 4480 int 4481 bcm_esw_stk_modport_set(int unit, int modid, bcm_port_t port) 4482 { 4483 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 4484 4485 LOG_INFO(BSL_LS_BCM_STK, 4486 (BSL_META_U(unit, 4487 "STK %d: modport set: modid %d to port %d\n"), 4488 unit, 4489 modid, port)); 4490 4491 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 4492 return BCM_E_PARAM; 4493 } 4494 if (BCM_GPORT_IS_SET(port) && !BCM_GPORT_IS_TRUNK(port)) { 4495 BCM_IF_ERROR_RETURN( 4496 bcm_esw_port_local_get(unit, port, &port)); 4497 } 4498 4499 switch (BCM_CHIP_FAMILY(unit)) { 4500 4501 #if defined(BCM_FIREBOLT_SUPPORT) 4502 case BCM_FAMILY_FIREBOLT: 4503 { 4504 modport_map_entry_t uc; 4505 uint32 hg_pbm; 4506 int rv; 4507 4508 if (!SOC_PORT_VALID(unit, port)) { 4509 return BCM_E_PORT; 4510 } 4511 4512 /* Convert port to HG bitmap for FBX devices other than Raven */ 4513 /* For Raven, use the absolute bitmap */ 4514 if (SOC_IS_RAVEN(unit)) { 4515 if (IS_ST_PORT(unit, port) || IS_CPU_PORT(unit, port)) { 4516 hg_pbm = 1 << port; 4517 rv = BCM_E_NONE; 4518 } else { 4519 rv = BCM_E_PORT; 4520 } 4521 } else if (SOC_IS_HAWKEYE(unit)) { 4522 return BCM_E_UNAVAIL; 4523 } else { 4524 rv = soc_xgs3_port_to_higig_bitmap(unit, port, &hg_pbm); 4525 } 4526 if (rv != BCM_E_NONE) { 4527 return BCM_E_PORT; 4528 } 4529 4530 soc_mem_lock(unit, MODPORT_MAPm); 4531 rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc); 4532 if (rv >= 0) { 4533 soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf, 4534 hg_pbm); 4535 rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, modid, &uc); 4536 } 4537 soc_mem_unlock(unit, MODPORT_MAPm); 4538 return rv; 4539 } 4540 #endif /* BCM_FIREBOLT_SUPPORT */ 4541 4542 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 4543 case BCM_FAMILY_BRADLEY: 4544 case BCM_FAMILY_HUMV: 4545 case BCM_FAMILY_SCORPION: 4546 case BCM_FAMILY_CONQUEROR: 4547 case BCM_FAMILY_TRIUMPH: 4548 case BCM_FAMILY_TRIUMPH2: 4549 { 4550 bcm_port_t ing_port; 4551 PBMP_ALL_ITER(unit, ing_port) { 4552 BCM_IF_ERROR_RETURN 4553 (_bcm_stk_port_modport_op(unit, 4554 _BCM_STK_PORT_MODPORT_OP_SET, 4555 ing_port, modid, &port, 1)); 4556 } 4557 break; 4558 } 4559 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 4560 4561 #ifdef BCM_TRIDENT_SUPPORT 4562 case BCM_FAMILY_TITAN: 4563 case BCM_FAMILY_TRIDENT: 4564 case BCM_FAMILY_KATANA: 4565 { 4566 bcm_port_t ing_port; 4567 bcm_pbmp_t all_pbmp; 4568 4569 BCM_PBMP_CLEAR(all_pbmp); 4570 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 4571 4572 #if defined(BCM_KATANA2_SUPPORT) 4573 if (soc_feature(unit, soc_feature_linkphy_coe) || 4574 soc_feature(unit, soc_feature_subtag_coe)) { 4575 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 4576 } 4577 if (SOC_IS_KATANA2(unit)) { 4578 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, 4579 &all_pbmp)); 4580 } 4581 #endif 4582 PBMP_ITER(all_pbmp, ing_port) { 4583 BCM_IF_ERROR_RETURN(bcm_td_stk_port_modport_op(unit, 4584 _BCM_STK_PORT_MODPORT_OP_SET, 4585 ing_port, modid, &port, 1)); 4586 } 4587 break; 4588 } 4589 #endif /* BCM_TRIDENT_SUPPORT */ 4590 4591 #if defined(BCM_XGS_FABRIC_SUPPORT) 4592 case BCM_FAMILY_HERCULES: 4593 case BCM_FAMILY_HERCULES15: 4594 { 4595 int ing_port; 4596 bcm_pbmp_t pbmp; 4597 4598 if (!SOC_PORT_VALID(unit, port)) { 4599 BCM_PBMP_CLEAR(pbmp); 4600 } else { 4601 BCM_PBMP_PORT_SET(pbmp, port); 4602 } 4603 4604 PBMP_HG_ITER(unit, ing_port) { 4605 BCM_IF_ERROR_RETURN(bcm_esw_stk_ucbitmap_set(unit, ing_port, 4606 modid, pbmp)); 4607 } 4608 4609 return BCM_E_NONE; 4610 } 4611 #endif 4612 4613 default: 4614 return BCM_E_UNAVAIL; 4615 } 4616 4617 return BCM_E_NONE; 4618 } 4619 4620 /* 4621 * Function: 4622 * bcm_stk_modport_get_all 4623 * Purpose: 4624 * Get all ports in MODPORT entry for modid 4625 * Parameters: 4626 * unit - (IN) Device Number 4627 * modid - (IN) module id 4628 * port_max - (IN) Maximum number of ports in array 4629 * port_array - (OUT) Array of ports 4630 * port_count - (OUT) Number of ports returned in array 4631 * Returns: 4632 * BCM_E_XXX 4633 * Note: 4634 * Supported by all devices except Strata and Hawkeye 4635 */ 4636 int 4637 bcm_esw_stk_modport_get_all(int unit, 4638 int modid, 4639 int port_max, 4640 bcm_port_t *port_array, 4641 int *port_count) 4642 { 4643 int tmp_port, mymodid; 4644 int count, isGport; 4645 _bcm_gport_dest_t gport_st; 4646 4647 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 4648 4649 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 4650 return BCM_E_PARAM; 4651 } 4652 4653 if (port_max < 0 && port_array == NULL) { 4654 return BCM_E_PARAM; 4655 } 4656 4657 count = 0; 4658 BCM_IF_ERROR_RETURN( 4659 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 4660 /* return code intentionaly ignored to support devices where mymodid */ 4661 /* was not assigned */ 4662 (void) bcm_esw_stk_my_modid_get(unit, &mymodid); 4663 4664 switch (BCM_CHIP_FAMILY(unit)) { 4665 4666 #if defined(BCM_FIREBOLT_SUPPORT) 4667 case BCM_FAMILY_FIREBOLT: 4668 { 4669 modport_map_entry_t uc; 4670 int rv; 4671 int hg_reg; 4672 4673 SOC_IF_ERROR_RETURN 4674 (READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc)); 4675 hg_reg = soc_MODPORT_MAPm_field32_get(unit, &uc, 4676 HIGIG_PORT_BITMAPf); 4677 4678 /* For Raven, hg_reg directly corresponds to the physical port */ 4679 if (SOC_IS_RAVEN(unit)) { 4680 int port; 4681 4682 port = 0; 4683 while (hg_reg != 0) { 4684 if (hg_reg & 1) { 4685 if (count < port_max) { 4686 tmp_port = port; 4687 if (TRUE == isGport) { 4688 if (BCM_MODID_INVALID == mymodid) { 4689 gport_st.gport_type = _SHR_GPORT_TYPE_DEVPORT; 4690 } else { 4691 gport_st.gport_type = _SHR_GPORT_TYPE_MODPORT; 4692 gport_st.modid = mymodid; 4693 } 4694 gport_st.port = tmp_port; 4695 BCM_IF_ERROR_RETURN( 4696 _bcm_esw_gport_construct(unit, &gport_st, 4697 &tmp_port)); 4698 } 4699 port_array[count] = tmp_port; 4700 } 4701 count++; 4702 if ((port_max != 0) && 4703 (port_max == count)) { 4704 break; 4705 } 4706 } 4707 port++; 4708 hg_reg >>= 1; 4709 } 4710 4711 if (port_count) { 4712 *port_count = count; 4713 } 4714 4715 return (count > 0) ? BCM_E_NONE : BCM_E_NOT_FOUND; 4716 4717 } else if (SOC_IS_HAWKEYE(unit)) { 4718 rv = BCM_E_UNAVAIL; 4719 } else { 4720 rv = soc_xgs3_higig_bitmap_to_port_all(unit, 4721 hg_reg, 4722 port_max, 4723 port_array, 4724 &count); 4725 if (BCM_SUCCESS(rv) && TRUE == isGport) { 4726 int i; 4727 4728 for (i = 0; i < count; i++) { 4729 tmp_port = port_array[i]; 4730 if (BCM_MODID_INVALID == mymodid) { 4731 gport_st.gport_type = _SHR_GPORT_TYPE_DEVPORT; 4732 } else { 4733 gport_st.gport_type = _SHR_GPORT_TYPE_MODPORT; 4734 gport_st.modid = mymodid; 4735 } 4736 gport_st.port = tmp_port; 4737 BCM_IF_ERROR_RETURN( 4738 _bcm_esw_gport_construct(unit, &gport_st, 4739 &tmp_port)); 4740 port_array[i] = tmp_port; 4741 } 4742 } 4743 4744 if (port_count) { 4745 *port_count = count; 4746 } 4747 } 4748 4749 return rv; 4750 } 4751 #endif /* BCM_FIREBOLT_SUPPORT */ 4752 4753 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 4754 case BCM_FAMILY_BRADLEY: 4755 case BCM_FAMILY_HUMV: 4756 case BCM_FAMILY_SCORPION: 4757 case BCM_FAMILY_CONQUEROR: 4758 case BCM_FAMILY_TRIUMPH: 4759 case BCM_FAMILY_TRIUMPH2: 4760 case BCM_FAMILY_TITAN: 4761 case BCM_FAMILY_TRIDENT: 4762 case BCM_FAMILY_KATANA: 4763 { 4764 bcm_port_t ing_port; 4765 int count, rv; 4766 bcm_pbmp_t all_pbmp; 4767 4768 BCM_PBMP_CLEAR(all_pbmp); 4769 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 4770 4771 #if defined(BCM_KATANA2_SUPPORT) 4772 if (soc_feature(unit, soc_feature_linkphy_coe) || 4773 soc_feature(unit, soc_feature_subtag_coe)) { 4774 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 4775 } 4776 if (SOC_IS_KATANA2(unit)) { 4777 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, 4778 &all_pbmp)); 4779 } 4780 #endif 4781 4782 PBMP_ITER(all_pbmp, ing_port) { 4783 #ifdef BCM_TRIDENT_SUPPORT 4784 if ((BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TRIDENT) || 4785 (BCM_CHIP_FAMILY(unit) == BCM_FAMILY_KATANA) || 4786 (BCM_CHIP_FAMILY(unit) == BCM_FAMILY_TITAN)) { 4787 rv = bcm_td_stk_port_modport_get(unit, ing_port, modid, 4788 port_max, port_array, &count); 4789 } else 4790 #endif /* BCM_TRIDENT_SUPPORT */ 4791 { 4792 rv =_bcm_stk_port_modport_get(unit, ing_port, modid, 4793 port_max, port_array, &count); 4794 } 4795 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) { 4796 return rv; 4797 } 4798 if ((port_max != 0) && 4799 (port_max < count)) { 4800 count = port_max; 4801 } 4802 if (port_count) { 4803 *port_count = count; 4804 } 4805 if ((TRUE == isGport) && (port_array != NULL)) { 4806 int i; 4807 4808 for (i = 0; i < count; i++) { 4809 if (BCM_GPORT_IS_TRUNK(port_array[i])) { 4810 continue; 4811 } 4812 tmp_port = port_array[i]; 4813 if (BCM_MODID_INVALID == mymodid) { 4814 gport_st.gport_type = _SHR_GPORT_TYPE_DEVPORT; 4815 } else { 4816 gport_st.gport_type = _SHR_GPORT_TYPE_MODPORT; 4817 gport_st.modid = mymodid; 4818 } 4819 gport_st.port = tmp_port; 4820 BCM_IF_ERROR_RETURN( 4821 _bcm_esw_gport_construct(unit, &gport_st, 4822 &tmp_port)); 4823 port_array[i] = tmp_port; 4824 } 4825 } 4826 4827 return rv; 4828 } 4829 break; 4830 } 4831 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 4832 4833 #if defined(BCM_XGS_FABRIC_SUPPORT) 4834 case BCM_FAMILY_HERCULES: 4835 case BCM_FAMILY_HERCULES15: 4836 { 4837 int ing_port; 4838 bcm_pbmp_t pbmp; 4839 4840 /* 4841 * Iterate through the ingress ports. 4842 * Find the first ingress port with a non-null bitmap 4843 * for the modid; return the first port in that bitmap. 4844 */ 4845 4846 PBMP_HG_ITER(unit, ing_port) { 4847 BCM_IF_ERROR_RETURN(bcm_esw_stk_ucbitmap_get(unit, ing_port, 4848 modid, &pbmp)); 4849 if (BCM_PBMP_NOT_NULL(pbmp)) { 4850 bcm_port_t port; 4851 4852 BCM_PBMP_ITER(pbmp, port) { 4853 if (count < port_max) { 4854 tmp_port = port; 4855 if (TRUE == isGport) { 4856 if (BCM_MODID_INVALID == mymodid) { 4857 gport_st.gport_type = _SHR_GPORT_TYPE_DEVPORT; 4858 } else { 4859 gport_st.gport_type = _SHR_GPORT_TYPE_MODPORT; 4860 gport_st.modid = mymodid; 4861 } 4862 gport_st.port = tmp_port; 4863 BCM_IF_ERROR_RETURN( 4864 _bcm_esw_gport_construct(unit, &gport_st, 4865 &tmp_port)); 4866 } 4867 port_array[count] = tmp_port; 4868 } 4869 if ((port_max != 0) && 4870 (port_max == count)) { 4871 break; 4872 } 4873 count++; 4874 } 4875 break; 4876 } 4877 } 4878 4879 if (port_count) { 4880 *port_count = count; 4881 } 4882 4883 return (count > 0) ? BCM_E_NONE : BCM_E_NOT_FOUND; 4884 } 4885 #endif 4886 4887 default: 4888 return BCM_E_UNAVAIL; 4889 } 4890 4891 return BCM_E_NONE; 4892 } 4893 4894 /* 4895 * Function: 4896 * bcm_stk_modport_get 4897 * Purpose: 4898 * Get the port in MODPORT entry for modid 4899 * Parameters: 4900 * unit - SOC unit# 4901 * modid - module id 4902 * port - (OUT) port number 4903 * Returns: 4904 * BCM_E_XXX 4905 * Note: 4906 * Supported by all devices except Strata 4907 */ 4908 4909 int 4910 bcm_esw_stk_modport_get(int unit, int modid, bcm_port_t *port) 4911 { 4912 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 4913 4914 if (port == NULL) { 4915 return BCM_E_PARAM; 4916 } 4917 4918 *port = -1; 4919 return bcm_esw_stk_modport_get_all(unit, modid, 1, port, NULL); 4920 } 4921 4922 4923 /* 4924 * Function: 4925 * bcm_stk_modport_clear 4926 * Purpose: 4927 * Clear entry in MODPORT table 4928 * Parameters: 4929 * unit - SOC unit# 4930 * modid - module id 4931 * Returns: 4932 * BCM_E_XXX 4933 * Note: 4934 * Supported by all devices except Strata 4935 */ 4936 4937 int 4938 bcm_esw_stk_modport_clear(int unit, int modid) 4939 { 4940 bcm_pbmp_t pbmp; 4941 int port; 4942 int rv; 4943 int use_modport_set; 4944 bcm_pbmp_t all_pbmp; 4945 4946 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 4947 4948 LOG_VERBOSE(BSL_LS_BCM_STK, 4949 (BSL_META_U(unit, 4950 "STK %d: Clearing mod port info of modid %d.\n"), 4951 unit, modid)); 4952 4953 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 4954 return BCM_E_PARAM; 4955 } 4956 4957 /* First try to clear the modport bitmap, if available */ 4958 4959 rv = BCM_E_INTERNAL; 4960 use_modport_set = FALSE; 4961 BCM_PBMP_CLEAR(pbmp); 4962 4963 BCM_PBMP_CLEAR(all_pbmp); 4964 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 4965 4966 #if defined(BCM_KATANA2_SUPPORT) 4967 if (soc_feature(unit, soc_feature_linkphy_coe) || 4968 soc_feature(unit, soc_feature_subtag_coe)) { 4969 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 4970 } 4971 if (SOC_IS_KATANA2(unit)) { 4972 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, 4973 &all_pbmp)); 4974 } 4975 #endif 4976 4977 /* Go though all ports, because on different devices, some or all 4978 of their ports may have a modport map. We'll be conservative 4979 and clear everything; this will catch cases like having stack 4980 ports with modport map settings that get converted into 4981 non-stack ports still getting those modport maps cleared. */ 4982 PBMP_ITER(all_pbmp, port) { 4983 rv = bcm_esw_stk_ucbitmap_set(unit, port, modid, pbmp); 4984 if (rv == BCM_E_NONE) { 4985 /* Cleared the modport map so modport_set not needed, 4986 keep going */ 4987 } else if (rv == BCM_E_UNAVAIL) { 4988 /* Do need modport_set, stop */ 4989 use_modport_set = TRUE; 4990 break; 4991 } else if (rv == BCM_E_PORT) { 4992 /* no modmap for this port, ignore error and keep going */ 4993 } else { 4994 /* some other error, stop, do not use modport_set */ 4995 break; 4996 } 4997 } 4998 4999 /* Set the modport to a stack port, if available. This should only 5000 happen on XGS switch devices that only have one stack port and 5001 do not have a modport bitmap. */ 5002 5003 if (use_modport_set) { 5004 port = IPIC_PORT(unit); 5005 if (port < 0) { 5006 port = SOC_PORT_MIN(unit, st); 5007 if (port < 0) { 5008 /* just clear the modport if a stack port cannot be 5009 found */ 5010 port = 0; 5011 } 5012 } 5013 rv = bcm_esw_stk_modport_set(unit, modid, port); 5014 } 5015 5016 return rv; 5017 } 5018 5019 /* 5020 * Function: 5021 * bcm_stk_modport_clear_all 5022 * Purpose: 5023 * Clear all entries in MODPORT table 5024 * Parameters: 5025 * unit - SOC unit# 5026 * Returns: 5027 * BCM_E_XXX 5028 * Note: 5029 * Supported by all devices except Strata 5030 */ 5031 5032 int 5033 bcm_esw_stk_modport_clear_all(int unit) 5034 { 5035 if (!SOC_UNIT_VALID(unit)) { 5036 return BCM_E_UNIT; 5037 } 5038 5039 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5040 5041 LOG_VERBOSE(BSL_LS_BCM_STK, 5042 (BSL_META_U(unit, 5043 "STK %d: Clearing all mod port info.\n"), 5044 unit)); 5045 5046 switch (BCM_CHIP_FAMILY(unit)) { 5047 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_XGS_FABRIC_SUPPORT) 5048 case BCM_FAMILY_FIREBOLT: 5049 case BCM_FAMILY_HERCULES15: 5050 case BCM_FAMILY_BRADLEY: 5051 case BCM_FAMILY_HUMV: 5052 case BCM_FAMILY_TRIUMPH: 5053 case BCM_FAMILY_SCORPION: 5054 case BCM_FAMILY_CONQUEROR: 5055 case BCM_FAMILY_TRIUMPH2: 5056 case BCM_FAMILY_TITAN: 5057 case BCM_FAMILY_TRIDENT: 5058 case BCM_FAMILY_KATANA: 5059 { 5060 int i; 5061 5062 for ( i = 0; i <= SOC_MODID_MAX(unit); i++) { 5063 bcm_esw_stk_modport_clear(unit, i); 5064 } 5065 break; 5066 } 5067 #endif 5068 5069 default: 5070 return BCM_E_UNAVAIL; 5071 } 5072 5073 return BCM_E_NONE; 5074 } 5075 5076 /* 5077 * Function: 5078 * bcm_esw_stk_modport_add 5079 * Purpose: 5080 * Adds a HG port given a destination modid 5081 * Parameters: 5082 * unit - SOC unit# 5083 * modid - module id 5084 * port - egress HG port 5085 * Returns: 5086 * BCM_E_XXX 5087 */ 5088 int 5089 bcm_esw_stk_modport_add(int unit, int modid, bcm_port_t port) 5090 { 5091 int rv = BCM_E_UNAVAIL; 5092 5093 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5094 5095 LOG_INFO(BSL_LS_BCM_STK, 5096 (BSL_META_U(unit, 5097 "STK %d: modport add: modid %d to port %d\n"), 5098 unit, 5099 modid, port)); 5100 5101 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 5102 return BCM_E_PARAM; 5103 } 5104 if (BCM_GPORT_IS_SET(port) && !BCM_GPORT_IS_TRUNK(port)) { 5105 BCM_IF_ERROR_RETURN( 5106 bcm_esw_port_local_get(unit, port, &port)); 5107 } 5108 5109 switch (BCM_CHIP_FAMILY(unit)) { 5110 5111 #if defined(BCM_FIREBOLT_SUPPORT) 5112 case BCM_FAMILY_FIREBOLT: 5113 { 5114 modport_map_entry_t uc; 5115 uint32 hg_pbm = 0, modport_pbm = 0; 5116 5117 if (!SOC_PORT_VALID(unit, port)) { 5118 return BCM_E_PORT; 5119 } 5120 5121 /* Convert port to HG bitmap */ 5122 5123 if (SOC_IS_RAVEN(unit)) { 5124 if (IS_ST_PORT(unit, port) || IS_CPU_PORT(unit, port)) { 5125 hg_pbm = 1 << port; 5126 rv = BCM_E_NONE; 5127 } else { 5128 rv = BCM_E_PORT; 5129 } 5130 } else if (SOC_IS_HAWKEYE(unit)) { 5131 return BCM_E_UNAVAIL; 5132 } else { 5133 rv = soc_xgs3_port_to_higig_bitmap(unit, port, &hg_pbm); 5134 } 5135 if (rv != BCM_E_NONE) { 5136 return BCM_E_PORT; 5137 } 5138 5139 soc_mem_lock(unit, MODPORT_MAPm); 5140 rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc); 5141 if (rv >= 0) { 5142 modport_pbm = soc_MODPORT_MAPm_field32_get(unit, &uc, 5143 HIGIG_PORT_BITMAPf); 5144 if (modport_pbm & hg_pbm) { 5145 soc_mem_unlock(unit, MODPORT_MAPm); 5146 return BCM_E_NONE; 5147 } 5148 5149 modport_pbm |= hg_pbm; 5150 soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf, 5151 modport_pbm); 5152 rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, modid, &uc); 5153 } 5154 soc_mem_unlock(unit, MODPORT_MAPm); 5155 break; 5156 } 5157 #endif /* BCM_FIREBOLT_SUPPORT */ 5158 5159 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5160 case BCM_FAMILY_BRADLEY: 5161 case BCM_FAMILY_HUMV: 5162 case BCM_FAMILY_SCORPION: 5163 case BCM_FAMILY_CONQUEROR: 5164 case BCM_FAMILY_TRIUMPH: 5165 case BCM_FAMILY_TRIUMPH2: 5166 { 5167 bcm_port_t ing_port; 5168 PBMP_ALL_ITER(unit, ing_port) { 5169 BCM_IF_ERROR_RETURN 5170 (_bcm_stk_port_modport_op(unit, 5171 _BCM_STK_PORT_MODPORT_OP_ADD, 5172 ing_port, modid, &port, 1)); 5173 } 5174 rv = BCM_E_NONE; 5175 break; 5176 } 5177 #if defined(BCM_TRIDENT_SUPPORT) 5178 case BCM_FAMILY_TITAN: 5179 case BCM_FAMILY_TRIDENT: 5180 case BCM_FAMILY_KATANA: 5181 { 5182 bcm_port_t ing_port; 5183 bcm_pbmp_t all_pbmp; 5184 5185 BCM_PBMP_CLEAR(all_pbmp); 5186 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 5187 5188 #if defined(BCM_KATANA2_SUPPORT) 5189 if (soc_feature(unit, soc_feature_linkphy_coe) || 5190 soc_feature(unit, soc_feature_subtag_coe)) { 5191 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 5192 } 5193 if (SOC_IS_KATANA2(unit)) { 5194 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, 5195 &all_pbmp)); 5196 } 5197 #endif 5198 5199 PBMP_ITER(all_pbmp, ing_port) { 5200 BCM_IF_ERROR_RETURN 5201 (bcm_td_stk_port_modport_op(unit, 5202 _BCM_STK_PORT_MODPORT_OP_ADD, 5203 ing_port, modid, &port, 1)); 5204 } 5205 rv = BCM_E_NONE; 5206 break; 5207 } 5208 #endif /* BCM_TRIDENT_SUPPORT */ 5209 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5210 5211 default: 5212 break; 5213 } 5214 5215 return rv; 5216 } 5217 5218 /* 5219 * Function: 5220 * bcm_esw_stk_modport_delete 5221 * Purpose: 5222 * Removes a HG (egress) port for given a destination modid 5223 * Parameters: 5224 * unit - SOC unit# 5225 * modid - module id 5226 * port - egress HG port 5227 * Returns: 5228 * BCM_E_XXX 5229 */ 5230 int 5231 bcm_esw_stk_modport_delete(int unit, int modid, bcm_port_t port) 5232 { 5233 int rv = BCM_E_UNAVAIL; 5234 5235 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5236 5237 LOG_INFO(BSL_LS_BCM_STK, 5238 (BSL_META_U(unit, 5239 "STK %d: modport delete: modid %d to port %d\n"), 5240 unit, 5241 modid, port)); 5242 5243 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 5244 return BCM_E_PARAM; 5245 } 5246 if (BCM_GPORT_IS_SET(port) && !BCM_GPORT_IS_TRUNK(port)) { 5247 BCM_IF_ERROR_RETURN( 5248 bcm_esw_port_local_get(unit, port, &port)); 5249 } 5250 5251 switch (BCM_CHIP_FAMILY(unit)) { 5252 5253 #if defined(BCM_FIREBOLT_SUPPORT) 5254 case BCM_FAMILY_FIREBOLT: 5255 { 5256 modport_map_entry_t uc; 5257 uint32 modport_pbm = 0, hg_pbm = 0; 5258 5259 if (!SOC_PORT_VALID(unit, port)) { 5260 return BCM_E_PORT; 5261 } 5262 5263 /* Convert port to HG bitmap */ 5264 if (SOC_IS_RAVEN(unit)) { 5265 if (IS_ST_PORT(unit, port) || IS_CPU_PORT(unit, port)) { 5266 hg_pbm = 1 << port; 5267 rv = BCM_E_NONE; 5268 } else { 5269 rv = BCM_E_PORT; 5270 } 5271 } else if (SOC_IS_HAWKEYE(unit)) { 5272 return BCM_E_UNAVAIL; 5273 } else { 5274 rv = soc_xgs3_port_to_higig_bitmap(unit, port, &hg_pbm); 5275 } 5276 if (rv != BCM_E_NONE) { 5277 return BCM_E_PORT; 5278 } 5279 5280 soc_mem_lock(unit, MODPORT_MAPm); 5281 rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc); 5282 if (rv >= 0) { 5283 modport_pbm = soc_MODPORT_MAPm_field32_get(unit, &uc, 5284 HIGIG_PORT_BITMAPf); 5285 if (!(modport_pbm & hg_pbm)) { 5286 soc_mem_unlock(unit, MODPORT_MAPm); 5287 return BCM_E_NOT_FOUND; 5288 } 5289 5290 modport_pbm &= ~hg_pbm; 5291 soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf, 5292 modport_pbm); 5293 rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, modid, &uc); 5294 } 5295 soc_mem_unlock(unit, MODPORT_MAPm); 5296 break; 5297 } 5298 #endif /* BCM_FIREBOLT_SUPPORT */ 5299 5300 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5301 case BCM_FAMILY_BRADLEY: 5302 case BCM_FAMILY_HUMV: 5303 case BCM_FAMILY_SCORPION: 5304 case BCM_FAMILY_CONQUEROR: 5305 case BCM_FAMILY_TRIUMPH: 5306 case BCM_FAMILY_TRIUMPH2: 5307 { 5308 bcm_port_t ing_port; 5309 PBMP_ALL_ITER(unit, ing_port) { 5310 BCM_IF_ERROR_RETURN 5311 (_bcm_stk_port_modport_op(unit, 5312 _BCM_STK_PORT_MODPORT_OP_DELETE, 5313 ing_port, modid, &port, 1)); 5314 } 5315 rv = BCM_E_NONE; 5316 break; 5317 } 5318 #if defined(BCM_TRIDENT_SUPPORT) 5319 case BCM_FAMILY_TITAN: 5320 case BCM_FAMILY_TRIDENT: 5321 case BCM_FAMILY_KATANA: 5322 { 5323 bcm_port_t ing_port; 5324 bcm_pbmp_t all_pbmp; 5325 5326 BCM_PBMP_CLEAR(all_pbmp); 5327 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 5328 5329 #if defined(BCM_KATANA2_SUPPORT) 5330 if (soc_feature(unit, soc_feature_linkphy_coe) || 5331 soc_feature(unit, soc_feature_subtag_coe)) { 5332 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 5333 } 5334 if (SOC_IS_KATANA2(unit)) { 5335 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, 5336 &all_pbmp)); 5337 } 5338 #endif 5339 PBMP_ITER(all_pbmp, ing_port) { 5340 BCM_IF_ERROR_RETURN 5341 (bcm_td_stk_port_modport_op(unit, 5342 _BCM_STK_PORT_MODPORT_OP_DELETE, 5343 ing_port, modid, &port, 1)); 5344 } 5345 rv = BCM_E_NONE; 5346 break; 5347 } 5348 #endif /* BCM_TRIDENT_SUPPORT */ 5349 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5350 5351 default: 5352 break; 5353 } 5354 5355 return rv; 5356 } 5357 5358 /* 5359 * Function: 5360 * bcm_esw_stk_port_modport_set 5361 * Purpose: 5362 * Set a destination path for a given destination module of the ingress 5363 * port. 5364 * Parameters: 5365 * unit - (IN) Device number 5366 * ing_port - (IN) Ingress port 5367 * dest_modid - (IN) Destination module id 5368 * dest_port - (IN) Destination port 5369 * Returns: 5370 * BCM_E_XXX 5371 */ 5372 int 5373 bcm_esw_stk_port_modport_set(int unit, bcm_port_t ing_port, 5374 bcm_module_t dest_modid, bcm_port_t dest_port) 5375 { 5376 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5377 5378 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5379 LOG_INFO(BSL_LS_BCM_STK, 5380 (BSL_META_U(unit, 5381 "STK %d: port modport set: ing port %d modid %d to port %d\n"), 5382 unit, ing_port, dest_modid, dest_port)); 5383 5384 #ifdef BCM_TRIDENT_SUPPORT 5385 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 5386 return bcm_td_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET, 5387 ing_port, dest_modid, &dest_port, 1); 5388 } else 5389 #endif /* BCM_TRIDENT_SUPPORT */ 5390 { 5391 return _bcm_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET, 5392 ing_port, dest_modid, &dest_port, 1); 5393 } 5394 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5395 return BCM_E_UNAVAIL; 5396 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5397 } 5398 5399 /* 5400 * Function: 5401 * bcm_esw_stk_port_modport_get 5402 * Purpose: 5403 * Get a destination path for a given destination module of the ingress 5404 * port. 5405 * Parameters: 5406 * unit - (IN) Device number 5407 * ing_port - (IN) Ingress port 5408 * dest_modid - (IN) Destination module id 5409 * dest_port - (OUT) Destination port 5410 * Returns: 5411 * BCM_E_XXX 5412 */ 5413 int 5414 bcm_esw_stk_port_modport_get(int unit, bcm_port_t ing_port, 5415 bcm_module_t dest_modid, bcm_port_t *dest_port) 5416 { 5417 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5418 int dest_port_count; 5419 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5420 5421 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5422 5423 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5424 #ifdef BCM_TRIDENT_SUPPORT 5425 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 5426 return bcm_td_stk_port_modport_get(unit, ing_port, dest_modid, 1, dest_port, 5427 &dest_port_count); 5428 } else 5429 #endif /* BCM_TRIDENT_SUPPORT */ 5430 { 5431 return _bcm_stk_port_modport_get(unit, ing_port, dest_modid, 1, dest_port, 5432 &dest_port_count); 5433 } 5434 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5435 return BCM_E_UNAVAIL; 5436 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5437 } 5438 5439 /* 5440 * Function: 5441 * bcm_esw_stk_port_modport_get_all 5442 * Purpose: 5443 * Get all destination paths for a given destination module of the 5444 * ingress port. 5445 * Parameters: 5446 * unit - (IN) Device number 5447 * ing_port - (IN) Ingress port 5448 * dest_modid - (IN) Destination module id 5449 * dest_port_max - (IN) Maximum number of ports in array 5450 * dest_port_array - (OUT) Array of ports 5451 * dest_port_count - (OUT) Number of ports returned in array 5452 * Returns: 5453 * BCM_E_XXX 5454 */ 5455 int 5456 bcm_esw_stk_port_modport_get_all(int unit, bcm_port_t ing_port, 5457 bcm_module_t dest_modid, int dest_port_max, 5458 bcm_port_t *dest_port_array, 5459 int *dest_port_count) 5460 { 5461 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5462 5463 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5464 #ifdef BCM_TRIDENT_SUPPORT 5465 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 5466 return bcm_td_stk_port_modport_get(unit, ing_port, dest_modid, dest_port_max, 5467 dest_port_array, dest_port_count); 5468 } else 5469 #endif /* BCM_TRIDENT_SUPPORT */ 5470 { 5471 return _bcm_stk_port_modport_get(unit, ing_port, dest_modid, dest_port_max, 5472 dest_port_array, dest_port_count); 5473 } 5474 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5475 return BCM_E_UNAVAIL; 5476 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5477 } 5478 5479 /* 5480 * Function: 5481 * bcm_esw_stk_port_modport_clear 5482 * Purpose: 5483 * Clear all destination paths for a given destination module of the 5484 * ingress port. 5485 * Parameters: 5486 * unit - (IN) Device number 5487 * ing_port - (IN) Ingress port 5488 * dest_modid - (IN) Destination module id 5489 * Returns: 5490 * BCM_E_XXX 5491 */ 5492 int 5493 bcm_esw_stk_port_modport_clear(int unit, bcm_port_t ing_port, 5494 bcm_module_t dest_modid) 5495 { 5496 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5497 5498 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5499 LOG_INFO(BSL_LS_BCM_STK, 5500 (BSL_META_U(unit, 5501 "STK %d: port modport clear: ing port %d modid %d\n"), 5502 unit, ing_port, dest_modid)); 5503 5504 #ifdef BCM_TRIDENT_SUPPORT 5505 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 5506 return bcm_td_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET, 5507 ing_port, dest_modid, NULL, 0); 5508 } else 5509 #endif /* BCM_TRIDENT_SUPPORT */ 5510 { 5511 return _bcm_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET, 5512 ing_port, dest_modid, NULL, 0); 5513 } 5514 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5515 return BCM_E_UNAVAIL; 5516 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5517 } 5518 5519 /* 5520 * Function: 5521 * bcm_esw_stk_port_modport_clear_all 5522 * Purpose: 5523 * Clear destination paths for all destination modules of the ingress 5524 * port. 5525 * Parameters: 5526 * unit - (IN) Device number 5527 * ing_port - (IN) Ingress port 5528 * Returns: 5529 * BCM_E_XXX 5530 */ 5531 int 5532 bcm_esw_stk_port_modport_clear_all(int unit, bcm_port_t ing_port) 5533 { 5534 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5535 5536 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5537 LOG_INFO(BSL_LS_BCM_STK, 5538 (BSL_META_U(unit, 5539 "STK %d: port modport clear all: ing port %d\n"), 5540 unit, ing_port)); 5541 5542 #ifdef BCM_TRIDENT_SUPPORT 5543 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 5544 return bcm_td_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET, 5545 ing_port, -1, NULL, 0); 5546 } else 5547 #endif /* BCM_TRIDENT_SUPPORT */ 5548 { 5549 return _bcm_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_SET, 5550 ing_port, -1, NULL, 0); 5551 } 5552 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5553 return BCM_E_UNAVAIL; 5554 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5555 } 5556 5557 /* 5558 * Function: 5559 * bcm_esw_stk_port_modport_add 5560 * Purpose: 5561 * Add one path for a given destination module of the ingress port. 5562 * Parameters: 5563 * unit - (IN) Device number 5564 * ing_port - (IN) Ingress port 5565 * dest_modid - (IN) Destination module id 5566 * dest_port - (IN) Destination port 5567 * Returns: 5568 * BCM_E_XXX 5569 */ 5570 int 5571 bcm_esw_stk_port_modport_add(int unit, bcm_port_t ing_port, 5572 bcm_module_t dest_modid, bcm_port_t dest_port) 5573 { 5574 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5575 5576 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5577 LOG_INFO(BSL_LS_BCM_STK, 5578 (BSL_META_U(unit, 5579 "STK %d: port modport add: ing port %d modid %d to port %d\n"), 5580 unit, ing_port, dest_modid, dest_port)); 5581 5582 #ifdef BCM_TRIDENT_SUPPORT 5583 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 5584 return bcm_td_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_ADD, 5585 ing_port, dest_modid, &dest_port, 1); 5586 } else 5587 #endif /* BCM_TRIDENT_SUPPORT */ 5588 { 5589 return _bcm_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_ADD, 5590 ing_port, dest_modid, &dest_port, 1); 5591 } 5592 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5593 return BCM_E_UNAVAIL; 5594 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5595 } 5596 5597 /* 5598 * Function: 5599 * bcm_esw_stk_port_modport_delete 5600 * Purpose: 5601 * Delete one path for a given destination module of the ingress port. 5602 * Parameters: 5603 * unit - (IN) Device number 5604 * ing_port - (IN) Ingress port 5605 * dest_modid - (IN) Destination module id 5606 * dest_port - (IN) Destination port 5607 * Returns: 5608 * BCM_E_XXX 5609 */ 5610 int 5611 bcm_esw_stk_port_modport_delete(int unit, bcm_port_t ing_port, 5612 bcm_module_t dest_modid, bcm_port_t dest_port) 5613 { 5614 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5615 5616 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5617 LOG_INFO(BSL_LS_BCM_STK, 5618 (BSL_META_U(unit, 5619 "STK %d: port modport delete: ing port %d modid %d to port %d\n"), 5620 unit, ing_port, dest_modid, dest_port)); 5621 5622 #ifdef BCM_TRIDENT_SUPPORT 5623 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 5624 return bcm_td_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_DELETE, 5625 ing_port, dest_modid, &dest_port, 1); 5626 } else 5627 #endif /* BCM_TRIDENT_SUPPORT */ 5628 { 5629 return _bcm_stk_port_modport_op(unit, _BCM_STK_PORT_MODPORT_OP_DELETE, 5630 ing_port, dest_modid, &dest_port, 1); 5631 } 5632 #else /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5633 return BCM_E_UNAVAIL; 5634 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5635 } 5636 5637 #ifdef _BCM_STK_FLAGS_GET 5638 5639 /**************************************************************** 5640 * 5641 * Get port's stack flags, per device type 5642 */ 5643 5644 STATIC int 5645 _esw_stk_flags_get(int unit, bcm_port_t port, uint32 *flags) 5646 { 5647 if (!SOC_IS_STACK_PORT(unit, port)) { 5648 *flags = BCM_STK_NONE; 5649 return BCM_E_NONE; 5650 } 5651 *flags = BCM_STK_ENABLE; 5652 5653 if (SOC_IS_INACTIVE_STACK_PORT(unit, port)) { 5654 *flags |= BCM_STK_INACTIVE; 5655 } 5656 5657 return BCM_E_NONE; 5658 } 5659 5660 #endif /* _BCM_STK_FLAGS_GET */ 5661 5662 #if defined(BCM_HERCULES_SUPPORT) 5663 /* 5664 * Set the unicast forwarding port bitmap 5665 */ 5666 STATIC int 5667 _bcm5675_stk_ucbitmap_set(int unit, bcm_port_t port, int modid, pbmp_t pbmp) 5668 { 5669 mem_uc_entry_t uc; 5670 int blk; 5671 int rv; 5672 5673 if (IS_CPU_PORT(unit, port)) { 5674 return BCM_E_PORT; 5675 } 5676 blk = SOC_PORT_BLOCK(unit, port); 5677 soc_mem_lock(unit, MEM_UCm); 5678 rv = READ_MEM_UCm(unit, blk, modid, &uc); 5679 if (rv >= 0) { 5680 soc_MEM_UCm_field32_set(unit, &uc, UCBITMAPf, 5681 SOC_PBMP_WORD_GET(pbmp, 0)); 5682 5683 rv = WRITE_MEM_UCm(unit, blk, modid, &uc); 5684 } 5685 soc_mem_unlock(unit, MEM_UCm); 5686 return rv; 5687 } 5688 5689 STATIC int 5690 _bcm567x_stk_ucbitmap_get(int unit, bcm_port_t port, int modid, pbmp_t *pbmp) 5691 { 5692 mem_uc_entry_t uc; 5693 int blk; 5694 5695 if (port < 0) { 5696 port = SOC_PORT(unit, hg, 0); 5697 } 5698 blk = SOC_PORT_BLOCK(unit, port); 5699 SOC_IF_ERROR_RETURN(READ_MEM_UCm(unit, blk, modid, &uc)); 5700 SOC_PBMP_CLEAR(*pbmp); 5701 SOC_PBMP_WORD_SET(*pbmp, 0, 5702 soc_MEM_UCm_field32_get(unit, &uc, UCBITMAPf)); 5703 5704 return BCM_E_NONE; 5705 } 5706 5707 STATIC int 5708 _bcm567x_stk_ucbitmap_del(int unit, bcm_port_t port, int modid, bcm_pbmp_t pbmp) 5709 { 5710 mem_uc_entry_t uc; 5711 int blk; 5712 int rv; 5713 uint32 fval; 5714 5715 /* Clear UCbitmap for port & MH.DST_MODID */ 5716 blk = SOC_PORT_BLOCK(unit, port); 5717 soc_mem_lock(unit, MEM_UCm); 5718 rv = READ_MEM_UCm(unit, blk, modid, &uc); 5719 if (rv >= 0) { 5720 soc_MEM_UCm_field_get(unit, &uc, UCBITMAPf, &fval); 5721 fval &= ~SOC_PBMP_WORD_GET(pbmp, 0); 5722 soc_MEM_UCm_field_set(unit, &uc, UCBITMAPf, &fval); 5723 rv = WRITE_MEM_UCm(unit, blk, modid, &uc); 5724 } 5725 soc_mem_unlock(unit, MEM_UCm); 5726 return rv; 5727 } 5728 5729 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 5730 5731 #if defined(BCM_FIREBOLT_SUPPORT) 5732 STATIC int 5733 _bcm56504_stk_ucbitmap_set(int unit, int modid, pbmp_t pbmp) 5734 { 5735 modport_map_entry_t uc; 5736 int rv; 5737 uint32 map; 5738 int offset; 5739 pbmp_t non_stk_port; 5740 5741 /* Check that port pbmp has only stack ports */ 5742 SOC_PBMP_ASSIGN(non_stk_port, pbmp); 5743 SOC_PBMP_REMOVE(non_stk_port, PBMP_ST_ALL(unit)); 5744 if (SOC_PBMP_NOT_NULL(non_stk_port)) { 5745 return BCM_E_PORT; 5746 } 5747 5748 offset = SOC_IS_RAPTOR(unit) ? 1 : SOC_HG_OFFSET(unit); 5749 map = SOC_PBMP_WORD_GET(pbmp, 0) >> offset; 5750 soc_mem_lock(unit, MODPORT_MAPm); 5751 rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc); 5752 if (rv >= 0) { 5753 soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf, 5754 map); 5755 rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, modid, &uc); 5756 } 5757 soc_mem_unlock(unit, MODPORT_MAPm); 5758 return rv; 5759 } 5760 5761 STATIC int 5762 _bcm56504_stk_ucbitmap_get(int unit, int modid, pbmp_t *pbmp) 5763 { 5764 modport_map_entry_t uc; 5765 uint32 map; 5766 int offset; 5767 5768 offset = SOC_IS_RAPTOR(unit) ? 1 : SOC_HG_OFFSET(unit); 5769 SOC_IF_ERROR_RETURN 5770 (READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc)); 5771 map = soc_MODPORT_MAPm_field32_get(unit, &uc, HIGIG_PORT_BITMAPf); 5772 SOC_PBMP_CLEAR(*pbmp); 5773 SOC_PBMP_WORD_SET(*pbmp, 0, (map << offset)); 5774 5775 return BCM_E_NONE; 5776 } 5777 5778 STATIC int 5779 _bcm56504_stk_ucbitmap_del(int unit, int modid, bcm_pbmp_t pbmp) 5780 { 5781 modport_map_entry_t uc; 5782 int rv; 5783 uint32 fval; 5784 uint32 map; 5785 int offset; 5786 pbmp_t non_stk_port; 5787 5788 /* Check that port pbmp has only stack ports */ 5789 SOC_PBMP_ASSIGN(non_stk_port, pbmp); 5790 SOC_PBMP_REMOVE(non_stk_port, PBMP_ST_ALL(unit)); 5791 if (SOC_PBMP_NOT_NULL(non_stk_port)) { 5792 return BCM_E_PORT; 5793 } 5794 5795 offset = SOC_IS_RAPTOR(unit) ? 1 : SOC_HG_OFFSET(unit); 5796 5797 /* Convert port to HG bitmap */ 5798 map = SOC_PBMP_WORD_GET(pbmp, 0) >> offset; 5799 soc_mem_lock(unit, MODPORT_MAPm); 5800 rv = READ_MODPORT_MAPm(unit, MEM_BLOCK_ANY, modid, &uc); 5801 if (rv >= 0) { 5802 fval = soc_MODPORT_MAPm_field32_get(unit, &uc, HIGIG_PORT_BITMAPf); 5803 fval &= ~map; 5804 soc_MODPORT_MAPm_field32_set(unit, &uc, HIGIG_PORT_BITMAPf, fval); 5805 rv = WRITE_MODPORT_MAPm(unit, MEM_BLOCK_ALL, modid, &uc); 5806 } 5807 soc_mem_unlock(unit, MODPORT_MAPm); 5808 return rv; 5809 } 5810 #endif /* BCM_FIREBOLT_SUPPORT */ 5811 5812 /* 5813 * Function: 5814 * bcm_stk_ucbitmap_set 5815 * Purpose: 5816 * Set the unicast forwarding port bitmap 5817 * Parameters: 5818 * unit - SOC unit# 5819 * port - ingress port number 5820 * modid - destination module ID index (from HiGig mod header) 5821 * pbmp - forwarding port bitmap 5822 * Returns: 5823 * BCM_E_XXX 5824 * Note: 5825 * Fabric only 5826 */ 5827 int 5828 bcm_esw_stk_ucbitmap_set(int unit, bcm_port_t port, int modid, pbmp_t pbmp) 5829 { 5830 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5831 5832 if (BCM_GPORT_IS_SET(port)) { 5833 BCM_IF_ERROR_RETURN( 5834 bcm_esw_port_local_get(unit, port, &port)); 5835 } 5836 5837 #ifdef BCM_HERCULES_SUPPORT 5838 if (SOC_IS_HERCULES15(unit)) { 5839 return _bcm5675_stk_ucbitmap_set(unit, port, modid, pbmp); 5840 } 5841 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 5842 5843 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5844 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 5845 bcm_port_t dest_port, dest_port_array[96]={0}; 5846 int count; 5847 5848 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 5849 return BCM_E_PARAM; 5850 } 5851 5852 count = 0; 5853 BCM_PBMP_ITER(pbmp, dest_port) { 5854 if (count >= 96) { 5855 return BCM_E_RESOURCE; 5856 } 5857 dest_port_array[count] = dest_port; 5858 count++; 5859 } 5860 #ifdef BCM_TRIDENT_SUPPORT 5861 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 5862 return bcm_td_stk_port_modport_op(unit, 5863 _BCM_STK_PORT_MODPORT_OP_SET, 5864 port, modid, dest_port_array, count); 5865 } else 5866 #endif /* BCM_TRIDENT_SUPPORT */ 5867 { 5868 return _bcm_stk_port_modport_op(unit, 5869 _BCM_STK_PORT_MODPORT_OP_SET, 5870 port, modid, dest_port_array, count); 5871 } 5872 } 5873 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5874 5875 #ifdef BCM_FIREBOLT_SUPPORT 5876 if (SOC_IS_FBX(unit)) { 5877 COMPILER_REFERENCE(port); 5878 return _bcm56504_stk_ucbitmap_set(unit, modid, pbmp); 5879 } 5880 #endif /* BCM_FIREBOLT_SUPPORT */ 5881 5882 return BCM_E_UNAVAIL; 5883 } 5884 5885 /* 5886 * Function: 5887 * bcm_stk_ucbitmap_get 5888 * Purpose: 5889 * Get the unicast forwarding port bitmap 5890 * Parameters: 5891 * unit - SOC unit# 5892 * port - ingress port number 5893 * modid - destination module ID index (from HiGig mod header) 5894 * pbmp - (out)forwarding port bitmap 5895 * Returns: 5896 * BCM_E_XXX 5897 * Note: 5898 * Fabric only 5899 */ 5900 int 5901 bcm_esw_stk_ucbitmap_get(int unit, bcm_port_t port, int modid, pbmp_t *pbmp) 5902 { 5903 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5904 5905 if (BCM_GPORT_IS_SET(port)) { 5906 BCM_IF_ERROR_RETURN( 5907 bcm_esw_port_local_get(unit, port, &port)); 5908 } 5909 5910 #ifdef BCM_XGS12_FABRIC_SUPPORT 5911 if (SOC_IS_XGS12_FABRIC(unit)) { 5912 return _bcm567x_stk_ucbitmap_get(unit, port, modid, pbmp); 5913 } 5914 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 5915 5916 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5917 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 5918 bcm_port_t dest_port_array[96]; 5919 int count, index, rv; 5920 5921 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 5922 return BCM_E_PARAM; 5923 } 5924 5925 #ifdef BCM_TRIDENT_SUPPORT 5926 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 5927 rv = bcm_td_stk_port_modport_get(unit, port, modid, 96, 5928 dest_port_array, &count); 5929 } else 5930 #endif /* BCM_TRIDENT_SUPPORT */ 5931 { 5932 rv =_bcm_stk_port_modport_get(unit, port, modid, 96, 5933 dest_port_array, &count); 5934 } 5935 if (rv == BCM_E_NOT_FOUND) { 5936 BCM_PBMP_CLEAR(*pbmp); 5937 return BCM_E_NONE; 5938 } else if (BCM_FAILURE(rv)) { 5939 return rv; 5940 } 5941 BCM_PBMP_CLEAR(*pbmp); 5942 for (index = 0; index < count; index++) { 5943 BCM_PBMP_PORT_ADD(*pbmp, dest_port_array[index]); 5944 } 5945 return BCM_E_NONE; 5946 } 5947 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 5948 5949 #ifdef BCM_FIREBOLT_SUPPORT 5950 if (SOC_IS_FBX(unit)) { 5951 COMPILER_REFERENCE(port); 5952 return _bcm56504_stk_ucbitmap_get(unit, modid, pbmp); 5953 } 5954 #endif /* BCM_FIREBOLT_SUPPORT */ 5955 5956 return BCM_E_UNAVAIL; 5957 } 5958 5959 /* 5960 * Function: 5961 * bcm_stk_ucbitmap_del 5962 * Purpose: 5963 * Remove a group of ports from a Unicast (UC) table entry for 5964 * a given ingress port. 5965 * Parameters: 5966 * unit - SOC unit# 5967 * port - ingress port number 5968 * modid - destination module ID index (in HiGig mod header) 5969 * pbmp - forwarding port bitmap 5970 * Returns: 5971 * BCM_E_XXX 5972 * Note: 5973 * Fabric only 5974 */ 5975 int 5976 bcm_esw_stk_ucbitmap_del(int unit, bcm_port_t port, int modid, bcm_pbmp_t pbmp) 5977 { 5978 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 5979 5980 if (BCM_GPORT_IS_SET(port)) { 5981 BCM_IF_ERROR_RETURN( 5982 bcm_esw_port_local_get(unit, port, &port)); 5983 } 5984 5985 #ifdef BCM_XGS12_FABRIC_SUPPORT 5986 if (SOC_IS_XGS12_FABRIC(unit)) { 5987 return _bcm567x_stk_ucbitmap_del(unit, port, modid, pbmp); 5988 } 5989 #endif /* BCM_XGS12_FABRIC_SUPPORT */ 5990 5991 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) 5992 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 5993 bcm_port_t dest_port, dest_port_array[96]={0}; 5994 int count; 5995 5996 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 5997 return BCM_E_PARAM; 5998 } 5999 6000 count = 0; 6001 BCM_PBMP_ITER(pbmp, dest_port) { 6002 if (count >= 96) { 6003 return BCM_E_RESOURCE; 6004 } 6005 dest_port_array[count] = dest_port; 6006 count++; 6007 } 6008 #ifdef BCM_TRIDENT_SUPPORT 6009 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 6010 return bcm_td_stk_port_modport_op(unit, 6011 _BCM_STK_PORT_MODPORT_OP_DELETE, 6012 port, modid, dest_port_array, count); 6013 } else 6014 #endif /* BCM_TRIDENT_SUPPORT */ 6015 { 6016 return _bcm_stk_port_modport_op(unit, 6017 _BCM_STK_PORT_MODPORT_OP_DELETE, 6018 port, modid, dest_port_array, count); 6019 } 6020 } 6021 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */ 6022 6023 #ifdef BCM_FIREBOLT_SUPPORT 6024 if (SOC_IS_FBX(unit)) { 6025 COMPILER_REFERENCE(port); 6026 return _bcm56504_stk_ucbitmap_del(unit, modid, pbmp); 6027 } 6028 #endif /* BCM_FIREBOLT_SUPPORT */ 6029 6030 return BCM_E_UNAVAIL; 6031 } 6032 #if defined(BCM_METROLITE_SUPPORT) 6033 /* Function: 6034 * _bcm_metrolite_stk_fmod_lmod_mapping_set 6035 * Purpose: 6036 * Similar function as bcm_esw_stk_fmod_lmod_mapping_set, 6037 * but Metrolite has different register formats for 6038 * ING_MODMAP_CTRL and EGR_MODMAP_CTRL 6039 */ 6040 int 6041 _bcm_metrolite_stk_fmod_lmod_mapping_set(int unit, bcm_port_t port, 6042 bcm_module_t fmod, bcm_module_t lmod) { 6043 uint32 reg32, oreg32; 6044 int rv; 6045 6046 if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) { 6047 reg32 = oreg32; 6048 soc_reg_field_set(unit, ING_MODMAP_CTRLr, ®32, 6049 MODULEID_OFFSETf, (fmod - lmod)); 6050 if (reg32 != oreg32) { 6051 rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32); 6052 if (rv >= 0) { 6053 /*ING and EGR Registers will be sync. No need to 6054 check again if value changed. */ 6055 rv = READ_EGR_MODMAP_CTRLr(unit, port, ®32); 6056 if (rv < 0) { 6057 ESW_STK_UNLOCK; 6058 return rv; 6059 } 6060 soc_reg_field_set(unit, EGR_MODMAP_CTRLr, ®32, 6061 MODULEID_OFFSETf, (fmod - lmod)); 6062 rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32); 6063 } 6064 } 6065 mod_map_data[unit]->l_modid[port] = lmod; 6066 } 6067 #ifdef BCM_WARM_BOOT_SUPPORT 6068 SOC_CONTROL_LOCK(unit); 6069 SOC_CONTROL(unit)->scache_dirty = 1; 6070 SOC_CONTROL_UNLOCK(unit); 6071 #endif 6072 6073 return rv; 6074 } 6075 #endif 6076 /* 6077 * Function: 6078 * bcm_stk_fmod_lmod_mapping_set 6079 * Purpose: 6080 * Set up mapping of (FMODID, FPORT) <--> (LMODID, LPORT) on 6081 * a fabric port. Assigns base FMODID and LMODID to devices 6082 * in the legacy domain attached to a fabric port. When fmod is 6083 * -1, l_modid state is populated with "lmod" value that is 6084 * passed (if it is valid) 6085 * Parameters: 6086 * unit - StrataSwitch PCI device unit number (driver internal). 6087 * port - StrataSwitch port number 6088 * fmod - Fabric Module Identifier 6089 * lmod - Local Module Identifier 6090 * enable - modmap enable = 1, disable = 0 6091 * Returns: 6092 * BCM_E_NONE - Success. 6093 * BCM_E_XXX - Failure. 6094 * Notes: 6095 * Fabric only (BCM5675). 6096 * The fmod assignment will be 6097 * Switch-1 LMODID = lmod FMODID = fmod 6098 * Switch-2 LMODID = lmod + 1 FMODID = fmod + 1 6099 * Switch-3 LMODID = lmod + 2 FMODID = fmod + 2 6100 * Switch-4 LMODID = lmod + 3 FMODID = fmod + 3 6101 * and so on. 6102 */ 6103 6104 int 6105 bcm_esw_stk_fmod_lmod_mapping_set(int unit, bcm_port_t port, 6106 bcm_module_t fmod, bcm_module_t lmod) 6107 { 6108 #if defined(LOCAL_MODMAP_SUPPORT) 6109 uint32 reg32, oreg32; 6110 int rv = BCM_E_UNAVAIL; 6111 6112 BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_fmod_lmod_mapping_set); 6113 LMOD_RANGE_CHECK(lmod); 6114 MOD_MAP_DATA_CHECK(unit); 6115 if (SOC_WARM_BOOT(unit) || fmod == -1) { 6116 ESW_STK_LOCK; 6117 mod_map_data[unit]->l_modid[port] = lmod; 6118 ESW_STK_UNLOCK; 6119 return BCM_E_NONE; 6120 } 6121 6122 FMOD_RANGE_CHECK(fmod); 6123 FMOD_LMOD_CHECK(fmod, lmod); 6124 6125 if (BCM_GPORT_IS_SET(port)) { 6126 BCM_IF_ERROR_RETURN( 6127 bcm_esw_port_local_get(unit, port, &port)); 6128 } 6129 6130 ESW_STK_LOCK; 6131 #if defined(BCM_METROLITE_SUPPORT) 6132 if (SOC_IS_METROLITE(unit)) { 6133 /* Metrolite supports only 64 MODIDs. Jira SDK-82046 */ 6134 if ((fmod - lmod) > 63) { 6135 ESW_STK_UNLOCK; 6136 return BCM_E_PARAM; 6137 } 6138 rv = _bcm_metrolite_stk_fmod_lmod_mapping_set(unit, port, fmod, lmod); 6139 ESW_STK_UNLOCK; 6140 return rv; 6141 } 6142 #endif 6143 6144 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 6145 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 6146 if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) { 6147 reg32 = oreg32; 6148 soc_reg_field_set(unit, ING_MODMAP_CTRLr, ®32, 6149 MODULEID_OFFSETf, (fmod - lmod)); 6150 if (reg32 != oreg32) { 6151 rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32); 6152 if (rv >= 0) { 6153 /* We must keep the ingress and egress copies in sync */ 6154 rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32); 6155 } 6156 } 6157 mod_map_data[unit]->l_modid[port] = lmod; 6158 } 6159 6160 6161 6162 } else 6163 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */ 6164 { 6165 #if defined(BCM_HERCULES_SUPPORT) 6166 if ((rv = READ_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) { 6167 reg32 = oreg32; 6168 soc_reg_field_set(unit, MODMAP_CTRLr, ®32, 6169 MODULE_ID_OFFSETf, (fmod - lmod)); 6170 if (reg32 != oreg32) { 6171 rv = WRITE_MODMAP_CTRLr(unit, port, reg32); 6172 } 6173 mod_map_data[unit]->l_modid[port] = lmod; 6174 } 6175 #endif 6176 } 6177 ESW_STK_UNLOCK; 6178 6179 #ifdef BCM_WARM_BOOT_SUPPORT 6180 SOC_CONTROL_LOCK(unit); 6181 SOC_CONTROL(unit)->scache_dirty = 1; 6182 SOC_CONTROL_UNLOCK(unit); 6183 #endif 6184 6185 return(rv); 6186 #else 6187 return BCM_E_UNAVAIL; 6188 #endif /* MODMAP_SUPPORT */ 6189 } 6190 6191 /* 6192 * Function: 6193 * bcm_stk_fmod_lmod_mapping_get 6194 * Purpose: 6195 * Get the (FMODID, LMODID) associated with a fabric port. 6196 * Gets the base FMODID and LMODID assigned to the devices 6197 * in the legacy domain attached to this fabric port. 6198 * Parameters: 6199 * unit - StrataSwitch PCI device unit number (driver internal). 6200 * port - StrataSwitch port number 6201 * fmod - (OUT) Fabric Module Identifier 6202 * lmod - (OUT)Local Module Identifier 6203 * Returns: 6204 * BCM_E_NONE - Success. 6205 * BCM_E_XXX - Failure. 6206 * Notes: 6207 * Fabric only (BCM5675) 6208 */ 6209 6210 int 6211 bcm_esw_stk_fmod_lmod_mapping_get(int unit, bcm_port_t port, 6212 bcm_module_t *fmod, bcm_module_t *lmod) 6213 { 6214 #if defined(LOCAL_MODMAP_SUPPORT) 6215 uint32 oreg32; 6216 6217 BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_fmod_lmod_mapping_get); 6218 MOD_MAP_DATA_CHECK(unit); 6219 6220 if (BCM_GPORT_IS_SET(port)) { 6221 BCM_IF_ERROR_RETURN( 6222 bcm_esw_port_local_get(unit, port, &port)); 6223 } 6224 6225 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 6226 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 6227 SOC_IF_ERROR_RETURN(READ_ING_MODMAP_CTRLr(unit, port, &oreg32)); 6228 *fmod = soc_reg_field_get(unit, ING_MODMAP_CTRLr, oreg32, 6229 MODULEID_OFFSETf); 6230 } else 6231 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */ 6232 { 6233 #if defined(BCM_HERCULES_SUPPORT) 6234 SOC_IF_ERROR_RETURN(READ_MODMAP_CTRLr(unit, port, &oreg32)); 6235 *fmod = soc_reg_field_get(unit, MODMAP_CTRLr, oreg32, 6236 MODULE_ID_OFFSETf); 6237 #else 6238 return BCM_E_UNAVAIL; 6239 #endif 6240 } 6241 6242 *lmod = mod_map_data[unit]->l_modid[port]; 6243 *fmod += *lmod; 6244 6245 return(BCM_E_NONE); 6246 #else 6247 return BCM_E_UNAVAIL; 6248 #endif /* BCM_MODMAP_SUPPORT */ 6249 } 6250 6251 #ifdef BCM_BRADLEY_SUPPORT 6252 int 6253 _bcm_stk_fmod_smod_mapping_group_set(int unit, int group, 6254 bcm_module_t fmod, bcm_module_t smod, 6255 bcm_port_t sport, uint32 nports) 6256 { 6257 int rv=BCM_E_NONE; 6258 ing_mod_map_table_entry_t immap; 6259 egr_mod_map_table_entry_t emmap; 6260 int i, found, group_offset_ing, group_offset_egr; 6261 uint32 fval; 6262 uint32 thresh; 6263 soc_field_t tf[] = {THRESH_Af, THRESH_Bf, THRESH_Cf, INVALIDf}; 6264 soc_field_t pf[] = {PORTOFF_Af, PORTOFF_Bf, PORTOFF_Cf, PORTOFF_Df}; 6265 soc_field_t mf[] = {MOD_Af, MOD_Bf, MOD_Cf, MOD_Df, INVALIDf}; 6266 6267 /* Note: Parameter checks were performed before calling this function */ 6268 if (group == 1) { 6269 group_offset_ing = soc_mem_index_count(unit, ING_MOD_MAP_TABLEm) / 2; 6270 group_offset_egr = soc_mem_index_count(unit, EGR_MOD_MAP_TABLEm) / 2; 6271 } else { /* group == 0 */ 6272 group_offset_ing = 0; 6273 group_offset_egr = 0; 6274 } 6275 6276 if (nports != 0) { 6277 SPORT_RANGE_CHECK((sport + nports - 1)); 6278 6279 sal_memset(&emmap, 0, sizeof(emmap)); 6280 soc_EGR_MOD_MAP_TABLEm_field_set(unit, &emmap, 6281 PORT_OFFSETf, (uint32 *)&sport); 6282 soc_EGR_MOD_MAP_TABLEm_field_set(unit, &emmap, 6283 MODIDf, (uint32 *)&smod); 6284 thresh = sport + nports - 1; 6285 6286 ESW_STK_LOCK; 6287 6288 if ((rv = READ_ING_MOD_MAP_TABLEm(unit, SOC_BLOCK_ANY, 6289 smod + group_offset_ing, &immap)) >= 0) { 6290 found = 0; 6291 for(i = 0; mf[i] != INVALIDf; i++) { 6292 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, mf[i], &fval); 6293 if (fval == 0) { 6294 if (fmod==0) { 6295 mod_map_data[unit]->fmod0[group] = smod+1; 6296 break; /* Found a slot for fmod 0 */ 6297 } 6298 if ((mod_map_data[unit]->fmod0[group]) && 6299 ((mod_map_data[unit]->fmod0[group] == (smod+1))) && 6300 !(found)) { 6301 found=1; /* This is fmod 0 */ 6302 } else { 6303 break; /* Found a slot */ 6304 } 6305 } 6306 } 6307 6308 if (mf[i] != INVALIDf) { 6309 for(; i > 0; i--) { 6310 soc_ING_MOD_MAP_TABLEm_field_get( 6311 unit, &immap, tf[i - 1], &fval); 6312 /* THRESH_A < THRESH_B < THRESH_C */ 6313 if (fval > thresh) { 6314 if (tf[i] != INVALIDf) { 6315 soc_ING_MOD_MAP_TABLEm_field_set( 6316 unit, &immap, tf[i], &fval); 6317 } else { 6318 mod_map_data[unit]->thresh_d[smod] = fval; 6319 } 6320 soc_ING_MOD_MAP_TABLEm_field_get( 6321 unit, &immap, pf[i - 1], &fval); 6322 soc_ING_MOD_MAP_TABLEm_field_set( 6323 unit, &immap, pf[i], &fval); 6324 soc_ING_MOD_MAP_TABLEm_field_get( 6325 unit, &immap, mf[i - 1], &fval); 6326 soc_ING_MOD_MAP_TABLEm_field_set( 6327 unit, &immap, mf[i], &fval); 6328 } else { 6329 break; 6330 } 6331 } 6332 6333 if (tf[i] != INVALIDf) { 6334 soc_ING_MOD_MAP_TABLEm_field_set( 6335 unit, &immap, tf[i], &thresh); 6336 } else { 6337 mod_map_data[unit]->thresh_d[smod] = thresh; 6338 } 6339 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, 6340 pf[i], (uint32 *)&sport); 6341 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, 6342 mf[i], (uint32 *)&fmod); 6343 rv = WRITE_EGR_MOD_MAP_TABLEm(unit, SOC_BLOCK_ALL, 6344 fmod + group_offset_egr, &emmap); 6345 if (rv >= 0) { 6346 rv = WRITE_ING_MOD_MAP_TABLEm(unit, SOC_BLOCK_ALL, 6347 smod + group_offset_ing, &immap); 6348 } 6349 } else { 6350 rv = BCM_E_PARAM; 6351 } 6352 } 6353 ESW_STK_UNLOCK; 6354 } else { /* This is actually a delete */ 6355 ESW_STK_LOCK; 6356 if ((rv = READ_EGR_MOD_MAP_TABLEm(unit, SOC_BLOCK_ANY, 6357 fmod + group_offset_egr, &emmap)) >= 0) { 6358 bcm_port_t o_sport = -1; 6359 bcm_module_t o_smod = -1; 6360 int j; 6361 6362 soc_EGR_MOD_MAP_TABLEm_field_get(unit, &emmap, 6363 PORT_OFFSETf, (uint32 *)&o_sport); 6364 soc_EGR_MOD_MAP_TABLEm_field_get(unit, &emmap, 6365 MODIDf, (uint32 *)&o_smod); 6366 sal_memset(&emmap, 0, sizeof(emmap)); 6367 if ((o_sport == sport) && (o_smod == smod)) { 6368 if ((rv = READ_ING_MOD_MAP_TABLEm(unit, SOC_BLOCK_ANY, 6369 smod + group_offset_ing, &immap)) >= 0) { 6370 for(i = 0; mf[i] != INVALIDf; i++) { 6371 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, mf[i], &fval); 6372 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, pf[i], &thresh); 6373 if ((fval == (uint32)fmod) && (thresh == (uint32)sport)) { 6374 if (tf[i] == INVALIDf) { 6375 mod_map_data[unit]->thresh_d[smod] = 0; 6376 fval = 0; 6377 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, mf[i], &fval); 6378 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, pf[i], &fval); 6379 } else { 6380 for (j = i; mf[j+1] != INVALIDf; j++) { 6381 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, pf[j+1], &fval); 6382 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, pf[j], &fval); 6383 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap,mf[j+1], &fval); 6384 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, mf[j], &fval); 6385 if (tf[j+1] != INVALIDf) { 6386 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, tf[j+1], &fval); 6387 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, tf[j], &fval); 6388 } 6389 } 6390 fval = 0; 6391 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, pf[j], &fval); 6392 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, mf[j], &fval); 6393 soc_ING_MOD_MAP_TABLEm_field_set(unit, &immap, tf[j-1], &fval); 6394 } 6395 break; 6396 } 6397 } 6398 if (mf[i] == INVALIDf) { 6399 rv = BCM_E_INTERNAL; 6400 } else { 6401 rv = WRITE_EGR_MOD_MAP_TABLEm(unit, SOC_BLOCK_ALL, 6402 fmod + group_offset_egr, &emmap); 6403 if (rv >= 0) { 6404 rv = WRITE_ING_MOD_MAP_TABLEm(unit, SOC_BLOCK_ALL, 6405 smod + group_offset_ing, &immap); 6406 } 6407 6408 if (fmod==0) { 6409 mod_map_data[unit]->fmod0[group] = 0; 6410 } 6411 } 6412 } 6413 } else { 6414 rv = BCM_E_PARAM; 6415 } 6416 } 6417 ESW_STK_UNLOCK; 6418 } 6419 6420 return(rv); 6421 } 6422 #endif /* BCM_BRADLEY_SUPPORT */ 6423 6424 /* 6425 * Function: 6426 * bcm_stk_fmod_smod_mapping_set 6427 * Purpose: 6428 * Set up mapping of (FMODID, FPORT) <--> (SMODID, SPORT) on fabric 6429 * Parameters: 6430 * unit - StrataSwitch PCI device unit number (driver internal). 6431 * port - StrataSwitch port number (-1 = All ports) 6432 * fmod - Fabric Module Identifier 6433 * smod - Switch Module Identifier 6434 * sport - Switch Module Base Port 6435 * nports - Number of ports on switch device with fmod. 6436 * (0 to remove previously added entry). 6437 * Returns: 6438 * BCM_E_NONE - Success. 6439 * BCM_E_XXX - Failure. 6440 * Notes: 6441 * Fabric only (BCM5675) 6442 */ 6443 6444 int 6445 bcm_esw_stk_fmod_smod_mapping_set(int unit, bcm_port_t port, 6446 bcm_module_t fmod, bcm_module_t smod, 6447 bcm_port_t sport, uint32 nports) 6448 { 6449 #if defined(LOCAL_MODMAP_SUPPORT) 6450 int rv=BCM_E_NONE; 6451 #if defined(BCM_HERCULES_SUPPORT) 6452 mem_ing_modmap_entry_t immap; 6453 mem_egr_modmap_entry_t emmap; 6454 int bk=-1, blk; 6455 int i, found; 6456 uint32 fval; 6457 uint32 thresh; 6458 soc_field_t tf[] = {THRESH_Af, THRESH_Bf, THRESH_Cf, INVALIDf}; 6459 soc_field_t pf[] = {PORTOFF_Af, PORTOFF_Bf, PORTOFF_Cf, PORTOFF_Df}; 6460 soc_field_t mf[] = {MOD_Af, MOD_Bf, MOD_Cf, MOD_Df, INVALIDf}; 6461 #endif 6462 6463 BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_fmod_smod_mapping_set); 6464 6465 LOG_VERBOSE(BSL_LS_BCM_STK, 6466 (BSL_META_U(unit, 6467 "STK unit %d port %d: Mapping fmod %d to smod %d sport %d " 6468 "for %d ports\n"), unit, port, fmod, smod, sport, nports)); 6469 6470 FMOD_RANGE_CHECK(fmod); 6471 SMOD_RANGE_CHECK(smod); 6472 MOD_MAP_DATA_CHECK(unit); 6473 6474 if (BCM_GPORT_IS_SET(port)) { 6475 BCM_IF_ERROR_RETURN( 6476 bcm_esw_port_local_get(unit, port, &port)); 6477 } 6478 6479 if (port >= 0) { 6480 if (!IS_HG_PORT(unit, port)) { 6481 return BCM_E_PARAM; 6482 } 6483 #if defined(BCM_HERCULES_SUPPORT) 6484 bk = SOC_PORT_BLOCK(unit, port); 6485 #endif 6486 } 6487 6488 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 6489 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 6490 int group; 6491 6492 /* After range checks, proceed */ 6493 if (port >= 0) { 6494 /* Determine group offsets for the tables */ 6495 BCM_IF_ERROR_RETURN 6496 (bcm_esw_stk_port_modmap_group_get(unit, port, &group)); 6497 if ((group < 0) || (group > _XGS3_MODMAP_GROUPS_MAX)) { 6498 return BCM_E_PARAM; 6499 } 6500 return _bcm_stk_fmod_smod_mapping_group_set(unit, group, fmod, 6501 smod, sport, nports); 6502 } else { 6503 for (group = 0; group <= _XGS3_MODMAP_GROUPS_MAX; group++) { 6504 rv = _bcm_stk_fmod_smod_mapping_group_set(unit, group, fmod, 6505 smod, sport, nports); 6506 if (rv < 0) { 6507 break; 6508 } 6509 } 6510 return rv; 6511 } 6512 } 6513 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */ 6514 #if defined(BCM_HERCULES_SUPPORT) 6515 if (nports != 0) { 6516 SPORT_RANGE_CHECK((sport + nports - 1)); 6517 6518 sal_memset(&emmap, 0, sizeof(emmap)); 6519 soc_MEM_EGR_MODMAPm_field_set(unit, &emmap, 6520 PORT_OFFf, (uint32 *)&sport); 6521 soc_MEM_EGR_MODMAPm_field_set(unit, &emmap, 6522 MODf, (uint32 *)&smod); 6523 thresh = sport + nports - 1; 6524 6525 ESW_STK_LOCK; 6526 SOC_MEM_BLOCK_ITER(unit, MEM_ING_MODMAPm, blk) { 6527 if ((port >= 0) && (bk != blk)) { 6528 continue; 6529 } 6530 6531 if ((rv = READ_MEM_ING_MODMAPm(unit, blk, smod, &immap)) >= 0) { 6532 6533 found = 0; 6534 for(i = 0; mf[i] != INVALIDf; i++) { 6535 int p; 6536 soc_MEM_ING_MODMAPm_field_get(unit, &immap, mf[i], &fval); 6537 p = SOC_BLOCK_PORT(unit, blk); 6538 if (fval == 0) { 6539 if (fmod==0) { 6540 mod_map_data[unit]->fmod0[p] = smod+1; 6541 break; /* Found a slot for fmod 0 */ 6542 } 6543 if ((mod_map_data[unit]->fmod0[p]) && 6544 ((mod_map_data[unit]->fmod0[p] == (smod+1))) && 6545 !(found)) { 6546 found=1; /* This is fmod 0 */ 6547 } else { 6548 break; /* Found a slot */ 6549 } 6550 } 6551 } 6552 6553 if (mf[i] != INVALIDf) { 6554 for(; i > 0; i--) { 6555 soc_MEM_ING_MODMAPm_field_get( 6556 unit, &immap, tf[i - 1], &fval); 6557 /* THRESH_A < THRESH_B < THRESH_C */ 6558 if (fval > thresh) { 6559 if (tf[i] != INVALIDf) { 6560 soc_MEM_ING_MODMAPm_field_set( 6561 unit, &immap, tf[i], &fval); 6562 } else { 6563 mod_map_data[unit]->thresh_d[smod] = fval; 6564 } 6565 soc_MEM_ING_MODMAPm_field_get( 6566 unit, &immap, pf[i - 1], &fval); 6567 soc_MEM_ING_MODMAPm_field_set( 6568 unit, &immap, pf[i], &fval); 6569 soc_MEM_ING_MODMAPm_field_get( 6570 unit, &immap, mf[i - 1], &fval); 6571 soc_MEM_ING_MODMAPm_field_set( 6572 unit, &immap, mf[i], &fval); 6573 } else { 6574 break; 6575 } 6576 } 6577 6578 if (tf[i] != INVALIDf) { 6579 soc_MEM_ING_MODMAPm_field_set(unit, &immap, tf[i], &thresh); 6580 } else { 6581 mod_map_data[unit]->thresh_d[smod] = thresh; 6582 } 6583 soc_MEM_ING_MODMAPm_field_set(unit, &immap, 6584 pf[i], (uint32 *)&sport); 6585 soc_MEM_ING_MODMAPm_field_set(unit, &immap, 6586 mf[i], (uint32 *)&fmod); 6587 if ((rv = WRITE_MEM_EGR_MODMAPm(unit, blk, fmod, &emmap)) < 0) { 6588 break; 6589 } 6590 if ((rv = WRITE_MEM_ING_MODMAPm(unit, blk, smod, &immap)) < 0) { 6591 break; 6592 } 6593 } else { 6594 rv = BCM_E_PARAM; 6595 } 6596 } 6597 } 6598 ESW_STK_UNLOCK; 6599 } else { /* This is actually a delete */ 6600 ESW_STK_LOCK; 6601 SOC_MEM_BLOCK_ITER(unit, MEM_ING_MODMAPm, blk) { 6602 if ((port >= 0) && (bk != blk)) { 6603 continue; 6604 } 6605 6606 if ((rv = READ_MEM_EGR_MODMAPm(unit, blk, fmod, &emmap)) >= 0) { 6607 bcm_port_t o_sport = -1; 6608 bcm_module_t o_smod = -1; 6609 int j, p; 6610 6611 soc_MEM_EGR_MODMAPm_field_get(unit, &emmap, 6612 PORT_OFFf, (uint32 *)&o_sport); 6613 soc_MEM_EGR_MODMAPm_field_get(unit, &emmap, 6614 MODf, (uint32 *)&o_smod); 6615 sal_memset(&emmap, 0, sizeof(emmap)); 6616 if ((o_sport == sport) && (o_smod == smod)) { 6617 if ((rv = READ_MEM_ING_MODMAPm(unit, blk, smod, &immap)) >= 0) { 6618 for(i = 0; mf[i] != INVALIDf; i++) { 6619 soc_MEM_ING_MODMAPm_field_get(unit, &immap, mf[i], &fval); 6620 soc_MEM_ING_MODMAPm_field_get(unit, &immap, pf[i], &thresh); 6621 if ((fval == (uint32)fmod) && (thresh == (uint32)sport)) { 6622 if (tf[i] == INVALIDf) { 6623 mod_map_data[unit]->thresh_d[smod] = 0; 6624 fval = 0; 6625 soc_MEM_ING_MODMAPm_field_set(unit, &immap, mf[i], &fval); 6626 soc_MEM_ING_MODMAPm_field_set(unit, &immap, pf[i], &fval); 6627 } else { 6628 for (j = i; mf[j+1] != INVALIDf; j++) { 6629 soc_MEM_ING_MODMAPm_field_get(unit, &immap, pf[j+1], &fval); 6630 soc_MEM_ING_MODMAPm_field_set(unit, &immap, pf[j], &fval); 6631 soc_MEM_ING_MODMAPm_field_get(unit, &immap,mf[j+1], &fval); 6632 soc_MEM_ING_MODMAPm_field_set(unit, &immap, mf[j], &fval); 6633 if (tf[j+1] != INVALIDf) { 6634 soc_MEM_ING_MODMAPm_field_get(unit, &immap, tf[j+1], &fval); 6635 soc_MEM_ING_MODMAPm_field_set(unit, &immap, tf[j], &fval); 6636 } 6637 } 6638 fval = 0; 6639 soc_MEM_ING_MODMAPm_field_set(unit, &immap, pf[j], &fval); 6640 soc_MEM_ING_MODMAPm_field_set(unit, &immap, mf[j], &fval); 6641 soc_MEM_ING_MODMAPm_field_set(unit, &immap, tf[j-1], &fval); 6642 } 6643 break; 6644 } 6645 } 6646 if (mf[i] == INVALIDf) { 6647 rv = BCM_E_INTERNAL; 6648 break; 6649 } 6650 6651 if ((rv = WRITE_MEM_EGR_MODMAPm(unit, blk, fmod, &emmap)) < 0) { 6652 break; 6653 } 6654 if ((rv = WRITE_MEM_ING_MODMAPm(unit, blk, smod, &immap)) < 0) { 6655 break; 6656 } 6657 6658 if (fmod==0) { 6659 p = SOC_BLOCK_PORT(unit, blk); 6660 mod_map_data[unit]->fmod0[p] = 0; 6661 } 6662 } 6663 } else { 6664 rv = BCM_E_PARAM; 6665 } 6666 } 6667 } 6668 ESW_STK_UNLOCK; 6669 } 6670 #endif /*BCM_HERCULES_SUPPORT */ 6671 6672 #ifdef BCM_WARM_BOOT_SUPPORT 6673 SOC_CONTROL_LOCK(unit); 6674 SOC_CONTROL(unit)->scache_dirty = 1; 6675 SOC_CONTROL_UNLOCK(unit); 6676 #endif 6677 6678 return(rv); 6679 #else 6680 return BCM_E_UNAVAIL; 6681 #endif /* MODMAP_SUPPORT */ 6682 } 6683 6684 #ifdef BCM_BRADLEY_SUPPORT 6685 int 6686 _bcm_stk_fmod_smod_mapping_group_get(int unit, bcm_port_t port, 6687 bcm_module_t fmod, bcm_module_t *smod, 6688 bcm_port_t *sport, uint32 *nports) 6689 { 6690 int rv; 6691 ing_mod_map_table_entry_t immap; 6692 egr_mod_map_table_entry_t emmap; 6693 uint32 fval; 6694 uint32 sp_val; 6695 int i, group, group_offset_ing, group_offset_egr; 6696 soc_field_t tf[] = {THRESH_Af, THRESH_Bf, THRESH_Cf, INVALIDf}; 6697 soc_field_t pf[] = {PORTOFF_Af, PORTOFF_Bf, PORTOFF_Cf, PORTOFF_Df}; 6698 soc_field_t mf[] = {MOD_Af, MOD_Bf, MOD_Cf, MOD_Df, INVALIDf}; 6699 6700 /* Determine group offsets for the tables */ 6701 BCM_IF_ERROR_RETURN 6702 (bcm_esw_stk_port_modmap_group_get(unit, port, &group)); 6703 6704 if (group != 0) { 6705 group_offset_ing = soc_mem_index_count(unit, ING_MOD_MAP_TABLEm) / 2; 6706 group_offset_egr = soc_mem_index_count(unit, EGR_MOD_MAP_TABLEm) / 2; 6707 } else { 6708 group_offset_ing = 0; 6709 group_offset_egr = 0; 6710 } 6711 6712 ESW_STK_LOCK; 6713 if ((rv = READ_EGR_MOD_MAP_TABLEm(unit, SOC_BLOCK_ANY, 6714 fmod + group_offset_egr, &emmap)) >= 0) { 6715 soc_EGR_MOD_MAP_TABLEm_field_get(unit, &emmap, 6716 PORT_OFFSETf, (uint32 *)sport); 6717 soc_EGR_MOD_MAP_TABLEm_field_get(unit, &emmap, 6718 MODIDf, (uint32 *)smod); 6719 if ((rv = READ_ING_MOD_MAP_TABLEm(unit, SOC_BLOCK_ANY, 6720 *smod + group_offset_ing, &immap)) >= 0) { 6721 for(i = 0; mf[i] != INVALIDf; i++) { 6722 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, mf[i], &fval); 6723 soc_ING_MOD_MAP_TABLEm_field_get(unit, &immap, pf[i], &sp_val); 6724 if ((fval == (uint32)fmod) && ((uint32)*sport == sp_val)) { 6725 if (tf[i] != INVALIDf) { 6726 soc_ING_MOD_MAP_TABLEm_field_get( 6727 unit, &immap, tf[i], &fval); 6728 } else { 6729 fval = mod_map_data[unit]->thresh_d[*smod]; 6730 } 6731 *nports = fval - sp_val + 1; 6732 break; /* Found */ 6733 } 6734 } 6735 if (mf[i] == INVALIDf || 6736 ((fmod==0) && (mod_map_data[unit]->fmod0[group] != (*smod+1)))) { 6737 rv = BCM_E_NOT_FOUND; 6738 } 6739 } 6740 } 6741 ESW_STK_UNLOCK; 6742 6743 return(rv); 6744 } 6745 #endif /* BCM_BRADLEY_SUPPORT */ 6746 6747 /* 6748 * Function: 6749 * bcm_stk_fmod_smod_mapping_get 6750 * Purpose: 6751 * Get the (SMODID, BASE_SPORT) and num ports associated with 6752 * switch device with fmod 6753 * Parameters: 6754 * unit - StrataSwitch PCI device unit number (driver internal). 6755 * port - StrataSwitch port number 6756 * fmod - Fabric Module Identifier 6757 * smod - (OUT) Switch Module Identifier 6758 * sport - (OUT) Switch Module Base Port 6759 * nports - (OUT) Number of ports on switch device with fmod. 6760 * Returns: 6761 * BCM_E_NONE - Success. 6762 * BCM_E_XXX - Failure. 6763 * Notes: 6764 * Fabric only (BCM5675) 6765 */ 6766 6767 int 6768 bcm_esw_stk_fmod_smod_mapping_get(int unit, bcm_port_t port, 6769 bcm_module_t fmod, bcm_module_t *smod, 6770 bcm_port_t *sport, uint32 *nports) 6771 { 6772 #if defined(LOCAL_MODMAP_SUPPORT) 6773 int rv = BCM_E_UNAVAIL; 6774 #if defined(BCM_HERCULES_SUPPORT) 6775 mem_ing_modmap_entry_t immap; 6776 mem_egr_modmap_entry_t emmap; 6777 uint32 fval; 6778 uint32 sp_val; 6779 int blk; 6780 int p; 6781 int i; 6782 soc_field_t tf[] = {THRESH_Af, THRESH_Bf, THRESH_Cf, INVALIDf}; 6783 soc_field_t pf[] = {PORTOFF_Af, PORTOFF_Bf, PORTOFF_Cf, PORTOFF_Df}; 6784 soc_field_t mf[] = {MOD_Af, MOD_Bf, MOD_Cf, MOD_Df, INVALIDf}; 6785 #endif 6786 BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_fmod_smod_mapping_get); 6787 6788 if (BCM_GPORT_IS_SET(port)) { 6789 BCM_IF_ERROR_RETURN( 6790 bcm_esw_port_local_get(unit, port, &port)); 6791 } 6792 6793 if (!IS_HG_PORT(unit, port)) { 6794 return BCM_E_PARAM; 6795 } 6796 6797 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 6798 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 6799 /* After range checks, proceed */ 6800 return _bcm_stk_fmod_smod_mapping_group_get(unit, port, fmod, smod, 6801 sport, nports); 6802 } 6803 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */ 6804 6805 #if defined(BCM_HERCULES_SUPPORT) 6806 blk = SOC_PORT_BLOCK(unit, port); 6807 6808 ESW_STK_LOCK; 6809 if ((rv = READ_MEM_EGR_MODMAPm(unit, blk, fmod, &emmap)) >= 0) { 6810 soc_MEM_EGR_MODMAPm_field_get(unit, &emmap, 6811 PORT_OFFf, (uint32 *)sport); 6812 soc_MEM_EGR_MODMAPm_field_get(unit, &emmap, 6813 MODf, (uint32 *)smod); 6814 if ((rv = READ_MEM_ING_MODMAPm(unit, blk, *smod, &immap)) >= 0) { 6815 for(i = 0; mf[i] != INVALIDf; i++) { 6816 soc_MEM_ING_MODMAPm_field_get(unit, &immap, mf[i], &fval); 6817 soc_MEM_ING_MODMAPm_field_get(unit, &immap, pf[i], &sp_val); 6818 if ((fval == (uint32)fmod) && ((uint32)*sport == sp_val)) { 6819 if (tf[i] != INVALIDf) { 6820 soc_MEM_ING_MODMAPm_field_get( 6821 unit, &immap, tf[i], &fval); 6822 } else { 6823 fval = mod_map_data[unit]->thresh_d[*smod]; 6824 } 6825 *nports = fval - sp_val + 1; 6826 break; /* Found */ 6827 } 6828 } 6829 p = SOC_BLOCK_PORT(unit, blk); 6830 if (mf[i] == INVALIDf || 6831 ((fmod==0) && (mod_map_data[unit]->fmod0[p] != (*smod+1)))) { 6832 rv = BCM_E_NOT_FOUND; 6833 } 6834 } 6835 } 6836 ESW_STK_UNLOCK; 6837 #endif /* BCM_HERCULES_SUPPORT */ 6838 return(rv); 6839 #else 6840 return BCM_E_UNAVAIL; 6841 #endif /* MODMAP_SUPPORT */ 6842 } 6843 #if defined(BCM_METROLITE_SUPPORT) 6844 /* 6845 * Function: 6846 * _bcm_metrolite_stk_port_modmap_group_set 6847 * Purpose: 6848 * similar to bcm_stk_port_modmap_group_set, 6849 * but metrolite has different register formats for 6850 * ING_MODMAP_CTRL and EGR_MODMAP_CTRL 6851 */ 6852 int 6853 _bcm_metrolite_stk_port_modmap_group_set(int unit, bcm_port_t port, int group) 6854 { 6855 uint32 reg32, oreg32; 6856 int rv; 6857 if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) { 6858 reg32 = oreg32; 6859 soc_reg_field_set(unit, ING_MODMAP_CTRLr, ®32, 6860 ING_MOD_MAP_IDf, group ? 1 : 0); 6861 if (reg32 != oreg32) { 6862 rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32); 6863 if (rv >= 0) { 6864 /*ING and EGR Registers will be sync. No need to 6865 check again if value changed. */ 6866 rv = READ_EGR_MODMAP_CTRLr(unit, port, ®32); 6867 if (rv < 0) { 6868 ESW_STK_UNLOCK; 6869 return rv; 6870 } 6871 soc_reg_field_set(unit, EGR_MODMAP_CTRLr, ®32, 6872 EGR_MOD_MAP_IDf, group ? 1 : 0); 6873 rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32); 6874 } 6875 } 6876 } 6877 #ifdef BCM_WARM_BOOT_SUPPORT 6878 SOC_CONTROL_LOCK(unit); 6879 SOC_CONTROL(unit)->scache_dirty = 1; 6880 SOC_CONTROL_UNLOCK(unit); 6881 #endif 6882 return rv; 6883 } 6884 #endif 6885 /* 6886 * Function: 6887 * bcm_stk_port_modmap_group_set 6888 * Purpose: 6889 * Assign module mapping group for port to use 6890 * Parameters: 6891 * unit - StrataSwitch PCI device unit number (driver internal). 6892 * port - StrataSwitch port number (-1 = All ports) 6893 * group - Module mapping group 6894 * Returns: 6895 * BCM_E_NONE - Success. 6896 * BCM_E_XXX - Failure. 6897 * Notes: 6898 * Fabric only 6899 */ 6900 6901 int 6902 bcm_esw_stk_port_modmap_group_set(int unit, bcm_port_t port, int group) 6903 { 6904 #if defined(LOCAL_MODMAP_SUPPORT) 6905 int rv = 0; 6906 BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_port_modmap_group_set); 6907 6908 if (BCM_GPORT_IS_SET(port)) { 6909 BCM_IF_ERROR_RETURN( 6910 bcm_esw_port_local_get(unit, port, &port)); 6911 } 6912 6913 if (!IS_HG_PORT(unit, port)) { 6914 return BCM_E_PARAM; 6915 } 6916 #if defined(BCM_METROLITE_SUPPORT) 6917 if (SOC_IS_METROLITE(unit)) { 6918 if ((group < 0) || (group > _XGS3_MODMAP_GROUPS_MAX)) { 6919 return BCM_E_PARAM; 6920 } 6921 ESW_STK_LOCK; 6922 rv = _bcm_metrolite_stk_port_modmap_group_set(unit, port, group); 6923 ESW_STK_UNLOCK; 6924 return rv; 6925 } 6926 #endif 6927 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 6928 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 6929 uint32 reg32, oreg32; 6930 6931 if ((group < 0) || (group > _XGS3_MODMAP_GROUPS_MAX)) { 6932 return BCM_E_PARAM; 6933 } 6934 6935 ESW_STK_LOCK; 6936 6937 if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) { 6938 reg32 = oreg32; 6939 soc_reg_field_set(unit, ING_MODMAP_CTRLr, ®32, 6940 ING_MOD_MAP_IDf, group ? 1 : 0); 6941 if (reg32 != oreg32) { 6942 rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32); 6943 if (rv >= 0) { 6944 /* We must keep the ingress and egress copies in sync */ 6945 rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32); 6946 } 6947 } 6948 } 6949 ESW_STK_UNLOCK; 6950 } else 6951 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */ 6952 { 6953 /* Only identity mapping allowed */ 6954 if (group != (port - 1)) { 6955 return BCM_E_PARAM; 6956 } 6957 } 6958 6959 #ifdef BCM_WARM_BOOT_SUPPORT 6960 SOC_CONTROL_LOCK(unit); 6961 SOC_CONTROL(unit)->scache_dirty = 1; 6962 SOC_CONTROL_UNLOCK(unit); 6963 #endif 6964 6965 return BCM_E_NONE; 6966 #else 6967 return BCM_E_UNAVAIL; 6968 #endif /* MODMAP_SUPPORT */ 6969 } 6970 6971 /* 6972 * Function: 6973 * bcm_stk_port_modmap_group_get 6974 * Purpose: 6975 * Retrieve module mapping group selected for port 6976 * Parameters: 6977 * unit - StrataSwitch PCI device unit number (driver internal). 6978 * port - StrataSwitch port number (-1 = All ports) 6979 * group - (OUT) Module mapping group 6980 * Returns: 6981 * BCM_E_NONE - Success. 6982 * BCM_E_XXX - Failure. 6983 * Notes: 6984 * Fabric only 6985 */ 6986 6987 int 6988 bcm_esw_stk_port_modmap_group_get(int unit, bcm_port_t port, int *group) 6989 { 6990 #if defined(LOCAL_MODMAP_SUPPORT) 6991 BCM_MODMAP_FEATURE_CHECK(unit, bcm_esw_stk_port_modmap_group_get); 6992 6993 if (BCM_GPORT_IS_SET(port)) { 6994 BCM_IF_ERROR_RETURN( 6995 bcm_esw_port_local_get(unit, port, &port)); 6996 } 6997 6998 if (!IS_HG_PORT(unit, port)) { 6999 return BCM_E_PARAM; 7000 } 7001 7002 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 7003 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 7004 uint32 oreg32; 7005 SOC_IF_ERROR_RETURN(READ_ING_MODMAP_CTRLr(unit, port, &oreg32)); 7006 *group = soc_reg_field_get(unit, ING_MODMAP_CTRLr, oreg32, 7007 ING_MOD_MAP_IDf); 7008 } else 7009 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */ 7010 { 7011 *group = port - 1; 7012 } 7013 return BCM_E_NONE; 7014 #else 7015 return BCM_E_UNAVAIL; 7016 #endif /* MODMAP_SUPPORT */ 7017 } 7018 7019 /* 7020 * Function: 7021 * bcm_stk_port_modmap_group_max_get 7022 * Purpose: 7023 * Retrieve maximum module mapping group allowed on device 7024 * Parameters: 7025 * unit - StrataSwitch PCI device unit number (driver internal). 7026 * max_group - (OUT) Module mapping group 7027 * Returns: 7028 * BCM_E_NONE - Success. 7029 * BCM_E_XXX - Failure. 7030 * Notes: 7031 * Fabric only 7032 */ 7033 7034 int 7035 bcm_esw_stk_port_modmap_group_max_get(int unit, int *max_group) 7036 { 7037 #if defined(LOCAL_MODMAP_SUPPORT) 7038 BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_port_modmap_group_max_get); 7039 7040 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 7041 *max_group = _XGS3_MODMAP_GROUPS_MAX; 7042 } else { 7043 *max_group = SOC_MAX_NUM_PORTS - 1; 7044 } 7045 7046 return BCM_E_NONE; 7047 #else 7048 return BCM_E_UNAVAIL; 7049 #endif /* MODMAP_SUPPORT */ 7050 } 7051 7052 /* 7053 * Function: 7054 * bcm_stk_modmap_enable_set 7055 * Purpose: 7056 * Enable/Disable Modid mapping on a given fabric port. 7057 * Parameters: 7058 * unit - StrataSwitch PCI device unit number (driver internal). 7059 * port - StrataSwitch port number 7060 * enable - Modmap enabled flag. 1 = enabled 0 = disabled 7061 * Returns: 7062 * BCM_E_NONE - Success. 7063 * BCM_E_XXX - Failure. 7064 * Notes: 7065 * Fabric only (BCM5675) 7066 */ 7067 7068 int 7069 bcm_esw_stk_modmap_enable_set(int unit, 7070 bcm_port_t port, int enable) 7071 { 7072 #if defined(LOCAL_MODMAP_SUPPORT) 7073 uint32 reg32, oreg32; 7074 int rv; 7075 7076 BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_modmap_enable_set); 7077 7078 LOG_VERBOSE(BSL_LS_BCM_STK, 7079 (BSL_META_U(unit, 7080 "STK %d: %sabling mod mapping port %d\n"), 7081 unit, enable ? "En" : "Dis", port)); 7082 7083 if (BCM_GPORT_IS_SET(port)) { 7084 BCM_IF_ERROR_RETURN( 7085 bcm_esw_port_local_get(unit, port, &port)); 7086 } 7087 7088 7089 if (!IS_ST_PORT(unit, port)) { 7090 return BCM_E_PORT; 7091 } 7092 7093 ESW_STK_LOCK; 7094 #if defined(BCM_METROLITE_SUPPORT) 7095 if (SOC_IS_METROLITE(unit)) { 7096 if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) { 7097 reg32 = oreg32; 7098 soc_reg_field_set(unit, ING_MODMAP_CTRLr, ®32, 7099 ING_MAP_ENf, enable ? 1 : 0); 7100 if (reg32 != oreg32) { 7101 rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32); 7102 if (rv >= 0) { 7103 /*ING and EGR Registers will be sync. No need to 7104 check again if value changed. */ 7105 rv = READ_EGR_MODMAP_CTRLr(unit, port, ®32); 7106 if (rv < 0) { 7107 ESW_STK_UNLOCK; 7108 return rv; 7109 } 7110 soc_reg_field_set(unit, EGR_MODMAP_CTRLr, ®32, 7111 EGR_MAP_ENf, enable?1:0); 7112 rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32); 7113 } 7114 } 7115 } 7116 ESW_STK_UNLOCK; 7117 return rv; 7118 } 7119 #endif 7120 7121 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 7122 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 7123 if ((rv = READ_ING_MODMAP_CTRLr(unit, port, &oreg32)) >= 0) { 7124 reg32 = oreg32; 7125 soc_reg_field_set(unit, ING_MODMAP_CTRLr, ®32, 7126 ING_MAP_ENf, enable ? 1 : 0); 7127 if (reg32 != oreg32) { 7128 rv = WRITE_ING_MODMAP_CTRLr(unit, port, reg32); 7129 if (rv >= 0) { 7130 /* We must keep the ingress and egress copies in sync */ 7131 rv = WRITE_EGR_MODMAP_CTRLr(unit, port, reg32); 7132 } 7133 } 7134 } 7135 } else 7136 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */ 7137 { 7138 #if defined(BCM_HERCULES_SUPPORT) 7139 if ((rv = READ_MODMAP_CTRLr(unit, port, &oreg32)) >=0 ) { 7140 reg32 = oreg32; 7141 soc_reg_field_set(unit, MODMAP_CTRLr, ®32, 7142 EGR_MAP_ENf, (enable)?1:0); 7143 soc_reg_field_set(unit, MODMAP_CTRLr, ®32, 7144 ING_MAP_ENf, (enable)?1:0); 7145 if (reg32 != oreg32) { 7146 rv = WRITE_MODMAP_CTRLr(unit, port, reg32); 7147 } 7148 } 7149 #endif 7150 } 7151 ESW_STK_UNLOCK; 7152 7153 return(BCM_E_NONE); 7154 #else 7155 return BCM_E_UNAVAIL; 7156 #endif /* MODMAP_SUPPORT */ 7157 } 7158 7159 /* 7160 * Function: 7161 * bcm_stk_modmap_enable_get 7162 * Purpose: 7163 * Get Modid mapping Enable/Disable state on a given fabric port. 7164 * Parameters: 7165 * unit - StrataSwitch PCI device unit number (driver internal). 7166 * port - (OUT) StrataSwitch port number 7167 * enable - (OUT) Modmap enabled flag. 1 = enabled 0 = disabled 7168 * Returns: 7169 * BCM_E_NONE - Success. 7170 * BCM_E_XXX - Failure. 7171 * Notes: 7172 * Fabric only (BCM5675) 7173 */ 7174 7175 int 7176 bcm_esw_stk_modmap_enable_get(int unit, 7177 bcm_port_t port, int *enable) 7178 { 7179 #if defined(LOCAL_MODMAP_SUPPORT) 7180 #if defined(BCM_HERCULES_SUPPORT) 7181 uint32 oreg32; 7182 #endif 7183 uint32 i_enable; 7184 uint32 e_enable; 7185 7186 BCM_MODMAP_FEATURE_CHECK(unit, bcm_stk_modmap_enable_get); 7187 if (!IS_ST_PORT(unit, port)) { 7188 return BCM_E_PORT; 7189 } 7190 7191 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 7192 if (SOC_IS_HBX(unit) || SOC_IS_TR_VL(unit)) { 7193 uint32 oreg32; 7194 7195 SOC_IF_ERROR_RETURN(READ_ING_MODMAP_CTRLr(unit, port, &oreg32)); 7196 i_enable = soc_reg_field_get(unit, ING_MODMAP_CTRLr, oreg32, 7197 ING_MAP_ENf); 7198 SOC_IF_ERROR_RETURN(READ_EGR_MODMAP_CTRLr(unit, port, &oreg32)); 7199 e_enable = soc_reg_field_get(unit, EGR_MODMAP_CTRLr, oreg32, 7200 EGR_MAP_ENf); 7201 } else 7202 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */ 7203 { 7204 #if defined(BCM_HERCULES_SUPPORT) 7205 SOC_IF_ERROR_RETURN(READ_MODMAP_CTRLr(unit, port, &oreg32)); 7206 i_enable = soc_reg_field_get(unit, MODMAP_CTRLr, oreg32, ING_MAP_ENf); 7207 e_enable = soc_reg_field_get(unit, MODMAP_CTRLr, oreg32, EGR_MAP_ENf); 7208 #else 7209 return BCM_E_UNAVAIL; 7210 #endif 7211 } 7212 *enable = (i_enable && e_enable); 7213 if ((i_enable || e_enable) != *enable) { 7214 return(BCM_E_INTERNAL); /* Error if only Ing or Egr map enabled */ 7215 } 7216 7217 return(BCM_E_NONE); 7218 #else 7219 return BCM_E_UNAVAIL; 7220 #endif /* MODMAP_SUPPORT */ 7221 } 7222 7223 /* 7224 * Module ID Mapping on Switch Chips 7225 * 7226 * The programming of module/port destinations that are external to a 7227 * switch chip must match the mapping that is programmed into the 7228 * associated fabric chips. Rather than trying to provide an 7229 * arbitrarily complex set of APIs to do this for the application, a 7230 * callback can be registered to map each module/port pair when it is 7231 * stored into hardware or fetched from hardware. 7232 * 7233 * For more information, refer to $SDK/doc/modid-mapping.txt. 7234 */ 7235 7236 bcm_stk_modmap_cb_t _bcm_stk_modmap_cb[BCM_MAX_NUM_UNITS]; 7237 7238 /* 7239 * Function: 7240 * bcm_stk_modmap_register 7241 * Purpose: 7242 * Register module ID mapping/unmapping callback function 7243 * Parameters: 7244 * unit - SOC unit # 7245 * func - User callback function for module ID mapping/unmapping 7246 */ 7247 int 7248 bcm_esw_stk_modmap_register(int unit, bcm_stk_modmap_cb_t func) 7249 { 7250 if (!SOC_UNIT_VALID(unit)) { 7251 return BCM_E_UNIT; 7252 } 7253 if (!SOC_IS_XGS_SWITCH(unit)) { 7254 return BCM_E_PARAM; 7255 } 7256 7257 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 7258 7259 _bcm_stk_modmap_cb[unit] = func; 7260 return BCM_E_NONE; 7261 } 7262 7263 /* 7264 * Function: 7265 * bcm_stk_modmap_unregister 7266 * Purpose: 7267 * Unregister module ID mapping/unmapping callback function 7268 * Parameters: 7269 * unit - SOC unit # 7270 */ 7271 int 7272 bcm_esw_stk_modmap_unregister(int unit) 7273 { 7274 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 7275 7276 _bcm_stk_modmap_cb[unit] = NULL; 7277 return BCM_E_NONE; 7278 } 7279 7280 /* 7281 * Function: 7282 * _bcm_stk_modmap_map 7283 * Purpose: 7284 * Internal function to call module ID mapping/unmapping callback function 7285 * Parameters: 7286 * unit - (IN) SOC unit # 7287 * setget - (IN) Mapping direction identifier BCM_STK_MODMAP_GET or BCM_STK_MODMAP_SET 7288 * mod_in - (IN) Module Id to map 7289 * port_in - (IN) Physical port to map no GPORT accepted 7290 * mod_out - (OUT) Module Id after mapping 7291 * port_out - (OUT) Physical port after mapping not a GPORT 7292 * Notes: 7293 * This function is called from within the BCM API implementations 7294 * whenever module ID mapping is needed. 7295 */ 7296 int 7297 _bcm_esw_stk_modmap_map(int unit, int setget, 7298 bcm_module_t mod_in, bcm_port_t port_in, 7299 bcm_module_t *mod_out, bcm_port_t *port_out) 7300 { 7301 int rv = BCM_E_NONE; 7302 bcm_module_t mod; 7303 bcm_port_t port; 7304 7305 if (!SOC_UNIT_VALID(unit)) { 7306 return BCM_E_UNIT; 7307 } 7308 7309 if ((port_in != -1) && (setget == BCM_STK_MODMAP_GET)) { 7310 /* Before the mapping, if multiple modid mode is enabled, adjust the 7311 * mod/port such that any port number above modport_max setting is 7312 * considered to be in the next module. 7313 */ 7314 7315 if (NUM_MODID(unit) > 1) { 7316 #if defined(BCM_TOMAHAWK_SUPPORT) 7317 /* Call asymmetric dual modid mapping function to split the 7318 * ports asymmetrically between two modids. 7319 */ 7320 if (soc_feature(unit, soc_feature_asymmetric_dual_modid) && 7321 port_in > SOC_MODPORT_MAX_FIRST(unit)) { 7322 BCM_IF_ERROR_RETURN ( 7323 _bcm_esw_stk_asymmetric_dual_modmap_map(unit, setget, 7324 &mod_in, &port_in)); 7325 } else 7326 #endif /* BCM_TOMAHAWK_SUPPORT */ 7327 if (port_in > SOC_MODPORT_MAX(unit)) { 7328 bcm_module_t my_modid; 7329 BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid)); 7330 if ((mod_in == my_modid) && (BCM_MODID_INVALID != mod_in)) { 7331 mod_in += port_in / (SOC_MODPORT_MAX(unit) + 1); 7332 port_in %= (SOC_MODPORT_MAX(unit) + 1); 7333 } 7334 } 7335 } 7336 } 7337 7338 if ((_bcm_stk_modmap_cb[unit] != NULL) && (BCM_MODID_INVALID != mod_in)) { 7339 rv = (*_bcm_stk_modmap_cb[unit])(unit, setget, 7340 mod_in, port_in, 7341 &mod, &port); 7342 if (rv < 0) { 7343 mod = mod_in; 7344 port = port_in; 7345 } 7346 } else { 7347 /* default identity mapping */ 7348 mod = mod_in; 7349 port = port_in; 7350 } 7351 if ((rv >= 0) && (port_in != -1) && (setget == BCM_STK_MODMAP_SET)) { 7352 /* After the mapping, if multiply-modid mode is enabled, adjust the 7353 * mod/port such that all ports are considered to be in the first 7354 * module. 7355 */ 7356 if (NUM_MODID(unit) > 1) { 7357 bcm_module_t my_modid; 7358 int isLocal; 7359 BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid)); 7360 if (BCM_MODID_INVALID != my_modid){ 7361 BCM_IF_ERROR_RETURN 7362 (_bcm_esw_modid_is_local(unit, mod, &isLocal)); 7363 if (isLocal) { 7364 #if defined(BCM_TOMAHAWK_SUPPORT) 7365 /* Call asymmetric dual modid unmapping function */ 7366 if (soc_feature(unit, soc_feature_asymmetric_dual_modid)) { 7367 BCM_IF_ERROR_RETURN ( 7368 _bcm_esw_stk_asymmetric_dual_modmap_map(unit, 7369 setget, &mod_in, &port_in)); 7370 port = port_in; 7371 mod = my_modid; 7372 } else 7373 #endif /* BCM_TOMAHAWK_SUPPORT */ 7374 { 7375 port += (mod - my_modid) * (SOC_MODPORT_MAX(unit) + 1); 7376 mod = my_modid; 7377 } 7378 } 7379 } 7380 } 7381 } 7382 if (port_out != NULL) { 7383 *port_out = port; 7384 } 7385 if (mod_out != NULL) { 7386 *mod_out = mod; 7387 } 7388 7389 return rv; 7390 } 7391 7392 7393 #ifdef BCM_TOMAHAWK_SUPPORT 7394 /* 7395 * Function: 7396 * _bcm_esw_stk_asymmetric_dual_modmap_map 7397 * Purpose: 7398 * Internal function for asymmetric dual module ID mapping/unmapping 7399 * Parameters: 7400 * unit - (IN) SOC unit # 7401 * setget - (IN) Mapping direction identifier BCM_STK_MODMAP_GET 7402 or BCM_STK_MODMAP_SET 7403 * mod_in - (IN) Module Id to map 7404 * port_in - (IN) Physical port to map no GPORT accepted 7405 * mod_out - (OUT) Module Id after mapping 7406 * port_out - (OUT) Physical port after mapping not a GPORT 7407 * Notes: 7408 * This function is called from within the BCM API implementations 7409 * whenever asymmetric dual module ID mapping is needed. 7410 */ 7411 int 7412 _bcm_esw_stk_asymmetric_dual_modmap_map(int unit, int setget, 7413 bcm_module_t *mod_in, bcm_port_t *port_in) 7414 { 7415 bcm_module_t my_modid; 7416 7417 /* Input parameters check. */ 7418 if (!SOC_UNIT_VALID(unit)) { 7419 return BCM_E_UNIT; 7420 } 7421 7422 /* Get local modulel ID */ 7423 BCM_IF_ERROR_RETURN (bcm_esw_stk_my_modid_get(unit, &my_modid)); 7424 7425 /* For TH, the port split used is (64 + 128(use 72)) between two modids. 7426 * Adjust mod/port such that any port number between modport_max_first 7427 * and modport_max considered to be in next module. 7428 */ 7429 if((*mod_in == my_modid) && (BCM_MODID_INVALID != *mod_in)) { 7430 if (setget == BCM_STK_MODMAP_GET && 7431 *port_in > SOC_MODPORT_MAX_FIRST(unit)) { 7432 *port_in += (SOC_MODPORT_MAX(unit) + 1) - 7433 (SOC_MODPORT_MAX_FIRST(unit) + 1); 7434 *mod_in += *port_in / (SOC_MODPORT_MAX(unit) + 1); 7435 *port_in %= (SOC_MODPORT_MAX(unit) + 1); 7436 } 7437 } 7438 7439 /* Adjust the mod/port such that all ports are considered to be in 7440 * the first module. 7441 */ 7442 if (setget == BCM_STK_MODMAP_SET) { 7443 *port_in += (*mod_in - my_modid) * (SOC_MODPORT_MAX_FIRST(unit) + 1); 7444 } 7445 7446 /* 7447 if (port_out != NULL) { 7448 *port_out = port_in; 7449 } 7450 if (mod_out != NULL) { 7451 *mod_out = mod_in; 7452 } 7453 */ 7454 7455 return (BCM_E_NONE); 7456 } 7457 #endif /* BCM_TOMAHAWK_SUPPORT */ 7458 7459 7460 /* 7461 * Function: 7462 * bcm_stk_modmap_map 7463 * Purpose: 7464 * Call module ID mapping/unmapping callback function 7465 * Parameters: 7466 * unit - SOC unit # 7467 * Notes: 7468 * This function is called from within the BCM API implementations 7469 * whenever module ID mapping is needed, but it can also be called 7470 * by the user application for informational purposes. 7471 */ 7472 int 7473 bcm_esw_stk_modmap_map(int unit, int setget, 7474 bcm_module_t mod_in, bcm_port_t port_in, 7475 bcm_module_t *mod_out, bcm_port_t *port_out) 7476 { 7477 bcm_port_t tmp_port; 7478 bcm_module_t tmp_modid; 7479 bcm_trunk_t tmp_tgid; 7480 int tmp_id, isGport; 7481 _bcm_gport_dest_t gport_st; 7482 7483 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 7484 7485 if (BCM_GPORT_IS_SET(port_in)) { 7486 BCM_IF_ERROR_RETURN( 7487 _bcm_esw_gport_resolve(unit, port_in, &tmp_modid, &tmp_port, 7488 &tmp_tgid, &tmp_id)); 7489 if ((BCM_TRUNK_INVALID != tmp_tgid) || 7490 (-1 != tmp_id)) { 7491 return BCM_E_PORT; 7492 } 7493 } else { 7494 tmp_port = port_in; 7495 tmp_modid = mod_in; 7496 } 7497 7498 BCM_IF_ERROR_RETURN( 7499 _bcm_esw_stk_modmap_map(unit, setget, tmp_modid, tmp_port, 7500 mod_out, port_out)); 7501 BCM_IF_ERROR_RETURN( 7502 bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport)); 7503 if (TRUE == isGport) { 7504 gport_st.modid = *mod_out; 7505 gport_st.port = *port_out; 7506 gport_st.gport_type = _SHR_GPORT_TYPE_MODPORT; 7507 BCM_IF_ERROR_RETURN( 7508 _bcm_esw_gport_construct(unit, &gport_st, port_out)); 7509 *mod_out = -1; 7510 } 7511 7512 return BCM_E_NONE; 7513 } 7514 7515 /**************************************************************** 7516 * 7517 * Procedures related to source module ID base indexing 7518 */ 7519 7520 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 7521 #if defined BCM_MONTEREY_SUPPORT 7522 STATIC int 7523 soc_egr_gpp_attribute_set(int unit, int base_index) 7524 { 7525 bcm_pbmp_t all_pbmp; 7526 bcm_port_t port = 0; 7527 int max_index = 0; 7528 7529 SOC_PBMP_CLEAR(all_pbmp); 7530 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 7531 7532 max_index = soc_mem_index_max(unit, EGR_GPP_ATTRIBUTESm); 7533 7534 PBMP_ITER(all_pbmp, port) { 7535 if (max_index < (base_index + port)) { 7536 continue; 7537 } 7538 SOC_IF_ERROR_RETURN( 7539 soc_mem_field32_modify(unit, EGR_GPP_ATTRIBUTESm, (base_index + port), 7540 EGR_LPORT_PROFILE_IDXf, port + 1)); 7541 } 7542 return SOC_E_NONE; 7543 7544 } 7545 #endif 7546 7547 /* 7548 * Function: 7549 * _src_mod_base_index_bk_init 7550 * Purpose: 7551 * Allocate and initialize data structures related to source modid base 7552 * indexing. 7553 * Parameters: 7554 * unit - (IN)SOC unit number. 7555 * Returns: 7556 * BCM_X_XXX 7557 */ 7558 int 7559 bcmi_esw_src_modid_base_index_bk_init(int unit) 7560 { 7561 int src_mod_port_tbl_size, i; 7562 soc_info_t *si=&SOC_INFO(unit); 7563 #if defined BCM_TRIDENT2PLUS_SUPPORT 7564 int entry_size = 0; 7565 void *default_entry = NULL; 7566 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 7567 7568 /* free memory space that is allocated before executing cmd rc */ 7569 _src_modid_base_index_bk_detach(unit); 7570 7571 if (src_modid_base_index_bk[unit] == NULL) { 7572 src_modid_base_index_bk[unit] = 7573 sal_alloc(sizeof(src_modid_base_index_bookkeeping_t), 7574 "src_modid_base_index_bk"); 7575 if (src_modid_base_index_bk[unit] == NULL) { 7576 return BCM_E_MEMORY; 7577 } 7578 } 7579 sal_memset(src_modid_base_index_bk[unit], 0, 7580 sizeof(src_modid_base_index_bookkeeping_t)); 7581 7582 src_modid_base_index_bk[unit]->num_ports = 7583 sal_alloc(sizeof(uint16) * (SOC_MODID_MAX(unit) + 1), 7584 "src_moid_base_index_bk num_ports array"); 7585 if (src_modid_base_index_bk[unit]->num_ports == NULL) { 7586 _src_modid_base_index_bk_detach(unit); 7587 return BCM_E_MEMORY; 7588 } 7589 sal_memset(src_modid_base_index_bk[unit]->num_ports, 0, 7590 sizeof(uint16) * (SOC_MODID_MAX(unit) + 1)); 7591 7592 src_mod_port_tbl_size = soc_mem_index_count(unit, src_mod_port_mems[0]); 7593 src_modid_base_index_bk[unit]->src_mod_port_table_bitmap = 7594 sal_alloc(SHR_BITALLOCSIZE(src_mod_port_tbl_size), 7595 "src_mod_port_table_bitmap"); 7596 if (src_modid_base_index_bk[unit]->src_mod_port_table_bitmap == NULL) { 7597 _src_modid_base_index_bk_detach(unit); 7598 return BCM_E_MEMORY; 7599 } 7600 sal_memset(src_modid_base_index_bk[unit]->src_mod_port_table_bitmap, 0, 7601 SHR_BITALLOCSIZE(src_mod_port_tbl_size)); 7602 7603 if(si->num_coe_modules != 0) { 7604 7605 /* Intialize the CoE module Id list */ 7606 src_modid_base_index_bk[unit]->coe_module_id_list = 7607 sal_alloc(sizeof(int) * si->num_coe_modules, 7608 "src_moid_base_index_bk coe_module_id_list array"); 7609 if (src_modid_base_index_bk[unit]->coe_module_id_list == NULL) { 7610 _src_modid_base_index_bk_detach(unit); 7611 return BCM_E_MEMORY; 7612 } 7613 7614 for (i=0; i < si->num_coe_modules; i++) { 7615 src_modid_base_index_bk[unit]->coe_module_id_list[i] = BCM_MODID_INVALID; 7616 } 7617 } 7618 7619 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 7620 /* Intialize the module Id type list */ 7621 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 7622 src_modid_base_index_bk[unit]->module_id_type_list = 7623 sal_alloc(sizeof(int) * si->num_modules, 7624 "src_moid_base_index_bk module_id_type_list array"); 7625 if (src_modid_base_index_bk[unit]->module_id_type_list == NULL) { 7626 _src_modid_base_index_bk_detach(unit); 7627 return BCM_E_MEMORY; 7628 } 7629 7630 for (i=0; i < si->num_modules; i++) { 7631 src_modid_base_index_bk[unit]->module_id_type_list[i] = 0; 7632 } 7633 7634 src_modid_base_index_bk[unit]->multi_nexthop_module_id_list = 7635 sal_alloc(sizeof(int) * si->num_modules, 7636 "src_moid_base_index_bk multi_nexthop_module_id_list array"); 7637 if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list == NULL) { 7638 _src_modid_base_index_bk_detach(unit); 7639 return BCM_E_MEMORY; 7640 } 7641 7642 for (i=0; i < si->num_modules; i++) { 7643 src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] = BCM_MODID_INVALID; 7644 } 7645 } 7646 #endif 7647 7648 #if defined BCM_TRIDENT2PLUS_SUPPORT 7649 if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) { 7650 /* For TD2P/Apache, all module IDs initially has to share the same 7651 * region in source mod table but it should not start with 0 as 7652 * when local MOD ID is configured it will also share the same range 7653 * and cause issues in HG packet processing. One way of handling it 7654 * is allowing the local MOD ID to get base idx past the default 7655 * range (i.e. after range of 0 to SOC_PORT_ADDR_MAX-1), but other 7656 * modules expect the base index of local MOD ID to be 0 especially 7657 * if doing upgrade from previous version of SDK code. Furthermore if 7658 * CoE subport feature exists then it would need first 618 entries 7659 * (331 for Apache) of source mod por table to support 106 logical ports 7660 * (75 for Apache) + 512 subports (256 for Apache), hence the local 7661 * MOD ID cannot be assigned base index past the SOC_PORT_ADDR_MAX-1 7662 * range. Hence to allow local MOD ID to get base index of 0 and 7663 * also to overcome HG packet processing issue, instead of blocking 7664 * range 0 to SOC_PORT_ADDR_MAX-1 for all module IDs to begin with 7665 * we ought to block SOC_PORT_ADDR_MAX entries from the end of the table 7666 */ 7667 src_modid_base_index_bk[unit]->default_base_idx = 7668 soc_mem_index_count(unit, src_mod_port_mems[0]) - 7669 (SOC_PORT_ADDR_MAX(unit) + 1); 7670 } else 7671 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 7672 { 7673 /* Initialize all MODBASE tables such that all module IDs initially 7674 * share the same region in source mod port tables, from entry 0 to 7675 * entry SOC_PORT_ADDR_MAX. A module ID will be allocated its own 7676 * region in source mod port tables as needed. 7677 */ 7678 src_modid_base_index_bk[unit]->default_base_idx = 0; 7679 } 7680 7681 if (!SOC_WARM_BOOT(unit)) { 7682 if(SOC_IS_KATANA(unit)) { 7683 if(soc_mem_is_valid(unit, SOURCE_TRUNK_MAP_MODBASEm)) { 7684 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, SOURCE_TRUNK_MAP_MODBASEm, 7685 MEM_BLOCK_ALL, 0)); 7686 } 7687 } 7688 #if defined BCM_TRIDENT2PLUS_SUPPORT 7689 else if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) { 7690 7691 for (i = 0; i < COUNTOF(src_modbase_mems); i++) { 7692 if(soc_mem_is_valid(unit, src_modbase_mems[i])) { 7693 entry_size = WORDS2BYTES( 7694 soc_mem_entry_words(unit, src_modbase_mems[i])); 7695 default_entry = 7696 soc_cm_salloc(unit, entry_size, "modbase table entry"); 7697 7698 if (default_entry == NULL) { 7699 return BCM_E_MEMORY; 7700 } 7701 7702 sal_memset(default_entry, 0x0, entry_size); 7703 sal_memcpy(default_entry, 7704 soc_mem_entry_null(unit, src_modbase_mems[i]), 7705 soc_mem_entry_bytes(unit, src_modbase_mems[i])); 7706 7707 soc_mem_field_set(unit, 7708 src_modbase_mems[i], 7709 (uint32 *) default_entry, 7710 (src_modbase_mems[i]==MODID_BASE_PTRm)?MODID_BASEf:BASEf, 7711 &src_modid_base_index_bk[unit]->default_base_idx); 7712 7713 SOC_IF_ERROR_CLEAN_RETURN( 7714 soc_mem_fill(unit, 7715 src_modbase_mems[i], MEM_BLOCK_ALL, default_entry), 7716 soc_cm_sfree(unit, default_entry)); 7717 7718 soc_cm_sfree(unit, default_entry); 7719 default_entry = NULL; 7720 #if defined BCM_MONTEREY_SUPPORT 7721 if (SOC_IS_MONTEREY(unit) && 7722 soc_feature(unit, soc_feature_xflow_macsec) && 7723 (src_modbase_mems[i] == EGR_GPP_ATTRIBUTES_MODBASEm)) { 7724 SOC_IF_ERROR_RETURN( 7725 soc_egr_gpp_attribute_set(unit, 7726 src_modid_base_index_bk[unit]->default_base_idx)); 7727 } 7728 #endif 7729 } 7730 } 7731 } 7732 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 7733 else { 7734 for (i = 0; i < COUNTOF(src_modbase_mems); i++) { 7735 if(soc_mem_is_valid(unit, src_modbase_mems[i])) { 7736 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, src_modbase_mems[i], 7737 MEM_BLOCK_ALL, 0)); 7738 } 7739 } 7740 } 7741 } 7742 7743 #if defined BCM_TRIDENT2PLUS_SUPPORT 7744 if (SOC_IS_TD2P_TT2P(unit)) { 7745 /* Reserve the range of entries in the port bitmap 7746 * First range is for its own logical ports and the 7747 * second range is for ports of non-configured MODs 7748 */ 7749 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0, BCM_STK_TD2P_NUM_LPORTS); 7750 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, 7751 src_modid_base_index_bk[unit]->default_base_idx, 7752 SOC_PORT_ADDR_MAX(unit) + 1); 7753 } else 7754 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 7755 #if defined BCM_TRIDENT3_SUPPORT 7756 if (SOC_IS_TRIDENT3X(unit)) { 7757 /* Reserve the range of entries in the port bitmap 7758 * First range is for its own logical ports and the 7759 * second range is for ports of non-configured MODs 7760 */ 7761 if (SOC_IS_TRIDENT3(unit)) { 7762 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0, 7763 TRIDENT3_DEV_PORTS_PER_DEV); 7764 } 7765 #if defined(BCM_MAVERICK2_SUPPORT) 7766 if (SOC_IS_MAVERICK2(unit)) { 7767 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0, 7768 MAVERICK2_DEV_PORTS_PER_DEV); 7769 } 7770 #endif 7771 #if defined(BCM_HELIX5_SUPPORT) 7772 if (SOC_IS_HELIX5(unit)) { 7773 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0, 7774 HELIX5_DEV_PORTS_PER_DEV); 7775 } 7776 #endif 7777 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, 7778 src_modid_base_index_bk[unit]->default_base_idx, 7779 SOC_PORT_ADDR_MAX(unit) + 1); 7780 } else 7781 #endif /* BCM_TRIDENT3_SUPPORT */ 7782 #if defined BCM_MONTEREY_SUPPORT 7783 if (SOC_IS_MONTEREY(unit)) { 7784 /* Reserve the range of entries in the port bitmap 7785 * First range is for its own logical ports and the 7786 * second range is for ports of non-configured MODs 7787 */ 7788 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0, BCM_STK_MONTEREY_NUM_LPORTS); 7789 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, 7790 src_modid_base_index_bk[unit]->default_base_idx, 7791 SOC_PORT_ADDR_MAX(unit) + 1); 7792 } else 7793 #endif /* BCM_MONTEREY_SUPPORT */ 7794 #if defined BCM_APACHE_SUPPORT 7795 if (SOC_IS_APACHE(unit)) { 7796 /* Reserve the range of entries in the port bitmap 7797 * First range is for its own logical ports and the 7798 * second range is for ports of non-configured MODs 7799 */ 7800 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit,0, BCM_STK_APACHE_NUM_LPORTS); 7801 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, 7802 src_modid_base_index_bk[unit]->default_base_idx, 7803 SOC_PORT_ADDR_MAX(unit) + 1); 7804 } else 7805 #endif /* BCM_APACHE_SUPPORT */ 7806 { 7807 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, 0, 7808 SOC_PORT_ADDR_MAX(unit) + 1); 7809 } 7810 if (SOC_IS_KATANA2(unit)) { 7811 if ((soc_feature(unit, soc_feature_linkphy_coe) && 7812 SOC_INFO(unit).linkphy_enabled) || 7813 (soc_feature(unit, soc_feature_subtag_coe) && 7814 SOC_INFO(unit).subtag_enabled)) { 7815 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, 7816 SOC_PORT_ADDR_MAX(unit) + 1, SOC_PORT_ADDR_MAX(unit) + 1); 7817 } 7818 } 7819 return BCM_E_NONE; 7820 } 7821 7822 /* 7823 * Function: 7824 * _src_modid_base_index_bk_detach 7825 * Purpose: 7826 * Deallocate data structures related to source modid base indexing. 7827 * Parameters: 7828 * unit - (IN)SOC unit number. 7829 * Returns: 7830 * None 7831 */ 7832 STATIC void 7833 _src_modid_base_index_bk_detach(int unit) 7834 { 7835 if (src_modid_base_index_bk[unit]) { 7836 if (src_modid_base_index_bk[unit]->num_ports) { 7837 sal_free(src_modid_base_index_bk[unit]->num_ports); 7838 src_modid_base_index_bk[unit]->num_ports = NULL; 7839 } 7840 if (src_modid_base_index_bk[unit]->src_mod_port_table_bitmap) { 7841 sal_free(src_modid_base_index_bk[unit]->src_mod_port_table_bitmap); 7842 src_modid_base_index_bk[unit]->src_mod_port_table_bitmap = NULL; 7843 } 7844 sal_free(src_modid_base_index_bk[unit]); 7845 src_modid_base_index_bk[unit] = NULL; 7846 7847 } 7848 } 7849 7850 /* 7851 * Function: 7852 * _src_modid_base_index_alloc 7853 * Purpose: 7854 * Allocate a source modid base index. 7855 * Parameters: 7856 * unit - (IN) SOC unit number. 7857 * modid - (IN) Source Module ID. 7858 * nports - (IN) Number of ports on the given module. 7859 * is_local_modid - (IN) 11 if allocation is needed for local module. 7860 * base_index - (OUT) Base index. 7861 * Returns: 7862 * BCM_E_xxx 7863 */ 7864 STATIC int 7865 _src_modid_base_index_alloc( 7866 int unit, 7867 bcm_module_t modid, 7868 int nports, 7869 int is_local_modid, 7870 int *base_index) 7871 { 7872 source_trunk_map_modbase_entry_t stm_modbase_entry; 7873 int max_base_index; 7874 int i, j; 7875 SHR_BITDCL occupied; 7876 source_trunk_map_table_entry_t stm_entry; 7877 egr_gpp_attributes_entry_t egr_gpp_entry; 7878 int lport_default_index, egr_lport_default_index; 7879 void *entry_null; 7880 #ifdef BCM_TRIDENT2PLUS_SUPPORT 7881 uint8 use_base_index_zero = 0; 7882 bcm_module_t mod_idx = 0; 7883 bcm_module_t my_modid = 0; 7884 int max_lports = BCM_STK_TD2P_NUM_LPORTS; 7885 #else /* BCM_TRIDENT2PLUS_SUPPORT */ 7886 COMPILER_REFERENCE(is_local_modid); 7887 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 7888 7889 SOC_IF_ERROR_RETURN( 7890 READ_SOURCE_TRUNK_MAP_MODBASEm( 7891 unit, MEM_BLOCK_ANY, modid, &stm_modbase_entry)); 7892 *base_index = 7893 soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get( 7894 unit, &stm_modbase_entry, BASEf); 7895 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 7896 if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) { 7897 /* TD2P SKUs can have max 106 logical ports support. 7898 * Apache SKUs can have max 75 logical ports support. 7899 */ 7900 #if defined(BCM_APACHE_SUPPORT) 7901 /* If Apache, override the max lports value, it is set to 7902 TD2P lport max to start with */ 7903 if (SOC_IS_APACHE(unit)) { 7904 max_lports = BCM_STK_APACHE_NUM_LPORTS; 7905 } 7906 #endif 7907 #if defined(BCM_MONTEREY_SUPPORT) 7908 if (SOC_IS_MONTEREY(unit)) { 7909 max_lports = BCM_STK_MONTEREY_NUM_LPORTS; 7910 } 7911 #endif 7912 #if defined(BCM_TRIDENT3_SUPPORT) 7913 /* If Trident3, override the max lports value, it is set to 7914 TD3 lport max to start with */ 7915 if (SOC_IS_TRIDENT3X(unit)) { 7916 if (SOC_IS_TRIDENT3(unit)) { 7917 max_lports = TRIDENT3_DEV_PORTS_PER_DEV; 7918 } 7919 #if defined(BCM_MAVERICK2_SUPPORT) 7920 if (SOC_IS_MAVERICK2(unit)) { 7921 max_lports = MAVERICK2_DEV_PORTS_PER_DEV; 7922 } 7923 #endif 7924 #if defined(BCM_HELIX5_SUPPORT) 7925 if (SOC_IS_HELIX5(unit)) { 7926 max_lports = HELIX5_DEV_PORTS_PER_DEV; 7927 } 7928 #endif 7929 } 7930 #endif 7931 if (is_local_modid && nports > max_lports) { 7932 return BCM_E_PARAM; 7933 } 7934 7935 BCM_IF_ERROR_RETURN( 7936 bcm_esw_stk_my_modid_get(unit, &my_modid)); 7937 7938 if (modid == my_modid || is_local_modid) { 7939 use_base_index_zero = 1; 7940 if(0 == *base_index) { 7941 return BCM_E_NONE; 7942 } 7943 *base_index = 0; 7944 } 7945 } 7946 7947 if (!use_base_index_zero) 7948 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 7949 { 7950 if (*base_index != src_modid_base_index_bk[unit]->default_base_idx) { 7951 return BCM_E_NONE; 7952 } 7953 7954 /* Find a contiguous region of source mod port tables that's large 7955 * enough to hold nports entries. 7956 */ 7957 max_base_index = soc_mem_index_count(unit, src_mod_port_mems[0]) - nports; 7958 for (i = 0; i <= max_base_index; i++) { 7959 /* Check if the contiguous region of source mod port tables from 7960 * index i to (i + nports - 1) is free. 7961 */ 7962 _BCM_SRC_MOD_PORT_TABLE_TEST_RANGE(unit, i, nports, occupied); 7963 if (!occupied) { 7964 break; 7965 } 7966 } 7967 if (i > max_base_index) { 7968 /* A contiguous region of the desired size could not be found in 7969 * source mod port tables. 7970 */ 7971 return BCM_E_RESOURCE; 7972 } 7973 *base_index = i; 7974 } 7975 7976 if(SOC_IS_KATANA(unit)) { 7977 SOC_IF_ERROR_RETURN 7978 (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_MODBASEm, 7979 modid, BASEf, *base_index)); 7980 } else { 7981 for (i = 0; i < COUNTOF(src_modbase_mems); i++) { 7982 if(soc_mem_is_valid(unit, src_modbase_mems[i])) { 7983 #ifdef BCM_TRIDENT2PLUS_SUPPORT 7984 if (src_modbase_mems[i] == MODID_BASE_PTRm) { 7985 mod_idx = modid % 64; /* lower 6 bit */ 7986 SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, 7987 MODID_BASE_PTRm, mod_idx, MODID_BASEf, *base_index)); 7988 } else 7989 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 7990 { 7991 SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, 7992 src_modbase_mems[i], modid, BASEf, *base_index)); 7993 } 7994 #if defined BCM_MONTEREY_SUPPORT 7995 if (SOC_IS_MONTEREY(unit) && 7996 soc_feature(unit, soc_feature_xflow_macsec) && 7997 (src_modbase_mems[i] == EGR_GPP_ATTRIBUTES_MODBASEm)) { 7998 SOC_IF_ERROR_RETURN( 7999 soc_egr_gpp_attribute_set(unit, 8000 *base_index)); 8001 } 8002 #endif 8003 } 8004 } 8005 } 8006 8007 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 8008 if ((SOC_IS_TD2P_TT2P(unit) || SOC_IS_TRIDENT3X(unit) || SOC_IS_APACHE(unit)) && use_base_index_zero) 8009 { 8010 /* For TD2P/Apache platforms base index 0 is reserved for local MODID 8011 * and hence we should not continue further and reset the relevant 8012 * src_mod_port_mems entries to default values. This is because local 8013 * MODID's configuration is done once at init time and we cannot afford 8014 * to lose it, as it will not be configured back. 8015 */ 8016 return BCM_E_NONE; 8017 } 8018 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 8019 8020 /* Set src_mod_port_table_bitmap */ 8021 _BCM_SRC_MOD_PORT_TABLE_USED_SET_RANGE(unit, *base_index, nports); 8022 8023 /* Set STM LPORT profile index to use default LPORT entry */ 8024 lport_default_index = _bcm_trx_lport_tab_default_entry_index_get(unit); 8025 sal_memcpy(&stm_entry, 8026 soc_mem_entry_null(unit, SOURCE_TRUNK_MAP_TABLEm), 8027 sizeof(stm_entry)); 8028 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, 8029 LPORT_PROFILE_IDXf, 8030 lport_default_index); 8031 8032 if(soc_feature(unit, soc_feature_egr_lport_tab_profile)) { 8033 /* Set Egress GPP LPORT profile index to use default LPORT entry */ 8034 8035 8036 egr_lport_default_index = 8037 _bcm_trx_egr_lport_tab_default_entry_index_get(unit); 8038 8039 sal_memcpy(&egr_gpp_entry, 8040 soc_mem_entry_null(unit, EGR_GPP_ATTRIBUTESm), 8041 sizeof(egr_gpp_entry)); 8042 soc_EGR_GPP_ATTRIBUTESm_field32_set(unit, &egr_gpp_entry, 8043 EGR_LPORT_PROFILE_IDXf, 8044 egr_lport_default_index); 8045 } 8046 8047 /* Clear the newly allocated region in each src mod port table */ 8048 if(SOC_IS_KATANA(unit)) { 8049 for (j = *base_index; j < (*base_index + nports); j++) { 8050 SOC_IF_ERROR_RETURN(soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm, 8051 MEM_BLOCK_ALL, j, 8052 &stm_entry)); 8053 } 8054 } else { 8055 for (i = 0; i < COUNTOF(src_mod_port_mems); i++) { 8056 if(!soc_mem_is_valid(unit, src_mod_port_mems[i])) { 8057 continue; 8058 } 8059 8060 if (src_mod_port_mems[i] == SOURCE_TRUNK_MAP_TABLEm) { 8061 entry_null = &stm_entry; 8062 } else if (soc_feature(unit, soc_feature_egr_lport_tab_profile)) { 8063 entry_null = &egr_gpp_entry; 8064 } else { 8065 entry_null = soc_mem_entry_null(unit, src_mod_port_mems[i]); 8066 } 8067 8068 for (j = *base_index; j < (*base_index + nports); j++) { 8069 SOC_IF_ERROR_RETURN(soc_mem_write(unit, src_mod_port_mems[i], 8070 MEM_BLOCK_ALL, j, 8071 entry_null)); 8072 } 8073 } 8074 } 8075 8076 return BCM_E_NONE; 8077 } 8078 8079 /* 8080 * Function: 8081 * _src_modid_base_index_free 8082 * Purpose: 8083 * Free a source modid base index. 8084 * Parameters: 8085 * unit - (IN) SOC unit number. 8086 * modid - (IN) Source Module ID. 8087 * nports - (IN) Number of ports on the given module. 8088 * Returns: 8089 * BCM_E_xxx 8090 */ 8091 STATIC int 8092 _src_modid_base_index_free( 8093 int unit, 8094 bcm_module_t modid, 8095 int nports) 8096 { 8097 source_trunk_map_modbase_entry_t stm_modbase_entry; 8098 source_trunk_map_table_entry_t stm_entry; 8099 int base_index; 8100 int i, j; 8101 void *entry_null; 8102 #ifdef BCM_TRIDENT2PLUS_SUPPORT 8103 bcm_module_t mod_idx = 0; 8104 bcm_module_t my_modid = 0; 8105 uint8 reuse_base_index_zero = 0; 8106 #endif 8107 8108 SOC_IF_ERROR_RETURN 8109 (READ_SOURCE_TRUNK_MAP_MODBASEm(unit, MEM_BLOCK_ANY, modid, 8110 &stm_modbase_entry)); 8111 base_index = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit, 8112 &stm_modbase_entry, BASEf); 8113 if (base_index == src_modid_base_index_bk[unit]->default_base_idx) { 8114 return BCM_E_NONE; 8115 } 8116 8117 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 8118 if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) { 8119 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 8120 8121 if (modid == my_modid && 0 == base_index) { 8122 reuse_base_index_zero = 1; 8123 } 8124 } 8125 8126 if (!reuse_base_index_zero) 8127 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 8128 { 8129 /* Clear src mod port table bitmap */ 8130 _BCM_SRC_MOD_PORT_TABLE_USED_CLR_RANGE(unit, base_index, nports); 8131 8132 sal_memcpy(&stm_entry, 8133 soc_mem_entry_null(unit, SOURCE_TRUNK_MAP_TABLEm), 8134 sizeof(stm_entry)); 8135 /* Clear the region to be freed in each src mod port table */ 8136 if(SOC_IS_KATANA(unit)) { 8137 for (j = base_index; j < (base_index + nports); j++) { 8138 SOC_IF_ERROR_RETURN( 8139 soc_mem_write(unit, SOURCE_TRUNK_MAP_TABLEm, 8140 MEM_BLOCK_ALL, j, &stm_entry)); 8141 } 8142 } else { 8143 for (i = 0; i < COUNTOF(src_mod_port_mems); i++) { 8144 if(!soc_mem_is_valid(unit, src_mod_port_mems[i])) { 8145 continue; 8146 } 8147 8148 if (src_mod_port_mems[i] == SOURCE_TRUNK_MAP_TABLEm) { 8149 entry_null = &stm_entry; 8150 } else { 8151 entry_null = soc_mem_entry_null(unit, src_mod_port_mems[i]); 8152 } 8153 8154 for (j = base_index; j < (base_index + nports); j++) { 8155 SOC_IF_ERROR_RETURN( 8156 soc_mem_write(unit, src_mod_port_mems[i], 8157 MEM_BLOCK_ALL, j, entry_null)); 8158 } 8159 } 8160 } 8161 } 8162 8163 if(SOC_IS_KATANA(unit)) { 8164 SOC_IF_ERROR_RETURN 8165 (soc_mem_field32_modify(unit, SOURCE_TRUNK_MAP_MODBASEm, 8166 modid, BASEf, 0)); 8167 } else { 8168 for (i = 0; i < COUNTOF(src_modbase_mems); i++) { 8169 if(soc_mem_is_valid(unit, src_modbase_mems[i])) { 8170 #ifdef BCM_TRIDENT2PLUS_SUPPORT 8171 if (src_modbase_mems[i] == MODID_BASE_PTRm) { 8172 mod_idx = modid % 64; /* lower 6 bit */ 8173 SOC_IF_ERROR_RETURN( 8174 soc_mem_field32_modify( 8175 unit, MODID_BASE_PTRm, mod_idx, MODID_BASEf, 8176 src_modid_base_index_bk[unit]->default_base_idx)); 8177 } else 8178 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 8179 { 8180 SOC_IF_ERROR_RETURN( 8181 soc_mem_field32_modify( 8182 unit, src_modbase_mems[i], modid, BASEf, 8183 src_modid_base_index_bk[unit]->default_base_idx)); 8184 } 8185 } 8186 } 8187 } 8188 return BCM_E_NONE; 8189 } 8190 8191 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 8192 8193 /* 8194 * Function: 8195 * bcm_esw_stk_module_enable 8196 * Purpose: 8197 * Enable or disable a module and specify its number of ports. 8198 * Parameters: 8199 * unit - (IN) SOC unit number. 8200 * modid - (IN) Module ID that is being enabled/disabled. 8201 * nports - (IN) Number of ports on the given module, 0 for no port 8202 * status change, -1 for default number of ports. 8203 * enable - (IN) TRUE to enable, FALSE to disable. 8204 * Returns: 8205 * BCM_E_xxx 8206 */ 8207 int 8208 bcm_esw_stk_module_enable( 8209 int unit, 8210 bcm_module_t modid, 8211 int nports, 8212 int enable) 8213 { 8214 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 8215 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 8216 8217 bcm_module_t mod_out; 8218 bcm_port_t port_out; 8219 int is_local; 8220 int old_nports; 8221 int base_index; 8222 8223 if (modid > SOC_MODID_MAX(unit)) { 8224 return BCM_E_PARAM; 8225 } 8226 8227 if ((nports > (SOC_PORT_ADDR_MAX(unit) + 1)) || (nports < -1)) { 8228 return BCM_E_PARAM; 8229 } 8230 8231 if (enable && (nports == 0)) { 8232 return BCM_E_PARAM; 8233 } 8234 8235 BCM_IF_ERROR_RETURN 8236 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 8237 modid, -1, 8238 &mod_out, &port_out)); 8239 BCM_IF_ERROR_RETURN 8240 (_bcm_esw_modid_is_local(unit, mod_out, &is_local)); 8241 8242 if (enable) { 8243 if (is_local) { 8244 /* If local modid, use the base modid */ 8245 mod_out = SOC_BASE_MODID(unit); 8246 } 8247 8248 old_nports = src_modid_base_index_bk[unit]->num_ports[mod_out]; 8249 if (old_nports > 0) { 8250 /* Already enabled */ 8251 return BCM_E_EXISTS; 8252 } 8253 8254 if (nports == -1) { 8255 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 8256 if (is_local && 8257 (SOC_IS_TD2P_TT2P(unit))) { 8258 /* In TD2P num of ports default to 106 for local MODID 8259 */ 8260 nports = BCM_STK_TD2P_NUM_LPORTS; 8261 } else 8262 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 8263 #if defined(BCM_MONTEREY_SUPPORT) 8264 if (is_local && 8265 (SOC_IS_MONTEREY(unit))) { 8266 nports = BCM_STK_MONTEREY_NUM_LPORTS; 8267 } else 8268 #endif /* BCM_MONTEREY_SUPPORT */ 8269 #if defined(BCM_APACHE_SUPPORT) 8270 if (is_local && 8271 (SOC_IS_APACHE(unit))) { 8272 /* In Apache num of ports default to 75 for local MODID 8273 */ 8274 nports = BCM_STK_APACHE_NUM_LPORTS; 8275 } else 8276 #endif /* BCM_APACHE_SUPPORT */ 8277 #if defined(BCM_TRIDENT3_SUPPORT) 8278 if (is_local && 8279 (SOC_IS_TRIDENT3X(unit))) { 8280 /* In trident3 num of ports default to max logical for local MODID 8281 */ 8282 if (SOC_IS_TRIDENT3(unit)) { 8283 nports = TRIDENT3_DEV_PORTS_PER_DEV; 8284 } 8285 #if defined(BCM_MAVERICK2_SUPPORT) 8286 if (SOC_IS_MAVERICK2(unit)) { 8287 nports = MAVERICK2_DEV_PORTS_PER_DEV; 8288 } 8289 #endif 8290 #if defined(BCM_HELIX5_SUPPORT) 8291 if (SOC_IS_HELIX5(unit)) { 8292 nports = HELIX5_DEV_PORTS_PER_DEV; 8293 } 8294 #endif 8295 } else 8296 #endif /* BCM_TRIDENT3_SUPPORT */ 8297 { 8298 /* Number of ports default to SOC_PORT_ADDR_MAX + 1 */ 8299 nports = SOC_PORT_ADDR_MAX(unit) + 1; 8300 } 8301 } 8302 8303 if (nports > 0) { 8304 BCM_IF_ERROR_RETURN 8305 (_src_modid_base_index_alloc(unit, mod_out, nports, 8306 is_local, &base_index)); 8307 src_modid_base_index_bk[unit]->num_ports[mod_out] = nports; 8308 } 8309 } else { 8310 if (is_local) { 8311 /* Cannot disable local module */ 8312 return BCM_E_PARAM; 8313 } 8314 8315 old_nports = src_modid_base_index_bk[unit]->num_ports[mod_out]; 8316 if (old_nports == 0) { 8317 /* Not enabled */ 8318 return BCM_E_DISABLED; 8319 } 8320 BCM_IF_ERROR_RETURN 8321 (_src_modid_base_index_free(unit, mod_out, old_nports)); 8322 src_modid_base_index_bk[unit]->num_ports[mod_out] = 0; 8323 } 8324 8325 return BCM_E_NONE; 8326 } 8327 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 8328 8329 return BCM_E_UNAVAIL; 8330 } 8331 8332 /* 8333 * Function: 8334 * _bcm_esw_src_modid_base_index_get 8335 * Purpose: 8336 * Allocate a source modid base index. 8337 * Parameters: 8338 * unit - (IN) SOC unit number. 8339 * modid - (IN) Source Module ID. 8340 * is_local - (IN) 1 if local Module ID. 8341 * base_index - (OUT) Source module base index. 8342 * Returns: 8343 * BCM_E_xxx 8344 */ 8345 int 8346 _bcm_esw_src_modid_base_index_get( 8347 int unit, 8348 bcm_module_t modid, 8349 int is_local, 8350 int *base_index) 8351 { 8352 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 8353 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 8354 8355 source_trunk_map_modbase_entry_t stm_modbase_entry; 8356 int nports; 8357 8358 SOC_IF_ERROR_RETURN 8359 (READ_SOURCE_TRUNK_MAP_MODBASEm(unit, MEM_BLOCK_ANY, modid, 8360 &stm_modbase_entry)); 8361 *base_index = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit, 8362 &stm_modbase_entry, BASEf); 8363 if (*base_index != src_modid_base_index_bk[unit]->default_base_idx) { 8364 /* Source module base index already allocated */ 8365 return BCM_E_NONE; 8366 } 8367 8368 if (NULL == src_modid_base_index_bk[unit]) { 8369 return BCM_E_INIT; 8370 } 8371 8372 /* Allocate a source module base index */ 8373 nports = src_modid_base_index_bk[unit]->num_ports[modid]; 8374 if (nports == 0) { 8375 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 8376 if (is_local && (SOC_IS_TD2P_TT2P(unit))) { 8377 /* In TD2P num of ports default to 106 for local MODID */ 8378 nports = BCM_STK_TD2P_NUM_LPORTS; 8379 } else 8380 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 8381 #if defined(BCM_MONTEREY_SUPPORT) 8382 if (is_local && SOC_IS_MONTEREY(unit)) { 8383 /* In Apache num of ports default to 75 for local MODID */ 8384 nports = BCM_STK_MONTEREY_NUM_LPORTS; 8385 } else 8386 #endif /* BCM_MONTEREY_SUPPORT */ 8387 #if defined(BCM_APACHE_SUPPORT) 8388 if (is_local && SOC_IS_APACHE(unit)) { 8389 /* In Apache num of ports default to 75 for local MODID */ 8390 nports = BCM_STK_APACHE_NUM_LPORTS; 8391 } else 8392 #endif /* BCM_APACHE_SUPPORT */ 8393 #if defined(BCM_TRIDENT3_SUPPORT) 8394 if (is_local && SOC_IS_TRIDENT3X(unit)) { 8395 /* In Apache num of ports default to max logical ports for local MODID */ 8396 if (SOC_IS_TRIDENT3(unit)) { 8397 nports = TRIDENT3_DEV_PORTS_PER_DEV; 8398 } 8399 #if defined(BCM_MAVERICK2_SUPPORT) 8400 if (SOC_IS_MAVERICK2(unit)) { 8401 nports = MAVERICK2_DEV_PORTS_PER_DEV; 8402 } 8403 #endif 8404 #if defined(BCM_HELIX5_SUPPORT) 8405 if (SOC_IS_HELIX5(unit)) { 8406 nports = HELIX5_DEV_PORTS_PER_DEV; 8407 } 8408 #endif 8409 } else 8410 #endif /* BCM_TRIDENT3_SUPPORT */ 8411 { 8412 /* Assume (SOC_PORT_ADDR_MAX + 1) if nports is not initialized 8413 * using bcm_esw_stk_module_enable API 8414 */ 8415 nports = SOC_PORT_ADDR_MAX(unit) + 1; 8416 } 8417 } 8418 BCM_IF_ERROR_RETURN 8419 (_src_modid_base_index_alloc( 8420 unit, modid, nports, is_local, base_index)); 8421 src_modid_base_index_bk[unit]->num_ports[modid] = nports; 8422 8423 return BCM_E_NONE; 8424 } 8425 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 8426 8427 return BCM_E_UNAVAIL; 8428 } 8429 8430 /* 8431 * Function: 8432 * _bcm_esw_src_modid_port_get 8433 * Purpose: 8434 * get modid and port number from STM entry index. 8435 * Parameters: 8436 * unit - (IN) SOC unit number. 8437 * stm_inx - (IN) Source Trunk Map entry index. 8438 * modid - (OUT) Source Module ID. 8439 * port - (OUT) Port Number. 8440 * Returns: 8441 * BCM_E_xxx 8442 */ 8443 int 8444 _bcm_esw_src_modid_port_get( 8445 int unit, 8446 int stm_inx, 8447 bcm_module_t *modid, 8448 int *port) 8449 { 8450 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 8451 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 8452 int i; 8453 int rv; 8454 int base_inx; 8455 source_trunk_map_modbase_entry_t stm_modbase_entry; 8456 8457 /* The SOURCE_TRUNK_MAP entry range pointed by the base index 8458 * for each modid is not overlapped. 8459 */ 8460 for (i = 0; i <= SOC_MODID_MAX(unit) ; i++) { 8461 8462 /* only read the valid entry */ 8463 if (src_modid_base_index_bk[unit]->num_ports[i]) { 8464 rv = READ_SOURCE_TRUNK_MAP_MODBASEm(unit, MEM_BLOCK_ANY, i, 8465 &stm_modbase_entry); 8466 if (SOC_FAILURE(rv)) { 8467 continue; 8468 } 8469 base_inx = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit, 8470 &stm_modbase_entry, BASEf); 8471 /* check if the stm_inx falls in the range */ 8472 if ((stm_inx >= base_inx) && (stm_inx < (base_inx + 8473 src_modid_base_index_bk[unit]->num_ports[i]))) { 8474 /* found the modid */ 8475 *modid = i; 8476 *port = stm_inx - base_inx; 8477 return BCM_E_NONE; 8478 } 8479 } 8480 } 8481 return BCM_E_PARAM; 8482 } 8483 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 8484 8485 #ifdef BCM_TRX_SUPPORT 8486 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 8487 *modid = stm_inx / (SOC_PORT_ADDR_MAX(unit) + 1); 8488 *port = stm_inx % (SOC_PORT_ADDR_MAX(unit) + 1); 8489 return BCM_E_NONE; 8490 } 8491 #endif 8492 return BCM_E_UNAVAIL; 8493 } 8494 8495 /* 8496 * Function: 8497 * _bcm_esw_src_mod_port_table_index_get 8498 * Purpose: 8499 * Derive index to source mod port tables. 8500 * Parameters: 8501 * unit - (IN) SOC unit number. 8502 * modid - (IN) Source Module ID. 8503 * port - (IN) Source Port ID. 8504 * index - (OUT) Source mod port table index. 8505 * Returns: 8506 * BCM_E_xxx 8507 */ 8508 int 8509 _bcm_esw_src_mod_port_table_index_get( 8510 int unit, 8511 bcm_module_t modid, 8512 bcm_port_t port, 8513 int *index) 8514 { 8515 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 8516 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 8517 int is_local; 8518 bcm_module_t mod_out; 8519 8520 BCM_IF_ERROR_RETURN 8521 (_bcm_esw_stk_modmap_map( 8522 unit, BCM_STK_MODMAP_SET, modid, -1, &mod_out, NULL)); 8523 BCM_IF_ERROR_RETURN 8524 (_bcm_esw_modid_is_local(unit, mod_out, &is_local)); 8525 8526 BCM_IF_ERROR_RETURN 8527 (_bcm_esw_src_modid_base_index_get(unit, modid, is_local, index)); 8528 *index += port; 8529 } else 8530 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 8531 if (SOC_IS_ENDURO(unit)) { 8532 *index = (modid * 64) + port; 8533 } else 8534 #ifdef BCM_TRX_SUPPORT 8535 if (soc_feature(unit, soc_feature_trunk_group_overlay)) { 8536 *index = (modid * (SOC_PORT_ADDR_MAX(unit) + 1)) + port; 8537 } else 8538 #endif 8539 { 8540 *index = (modid << SOC_TRUNK_BIT_POS(unit)) + port; 8541 } 8542 8543 return BCM_E_NONE; 8544 } 8545 8546 /* 8547 * Function: 8548 * _bcm_esw_src_mod_port_table_index_get_from_port 8549 * Purpose: 8550 * Derive index to source mod port tables. 8551 * Parameters: 8552 * unit - (IN) SOC unit number. 8553 * port - (IN) Source Port ID. 8554 * index - (OUT) Source mod port table index. 8555 * 8556 * port only accept: 8557 * GPORT Subport 8558 * Pysical port 8559 * Returns: 8560 * BCM_E_xxx 8561 */ 8562 int 8563 _bcm_esw_src_mod_port_table_index_get_from_port( 8564 int unit, 8565 bcm_port_t port, 8566 int *index) 8567 { 8568 int mod_out; 8569 #if defined BCM_HGPROXY_COE_SUPPORT 8570 bcm_trunk_t trunk_id; 8571 bcm_port_t port_out; 8572 int id; 8573 #endif 8574 8575 #if defined BCM_HGPROXY_COE_SUPPORT 8576 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 8577 BCM_GPORT_IS_SET(port) && 8578 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 8579 BCM_IF_ERROR_RETURN( 8580 _bcm_esw_gport_resolve(unit, port, &mod_out, &port_out, 8581 &trunk_id, &id)); 8582 BCM_IF_ERROR_RETURN( 8583 _bcm_esw_src_mod_port_table_index_get(unit, mod_out, 8584 port_out, index)); 8585 } else 8586 #endif 8587 8588 { 8589 /* Get module id for unit. */ 8590 BCM_IF_ERROR_RETURN( 8591 bcm_esw_stk_my_modid_get(unit, &mod_out)); 8592 BCM_IF_ERROR_RETURN( 8593 _bcm_esw_src_mod_port_table_index_get(unit, mod_out, 8594 port, index)); 8595 } 8596 8597 return BCM_E_NONE; 8598 } 8599 8600 8601 #if defined(BCM_KATANA2_SUPPORT) 8602 8603 /* 8604 * Function: 8605 * _bcm_stk_index_based_cfg_modport_count 8606 * Purpose: 8607 * Given a index, compute modports already created prior 8608 * to this mod_index. This is called when creating modports 8609 * to check if there is room to create additional modports. 8610 * Parameters: 8611 * unit - (IN) unit number. 8612 * mod_index - (IN) Module index to use for computation 8613 * modport_count - (OUT) Number of modports created prior to 8614 * this mod_index 8615 * Returns: 8616 * BCM_E_XXX 8617 */ 8618 8619 int 8620 _bcm_stk_index_based_cfg_modport_count(int unit, int mod_index, 8621 uint8 *modport_count) 8622 { 8623 int my_modid_list[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 8624 int my_modid_valid[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 8625 int my_modport_base_ptr[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 8626 int modid = 0; 8627 8628 if(modport_count == NULL) { 8629 return BCM_E_PARAM; 8630 } 8631 8632 /* Sanity check the 'mod_index' value, first index (_BCMI_KATANA2_MODULE_1) 8633 reserved for front panel ports */ 8634 if((mod_index < _BCMI_KATANA2_MODULE_2) || 8635 (mod_index > KT2_MAX_MODIDS_PER_TRANSLATION_TABLE)) { 8636 return BCM_E_PARAM; 8637 } 8638 8639 BCM_IF_ERROR_RETURN( 8640 bcm_kt2_modid_get_all(unit, my_modid_list, my_modid_valid, 8641 my_modport_base_ptr)); 8642 8643 /* Depending on the mod_index, compute the previous allocation of 8644 modports, fall through to get full list */ 8645 switch(mod_index) { 8646 case _BCMI_KATANA2_MODULE_4: 8647 if(my_modid_valid[_BCMI_KATANA2_MODULE_3]) { 8648 modid = my_modid_list[_BCMI_KATANA2_MODULE_3]; 8649 *modport_count += 8650 src_modid_base_index_bk[unit]->num_ports[modid]; 8651 } 8652 case _BCMI_KATANA2_MODULE_3: 8653 if(my_modid_valid[_BCMI_KATANA2_MODULE_2]) { 8654 modid = my_modid_list[_BCMI_KATANA2_MODULE_2]; 8655 *modport_count += 8656 src_modid_base_index_bk[unit]->num_ports[modid]; 8657 } 8658 break; 8659 case _BCMI_KATANA2_MODULE_2: 8660 /* This is the first Coe Module being created, just set the 8661 modport_count to 0 */ 8662 *modport_count = 0; 8663 break; 8664 default: 8665 *modport_count = 0; 8666 return BCM_E_PARAM; 8667 } 8668 8669 return BCM_E_NONE; 8670 } 8671 8672 /* 8673 * Function: 8674 * _bcm_stk_index_based_mod_cfg_check 8675 * Purpose: 8676 * Given a index, determine if the subsequent modules are 8677 * created. This is called when deleting modports so 8678 * ordered deletion can be enforced. User has to essentially 8679 * delete latest added modules first. 8680 * 8681 * Parameters: 8682 * unit - (IN) unit number. 8683 * mod_index - (IN) Module index to use for computation 8684 * mod_cfg - (OUT) True if subsequent mods created 8685 * already 8686 * Returns: 8687 * BCM_E_XXX 8688 */ 8689 8690 int 8691 _bcm_stk_index_based_mod_cfg_check(int unit, int mod_index, 8692 uint8 *mod_cfg) 8693 { 8694 int my_modid_list[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 8695 int my_modid_valid[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 8696 int my_modport_base_ptr[KT2_MAX_MODIDS_PER_TRANSLATION_TABLE] = {0}; 8697 8698 if(mod_cfg == NULL) { 8699 return BCM_E_PARAM; 8700 } 8701 8702 /* Sanity check the 'mod_index' value, first index (_BCMI_KATANA2_MODULE_1) 8703 reserved for front panel ports */ 8704 if((mod_index < _BCMI_KATANA2_MODULE_2) || 8705 (mod_index > KT2_MAX_MODIDS_PER_TRANSLATION_TABLE)) { 8706 return BCM_E_PARAM; 8707 } 8708 8709 8710 BCM_IF_ERROR_RETURN( 8711 bcm_kt2_modid_get_all(unit, my_modid_list, my_modid_valid, 8712 my_modport_base_ptr)); 8713 8714 *mod_cfg = FALSE; 8715 8716 /* Depending on the mod_index, compute the subsequent mods, 8717 to check if they are already created, fall thru to check all, 8718 the array index is '0' based whereas the index is '1' based. 8719 _BCMI_KATANA2_MODULE_1 is reserved for local-mod and the 8720 _BCMI_KATANA2_MODULE_2/3/4 are used for CoE ports */ 8721 switch(mod_index) { 8722 8723 /* coverity[fallthrough] */ 8724 case _BCMI_KATANA2_MODULE_2: 8725 *mod_cfg = my_modid_valid[_BCMI_KATANA2_MODULE_3]; 8726 8727 /* coverity[unterminated_case] */ 8728 case _BCMI_KATANA2_MODULE_3: 8729 if(*mod_cfg == FALSE) { 8730 *mod_cfg = my_modid_valid[_BCMI_KATANA2_MODULE_4]; 8731 } 8732 break; 8733 case _BCMI_KATANA2_MODULE_4: 8734 /* The last module can always be deleted, just set to 0 */ 8735 *mod_cfg = 0; 8736 break; 8737 default: 8738 return BCM_E_PARAM; 8739 } 8740 8741 return BCM_E_NONE; 8742 } 8743 8744 #endif /* #if defined(BCM_KATANA2_SUPPORT) */ 8745 8746 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 8747 8748 /* 8749 * Function: 8750 * _bcm_update_mod_config_by_type 8751 * Purpose: 8752 * Derive index to source mod port tables. 8753 * Parameters: 8754 * unit - (IN) SOC unit number. 8755 * flags - (IN) Indicates type of module 8756 * mod_index - (IN) Index of the module being updated 8757 * mod_id - (IN) The module identifier being updated 8758 * valid - (IN) Indicates if the mod being passed is valid 8759 * base_idx - (IN) Base index to program if the module is valid 8760 * Returns: 8761 * BCM_E_xxx 8762 */ 8763 8764 STATIC int _bcm_esw_stk_update_mod_config_by_type(int unit, int flags, int mod_index, 8765 int mod_id, int valid, int base_idx) 8766 { 8767 uint64 mod_64; 8768 soc_reg_t reg; 8769 int mod_id_fld, mod_base_fld, mod_valid_fld; 8770 8771 /* Make sure the caller has provided a valid type of module */ 8772 if(!(flags & BCM_MODID_TYPE_COE) && 8773 !(flags & BCM_MODID_TYPE_MULTI_NEXT_HOPS)) { 8774 return BCM_E_INTERNAL; 8775 } 8776 8777 /* Switch based on the mod_id and set the appropriate registry */ 8778 switch (mod_index) { 8779 8780 case BCM_TD2P_COE_MODULE_1: 8781 8782 /* Determine the correct field to program */ 8783 mod_id_fld = MODID_1f; 8784 mod_base_fld = MODID_1_BASEf; 8785 mod_valid_fld = MODID_1_VALIDf; 8786 8787 /* Make a note of the specific register we need to update */ 8788 reg = MY_MODID_SET_2_64r; 8789 8790 break; 8791 8792 case BCM_TD2P_COE_MODULE_2: 8793 8794 /* Determine the correct field to program */ 8795 mod_id_fld = MODID_2f; 8796 mod_base_fld = MODID_2_BASEf; 8797 mod_valid_fld = MODID_2_VALIDf; 8798 8799 /* Make a note of the specific register we need to update */ 8800 reg = MY_MODID_SET_3_64r; 8801 8802 break; 8803 8804 case BCM_TD2P_COE_MODULE_3: 8805 8806 mod_id_fld = MODID_3f; 8807 mod_base_fld = MODID_3_BASEf; 8808 mod_valid_fld = MODID_3_VALIDf; 8809 8810 /* Make a note of the specific register we need to update */ 8811 reg = MY_MODID_SET_3_64r; 8812 8813 break; 8814 8815 case BCM_TD2P_COE_MODULE_4: 8816 8817 mod_id_fld = MODID_4f; 8818 mod_base_fld = MODID_4_BASEf; 8819 mod_valid_fld = MODID_4_VALIDf; 8820 8821 /* Make a note of the specific register we need to update */ 8822 reg = MY_MODID_SET_4_64r; 8823 break; 8824 8825 case BCM_TD2P_COE_MODULE_5: 8826 8827 mod_id_fld = MODID_5f; 8828 mod_base_fld = MODID_5_BASEf; 8829 mod_valid_fld = MODID_5_VALIDf; 8830 8831 /* Make a note of the specific register we need to update */ 8832 reg = MY_MODID_SET_4_64r; 8833 8834 break; 8835 8836 default: 8837 return BCM_E_PARAM; 8838 } 8839 8840 /* Setup the base register */ 8841 COMPILER_64_ZERO(mod_64); 8842 BCM_IF_ERROR_RETURN(READ_MY_MODID_SET_64r(unit, &mod_64)); 8843 soc_reg64_field32_set(unit, MY_MODID_SET_64r, &mod_64, 8844 mod_id_fld, (valid ? (mod_id): 0)); 8845 soc_reg64_field32_set(unit, MY_MODID_SET_64r, &mod_64, 8846 mod_valid_fld, valid); 8847 BCM_IF_ERROR_RETURN(WRITE_MY_MODID_SET_64r(unit, mod_64)); 8848 8849 /* Update the specific register */ 8850 8851 /* Set the individual registers */ 8852 COMPILER_64_ZERO(mod_64); 8853 BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, 0, &mod_64)); 8854 8855 soc_reg64_field32_set(unit, reg, &mod_64, 8856 mod_id_fld, (valid ? (mod_id): 0)); 8857 soc_reg64_field32_set(unit, reg, &mod_64, 8858 mod_base_fld, base_idx); 8859 soc_reg64_field32_set(unit, reg, &mod_64, 8860 mod_valid_fld, valid); 8861 BCM_IF_ERROR_RETURN(soc_reg_set(unit, reg, REG_PORT_ANY, 0, mod_64)); 8862 8863 /* Set the egress registers */ 8864 if (!(flags & BCM_MODID_TYPE_MULTI_NEXT_HOPS)) { 8865 /* Set the egress registers */ 8866 COMPILER_64_ZERO(mod_64); 8867 BCM_IF_ERROR_RETURN(READ_EGR_MY_MODID_SET_64r(unit, &mod_64)); 8868 soc_reg64_field32_set(unit, EGR_MY_MODID_SET_64r, &mod_64, 8869 mod_id_fld, (valid ? (mod_id): 0)); 8870 soc_reg64_field32_set(unit, EGR_MY_MODID_SET_64r, &mod_64, 8871 mod_valid_fld, valid); 8872 BCM_IF_ERROR_RETURN(WRITE_EGR_MY_MODID_SET_64r(unit, mod_64)); 8873 } 8874 8875 return BCM_E_NONE; 8876 } 8877 8878 /* 8879 * Function: 8880 * _bcm_esw_stk_get_mod_config_by_type 8881 * Purpose: 8882 * Retrieve index to source mod port tables. 8883 * Parameters: 8884 * unit - (IN) SOC unit number. 8885 * flags - (IN) Indicates type of module 8886 * mod_index - (IN) Index of the module being retrieved 8887 * mod_id - (OUT) The module identifier being retrieved 8888 * valid - (OUT) Indicates if the mod is valid 8889 * base_idx - (OUT) Base index to program 8890 * Returns: 8891 * BCM_E_xxx 8892 */ 8893 8894 int _bcm_esw_stk_get_mod_config_by_type(int unit, int flags, int mod_index, 8895 int *mod_id, int *valid, int *base_idx) 8896 { 8897 uint64 mod_64; 8898 8899 int mod_id_fld[] = {MODID_1f, 8900 MODID_2f, 8901 MODID_3f, 8902 MODID_4f, 8903 MODID_5f}; 8904 int mod_base_fld[] = {MODID_1_BASEf, 8905 MODID_2_BASEf, 8906 MODID_3_BASEf, 8907 MODID_4_BASEf, 8908 MODID_5_BASEf}; 8909 int mod_valid_fld[] = {MODID_1_VALIDf, 8910 MODID_2_VALIDf, 8911 MODID_3_VALIDf, 8912 MODID_4_VALIDf, 8913 MODID_5_VALIDf}; 8914 int reg[] = {MY_MODID_SET_2_64r, 8915 MY_MODID_SET_3_64r, 8916 MY_MODID_SET_3_64r, 8917 MY_MODID_SET_4_64r, 8918 MY_MODID_SET_4_64r}; 8919 8920 /* Make sure the caller has provided a valid type of module */ 8921 if(!(flags & BCM_MODID_TYPE_COE) && 8922 !(flags & BCM_MODID_TYPE_MULTI_NEXT_HOPS)) { 8923 return BCM_E_INTERNAL; 8924 } 8925 8926 8927 if ((mod_index < BCM_TD2P_COE_MODULE_1) || 8928 (mod_index > BCM_TD2P_COE_MODULE_5)) { 8929 return BCM_E_PARAM; 8930 } 8931 8932 /* Get the individual registers */ 8933 COMPILER_64_ZERO(mod_64); 8934 BCM_IF_ERROR_RETURN( 8935 soc_reg_get(unit, reg[mod_index - 1], REG_PORT_ANY, 0, &mod_64)); 8936 8937 *mod_id = soc_reg64_field32_get(unit, reg[mod_index - 1], mod_64, 8938 mod_id_fld[mod_index - 1]); 8939 *base_idx = soc_reg64_field32_get(unit, reg[mod_index - 1], mod_64, 8940 mod_base_fld[mod_index - 1]); 8941 *valid = soc_reg64_field32_get(unit, reg[mod_index - 1], mod_64, 8942 mod_valid_fld[mod_index - 1]); 8943 8944 return BCM_E_NONE; 8945 } 8946 8947 /* 8948 * Function : _bcm_esw_my_modid_additional_check 8949 * Description : Identifies if given modid is my modid on a given unit 8950 * 8951 * Parameters : 8952 * (IN) unit - BCM device number 8953 * (IN) modnd - Module ID 8954 * (OUT) result - TRUE if modid is local, FALSE otherwise 8955 * Returns : BCM_E_XXX 8956 */ 8957 int 8958 _bcm_esw_my_modid_additional_check(int unit, bcm_module_t modid, int *result) 8959 { 8960 int modid_value = 0; 8961 uint32 modid_mask = 0; 8962 8963 /* Parameter check */ 8964 if (result == NULL) { 8965 return (BCM_E_PARAM); 8966 } 8967 8968 BCM_IF_ERROR_RETURN 8969 (_bcm_esw_stk_modid_range_info_get(unit, &modid_value, &modid_mask)); 8970 if(!modid_mask) { /* No extra my modid */ 8971 *result = FALSE; 8972 return (BCM_E_NONE); 8973 } 8974 8975 if((modid & modid_mask) == (modid_value & modid_mask)) { 8976 *result = TRUE; 8977 } else { 8978 *result = FALSE; 8979 } 8980 8981 return (BCM_E_NONE); 8982 } 8983 /* 8984 * Function: 8985 * _bcm_esw_stk_modid_range_info_get 8986 * Purpose: 8987 * Get the module ID and module MASK from HW. 8988 * Parameters: 8989 * unit - (IN) SOC unit# 8990 * mod_base - (OUT) module ID. 8991 * mod_mask - (OUT) The module mask. 8992 * Returns: 8993 * BCM_E_xxx 8994 */ 8995 int _bcm_esw_stk_modid_range_info_get(int unit, int *mod_base, uint32 *mod_mask) 8996 { 8997 8998 /* Parameter check */ 8999 if(NULL == mod_base || NULL == mod_mask) { 9000 return BCM_E_PARAM; 9001 } 9002 9003 *mod_base = src_modid_base_index_bk[unit]->module_id_range.mod_base; 9004 *mod_mask = src_modid_base_index_bk[unit]->module_id_range.mod_mask; 9005 9006 return BCM_E_NONE; 9007 } 9008 9009 /* 9010 * Function: 9011 * _bcm_esw_stk_modid_range_set 9012 * Purpose: 9013 * Set the module ID and module MASK into HW. 9014 * Parameters: 9015 * unit - (IN) SOC unit# 9016 * mod_base - (IN) module ID. 9017 * mod_mask - (IN) The module mask. 9018 * valid - (IN) valid bit. 9019 * Returns: 9020 * BCM_E_xxx 9021 */ 9022 int _bcm_esw_stk_modid_range_set(int unit, int mod_base, uint32 mod_mask, uint32 valid) 9023 { 9024 uint32 rval = 0; 9025 9026 /* Parameter check */ 9027 if((mod_base < 0) || (mod_base > 0xff) || (mod_mask > 0xff)) { 9028 return BCM_E_PARAM; 9029 } 9030 9031 BCM_IF_ERROR_RETURN 9032 (soc_reg32_get(unit, MY_MODID_CONFIGr, REG_PORT_ANY, 0, &rval)); 9033 soc_reg_field_set(unit, MY_MODID_CONFIGr, &rval, VALUEf, mod_base); 9034 soc_reg_field_set(unit, MY_MODID_CONFIGr, &rval, MASKf, mod_mask); 9035 soc_reg_field_set(unit, MY_MODID_CONFIGr, &rval, VALIDf, (valid ? 1 : 0)); 9036 BCM_IF_ERROR_RETURN 9037 (soc_reg32_set(unit, MY_MODID_CONFIGr, REG_PORT_ANY, 0, rval)); 9038 BCM_IF_ERROR_RETURN 9039 (soc_reg32_get(unit, MY_MODID_CONFIG_2r, REG_PORT_ANY, 0, &rval)); 9040 soc_reg_field_set(unit, MY_MODID_CONFIG_2r, &rval, VALUEf, mod_base); 9041 soc_reg_field_set(unit, MY_MODID_CONFIG_2r, &rval, MASKf, mod_mask); 9042 soc_reg_field_set(unit, MY_MODID_CONFIG_2r, &rval, VALIDf, (valid ? 1 : 0)); 9043 BCM_IF_ERROR_RETURN 9044 (soc_reg32_set(unit, MY_MODID_CONFIG_2r, REG_PORT_ANY, 0, rval)); 9045 src_modid_base_index_bk[unit]->module_id_range.mod_base = mod_base; 9046 src_modid_base_index_bk[unit]->module_id_range.mod_mask = mod_mask; 9047 9048 return BCM_E_NONE; 9049 } 9050 9051 /* 9052 * Function: 9053 * _bcm_esw_stk_multi_next_hops_modid_valid 9054 * Purpose: 9055 * Check the module ID for multiple next hops. 9056 * Parameters: 9057 * modid - (IN) Module ID. 9058 * mod_mask - (IN) The module mask. 9059 * Returns: 9060 * BCM_E_xxx 9061 */ 9062 int _bcm_esw_stk_multi_nexthops_modid_valid(int modid, uint32 mod_mask) 9063 { 9064 int i = 0; 9065 9066 for (i = 0; i < BCM_MAX_NUM_MODID_MASK; i++) { 9067 /* The range only one module */ 9068 if(mod_mask == modid_mask_data[0].mod_mask) { 9069 return BCM_E_NONE; 9070 } 9071 9072 /* The range more than one module */ 9073 if(mod_mask == modid_mask_data[i].mod_mask) { 9074 break; 9075 } 9076 } 9077 9078 for (; i < BCM_MAX_NUM_MODID_MASK; i++) { 9079 if((modid % modid_mask_data[i].num_mods) == 0) { 9080 break; 9081 } 9082 } 9083 9084 if(i == BCM_MAX_NUM_MODID_MASK) { 9085 return BCM_E_PARAM; 9086 } 9087 9088 return BCM_E_NONE; 9089 } 9090 9091 /* 9092 * Function: 9093 * _bcm_esw_stk_multi_nexthops_module_mask_get 9094 * Purpose: 9095 * Get the module mask for the specified number of modules. 9096 * Parameters: 9097 * num_mods - (IN) The number of modules. 9098 * mod_mask - (OUT) The module mask. 9099 * Returns: 9100 * BCM_E_xxx 9101 */ 9102 int _bcm_esw_stk_multi_nexthops_module_mask_get(int num_mods, uint32 *mod_mask) 9103 { 9104 int i = 0; 9105 9106 /* Parameter check */ 9107 if(NULL == mod_mask || num_mods <= 0) { 9108 return BCM_E_PARAM; 9109 } 9110 9111 for (i = 0; i < BCM_MAX_NUM_MODID_MASK; i++) { 9112 if(num_mods == modid_mask_data[i].num_mods) { 9113 break; 9114 } 9115 } 9116 9117 if(i == BCM_MAX_NUM_MODID_MASK) { 9118 return BCM_E_PARAM; 9119 } 9120 9121 *mod_mask = modid_mask_data[i].mod_mask; 9122 9123 return BCM_E_NONE; 9124 } 9125 9126 /* 9127 * Function: 9128 * _bcm_esw_stk_multi_nexthops_modules_num_get 9129 * Purpose: 9130 * Get the number of modules for the specified module mask. 9131 * Parameters: 9132 * mod_mask - (IN) The module mask. 9133 * num_mods - (OUT) The number of modules. 9134 * Returns: 9135 * BCM_E_xxx 9136 */ 9137 9138 int _bcm_esw_stk_multi_nexthops_modules_num_get(uint32 mod_mask, int *num_mods) 9139 { 9140 int i = 0; 9141 9142 /* Parameter check */ 9143 if(NULL == num_mods) { 9144 return BCM_E_PARAM; 9145 } 9146 9147 if(mod_mask == 0) { 9148 *num_mods = 0; 9149 return BCM_E_NONE; 9150 } 9151 9152 for (i = 0; i < BCM_MAX_NUM_MODID_MASK; i++) { 9153 if(mod_mask == modid_mask_data[i].mod_mask) { 9154 break; 9155 } 9156 } 9157 9158 if(i == BCM_MAX_NUM_MODID_MASK) { 9159 return BCM_E_PARAM; 9160 } 9161 9162 *num_mods = modid_mask_data[i].num_mods; 9163 9164 return BCM_E_NONE; 9165 } 9166 9167 /* 9168 * Function: 9169 * _bcm_esw_stk_modid_range_config_add 9170 * Purpose: 9171 * Add a module range of multiple next hop type 9172 * Parameters: 9173 * unit - (IN)SOC unit# 9174 * mod_cfg - (OUT)the value 9175 * Returns: 9176 * BCM_E_XXX 9177 */ 9178 int _bcm_esw_stk_modid_range_config_add(int unit, bcm_stk_modid_config_t *mod_cfg) 9179 { 9180 uint32 mod_mask = 0, old_mod_mask = 0; 9181 int mod_idx = 0, i = 0, rv = 0; 9182 int old_modid = 0, base_index = 0; 9183 int modid = mod_cfg->modid; 9184 int n_ports = mod_cfg->num_ports; 9185 int n_mods = mod_cfg->num_mods; 9186 soc_info_t *si = &SOC_INFO(unit); 9187 9188 /* Parameter check */ 9189 if ((mod_cfg == NULL)||(modid > SOC_MODID_MAX(unit)) || (modid < 0) 9190 || ((n_ports < 0) && (n_ports != -1)) 9191 || (n_ports > SOC_PORT_ADDR_MAX(unit) + 1) 9192 || (mod_cfg->modid_type != bcmStkModidTypeMultiNextHops)) { 9193 return BCM_E_PARAM; 9194 } 9195 9196 if (n_ports == 0) { 9197 /* num_ports 0 for a module only mapping to a local egress port 9198 * and port on this module is ignored during this mapping. 9199 */ 9200 BCM_IF_ERROR_RETURN( 9201 _bcm_esw_stk_multi_nexthops_module_mask_get(mod_cfg->num_mods, 9202 &mod_mask)); 9203 9204 BCM_IF_ERROR_RETURN 9205 (_bcm_esw_stk_multi_nexthops_modid_valid(modid, mod_mask)); 9206 9207 BCM_IF_ERROR_RETURN( 9208 _bcm_esw_stk_modid_range_info_get(unit, &old_modid, &old_mod_mask)); 9209 if ((old_modid && (old_modid != modid)) || 9210 (old_mod_mask && (old_mod_mask != mod_mask))) { 9211 return BCM_E_RESOURCE; 9212 } 9213 9214 for (mod_idx = modid; mod_idx < modid + mod_cfg->num_mods; mod_idx++) { 9215 /* Check if the modid passed in is the same as any of the existing 9216 * mod ids, if it is return error 9217 */ 9218 if (src_modid_base_index_bk[unit]->num_ports[mod_idx] > 0) { 9219 return BCM_E_EXISTS; 9220 } 9221 } 9222 9223 n_ports = 1; 9224 for (mod_idx = modid; mod_idx < modid + mod_cfg->num_mods; mod_idx++) { 9225 rv = _src_modid_base_index_alloc( 9226 unit, mod_idx, n_ports, 0, &base_index); 9227 if (BCM_FAILURE(rv)) { 9228 goto cleanup; 9229 } 9230 src_modid_base_index_bk[unit]->num_ports[mod_idx] = n_ports; 9231 } 9232 9233 BCM_IF_ERROR_RETURN 9234 (_bcm_esw_stk_modid_range_set(unit, modid, mod_mask, 1)); 9235 } else { 9236 if (n_mods > 1) { 9237 return BCM_E_PARAM; 9238 } 9239 9240 /* Now check if the dual_mod id mode is enable, if it is, the modid 9241 * cannot be a odd, since the modid+1 is always reserved for the second 9242 * set of ports 9243 */ 9244 if ((NUM_MODID(unit) > 1) && ((modid % 2) != 0)) { 9245 return BCM_E_PARAM; 9246 } 9247 9248 /* Check if the modid passed in is the same as any of the existing 9249 mod ids, if it is return error */ 9250 if (src_modid_base_index_bk[unit]->num_ports[modid] > 0) { 9251 return BCM_E_EXISTS; 9252 } 9253 9254 /* Check if the current mod list is full */ 9255 for (i = 0; i < si->num_modules; i++) { 9256 if (src_modid_base_index_bk[unit]->module_id_type_list[i] == 0) { 9257 break; 9258 } 9259 } 9260 9261 /* If no room left, send back a resource error */ 9262 if (i == si->num_modules) { 9263 return BCM_E_RESOURCE; 9264 } 9265 9266 /* Start allocating resources based on the 'nports' value */ 9267 if (n_ports == -1) { 9268 /* If nports is '-1' allocate max ports possible */ 9269 n_ports = SOC_PORT_ADDR_MAX(unit) + 1; 9270 } 9271 9272 rv = _src_modid_base_index_alloc(unit, modid, n_ports, 0, 9273 &base_index); 9274 if (BCM_FAILURE(rv)) { 9275 goto cleanup; 9276 } 9277 rv = _bcm_esw_stk_update_mod_config_by_type( 9278 unit, BCM_MODID_TYPE_MULTI_NEXT_HOPS, i+1, modid, 1, 9279 base_index); 9280 if (BCM_FAILURE(rv)) { 9281 goto cleanup; 9282 } 9283 9284 /* Store the number of ports allocated */ 9285 src_modid_base_index_bk[unit]->num_ports[modid] = n_ports; 9286 9287 /* Record the fact that we have added a Multi Nexthop module */ 9288 src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] = modid; 9289 9290 /* Record the module id and type that we have added*/ 9291 src_modid_base_index_bk[unit]->module_id_type_list[i] = 9292 BCM_MODID_TYPE_MULTI_NEXT_HOPS; 9293 } 9294 return BCM_E_NONE; 9295 9296 cleanup: 9297 for (i = modid; i < mod_idx; i++) { 9298 (void) _src_modid_base_index_free(unit, i, 9299 src_modid_base_index_bk[unit]->num_ports[i]); 9300 src_modid_base_index_bk[unit]->num_ports[i] = 0; 9301 } 9302 return rv; 9303 } 9304 9305 /* 9306 * Function: 9307 * _bcm_esw_stk_modid_range_config_get 9308 * Purpose: 9309 * Get the module range config 9310 * Parameters: 9311 * unit - (IN)SOC unit# 9312 * mod_cfg - (OUT)the value 9313 * Returns: 9314 * BCM_E_XXX 9315 */ 9316 int _bcm_esw_stk_modid_range_config_get(int unit, bcm_stk_modid_config_t *mod_cfg) 9317 { 9318 uint32 mod_mask = 0; 9319 int i = 0; 9320 soc_info_t *si = &SOC_INFO(unit); 9321 9322 /* Parameter check */ 9323 if ((mod_cfg == NULL) 9324 || (mod_cfg->modid_type != bcmStkModidTypeMultiNextHops)) { 9325 return BCM_E_PARAM; 9326 } 9327 9328 if (mod_cfg->modid == BCM_MODID_INVALID) { 9329 BCM_IF_ERROR_RETURN( 9330 _bcm_esw_stk_modid_range_info_get(unit, &mod_cfg->modid, 9331 &mod_mask)); 9332 if(!mod_mask) { 9333 mod_cfg->modid = BCM_MODID_INVALID; 9334 } 9335 9336 BCM_IF_ERROR_RETURN( 9337 _bcm_esw_stk_multi_nexthops_modules_num_get(mod_mask, 9338 &mod_cfg->num_mods)); 9339 9340 if (mod_cfg->modid >= 0) { 9341 mod_cfg->num_ports = 0; 9342 } 9343 } else { 9344 if ((mod_cfg->modid < 0) || (mod_cfg->modid > SOC_MODID_MAX(unit))) { 9345 return BCM_E_PARAM; 9346 } 9347 9348 /* Look for and return details for the mod-id passed in */ 9349 for (i = 0; i < si->num_modules; i++) { 9350 if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] 9351 == mod_cfg->modid) { 9352 mod_cfg->num_ports = 9353 src_modid_base_index_bk[unit]->num_ports[mod_cfg->modid]; 9354 mod_cfg->num_mods = 1; 9355 break; 9356 } 9357 } 9358 9359 if (i == si->num_modules) { 9360 return BCM_E_NOT_FOUND; 9361 } 9362 } 9363 9364 return BCM_E_NONE; 9365 } 9366 9367 /* 9368 * Function: 9369 * _bcm_esw_stk_modid_range_config_delete 9370 * Purpose: 9371 * Delete the specific module range 9372 * Parameters: 9373 * unit - (IN) SOC unit# 9374 * modid_type - (IN)The type of module 9375 * Returns: 9376 * BCM_E_XXX 9377 */ 9378 int _bcm_esw_stk_modid_range_config_delete(int unit, 9379 bcm_stk_modid_config_t *mod_cfg) 9380 { 9381 uint32 mod_mask = 0; 9382 int mod_idx = 0, i = 0; 9383 int modid = 0; 9384 int num_mods = 0; 9385 int nports = 0; 9386 soc_info_t *si = &SOC_INFO(unit); 9387 /* Parameter check */ 9388 if (mod_cfg->modid_type != bcmStkModidTypeMultiNextHops) { 9389 return BCM_E_PARAM; 9390 } 9391 9392 if (mod_cfg->modid == BCM_MODID_INVALID) { 9393 BCM_IF_ERROR_RETURN 9394 (_bcm_esw_stk_modid_range_info_get(unit, &modid, &mod_mask)); 9395 if(mod_mask) { 9396 nports = src_modid_base_index_bk[unit]->num_ports[modid]; 9397 } 9398 9399 BCM_IF_ERROR_RETURN( 9400 _bcm_esw_stk_multi_nexthops_modules_num_get(mod_mask, &num_mods)); 9401 for (mod_idx = modid; mod_idx < modid + num_mods; mod_idx++) { 9402 BCM_IF_ERROR_RETURN 9403 (_src_modid_base_index_free(unit, mod_idx, nports)); 9404 src_modid_base_index_bk[unit]->num_ports[mod_idx] = 0; 9405 } 9406 9407 /* Clear MY_MODID_CONFIGr */ 9408 BCM_IF_ERROR_RETURN 9409 (_bcm_esw_stk_modid_range_set(unit, 0, 0, 0)); 9410 } else { 9411 modid = mod_cfg->modid; 9412 if (modid > SOC_MODID_MAX(unit)) { 9413 return BCM_E_PARAM; 9414 } 9415 9416 /* Now check if the dual_mod id mode is enable, if it is, the modid 9417 cannot be a odd, since the modid+1 is always reserved for the second 9418 set of ports */ 9419 if((NUM_MODID(unit) > 1) && ((modid%2) != 0)) { 9420 return BCM_E_PARAM; 9421 } 9422 9423 /* Check if the modid passed in is configured, if it is not 9424 return error */ 9425 if (src_modid_base_index_bk[unit]->num_ports[modid] <= 0) { 9426 return BCM_E_NOT_FOUND; 9427 } 9428 9429 /* Get the index of the Multi Next Hop array where this mod lives */ 9430 for (i = 0; i < si->num_modules; i++) { 9431 if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] == 9432 modid) { 9433 break; 9434 } 9435 } 9436 9437 /* No such module configued, send back an error */ 9438 if (i == si->num_modules) { 9439 return BCM_E_PARAM; 9440 } 9441 9442 BCM_IF_ERROR_RETURN( 9443 _bcm_esw_stk_update_mod_config_by_type(unit, 9444 BCM_MODID_TYPE_MULTI_NEXT_HOPS, i+1, modid, 0, 0)); 9445 9446 /* Get the number of ports for this mod id */ 9447 nports = src_modid_base_index_bk[unit]->num_ports[modid]; 9448 9449 /* Free the range of modports allocated */ 9450 BCM_IF_ERROR_RETURN 9451 (_src_modid_base_index_free(unit, modid, nports)); 9452 9453 /* Reset the number of ports */ 9454 src_modid_base_index_bk[unit]->num_ports[modid] = 0; 9455 9456 /* Record the fact that we this entry is now available */ 9457 src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] = 9458 BCM_MODID_INVALID; 9459 9460 /* Reset the module id type*/ 9461 src_modid_base_index_bk[unit]->module_id_type_list[i] = 0; 9462 } 9463 9464 return BCM_E_NONE; 9465 } 9466 9467 #endif /* #if BCM_TRIDENT2PLUS_SUPPORT */ 9468 9469 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 9470 9471 /* 9472 * Function: 9473 * _bcm_esw_stk_modid_config_add 9474 * Purpose: 9475 * Add a new module 9476 * Parameters: 9477 * unit - (In)SOC unit# 9478 * mod_cfg - (Out)The config parm 9479 * Returns: 9480 * BCM_E_XXX 9481 */ 9482 int 9483 _bcm_esw_stk_modid_config_add( 9484 int unit, 9485 bcm_stk_modid_config_t *mod_cfg) 9486 { 9487 int modid = 0, i = 0, rv = BCM_E_NONE, base_index = 0; 9488 int n_ports = mod_cfg->num_ports; 9489 soc_info_t *si = &SOC_INFO(unit); 9490 9491 /* Parameter check */ 9492 if ((mod_cfg == NULL) || 9493 (mod_cfg->modid < 0) || 9494 (mod_cfg->modid > SOC_MODID_MAX(unit))) { 9495 return BCM_E_PARAM; 9496 } 9497 9498 /* Ensure the number of ports is a valid value */ 9499 if ((n_ports > (SOC_PORT_ADDR_MAX(unit) + 1)) || (n_ports < -1) || 9500 (n_ports == 0)) { 9501 return BCM_E_PARAM; 9502 } 9503 9504 /* Get the module Id */ 9505 modid = mod_cfg->modid; 9506 9507 /* Now check if the dual_mod id mode is enable, if it is, the modid 9508 * cannot be a odd, since the modid+1 is always reserved for the second 9509 * set of ports 9510 */ 9511 if((NUM_MODID(unit) > 1) && ((modid % 2) != 0)) { 9512 return BCM_E_PARAM; 9513 } 9514 9515 /* Check if the modid passed in is the same as any of the existing 9516 mod ids, if it is return error */ 9517 if (src_modid_base_index_bk[unit]->num_ports[modid] > 0) { 9518 return BCM_E_EXISTS; 9519 } 9520 9521 /* Check if the current CoE mod list is full */ 9522 for (i=0; i<si->num_coe_modules; i++) { 9523 if (src_modid_base_index_bk[unit]->coe_module_id_list[i] == 9524 BCM_MODID_INVALID) { 9525 break; 9526 } 9527 } 9528 9529 /* If no room left, send back a resource error */ 9530 if (i == si->num_coe_modules) { 9531 return BCM_E_RESOURCE; 9532 } 9533 9534 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 9535 /* Check if the current mod list is full */ 9536 for (i = 0; i < si->num_modules; i++) { 9537 if (src_modid_base_index_bk[unit]->module_id_type_list[i] == 0) { 9538 break; 9539 } 9540 } 9541 9542 /* If no room left, send back a resource error */ 9543 if (i == si->num_modules) { 9544 return BCM_E_RESOURCE; 9545 } 9546 } 9547 9548 /* Start allocating resources based on the 'nports' value */ 9549 if (n_ports <= -1) { 9550 /* If nports is '-1' allocate max ports possible */ 9551 n_ports = SOC_PORT_ADDR_MAX(unit) + 1; 9552 } 9553 9554 BCM_IF_ERROR_RETURN 9555 (_src_modid_base_index_alloc(unit, modid, n_ports, 0, &base_index)); 9556 9557 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9558 9559 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 9560 9561 9562 9563 /* Program the relevant registers */ 9564 rv = _bcm_esw_stk_update_mod_config_by_type(unit, 9565 BCM_MODID_TYPE_COE, i+1, modid, 1, base_index); 9566 if (BCM_FAILURE(rv)) { 9567 goto cleanup; 9568 } 9569 } 9570 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) */ 9571 9572 #if defined(BCM_KATANA2_SUPPORT) 9573 9574 if (si->coe_stacking_mode) { 9575 uint8 modport_count = 0; 9576 int pp_port_index_min = SOC_INFO(unit).pp_port_index_min; 9577 int subport_port_max = SOC_INFO(unit).subport_port_max; 9578 9579 /* Based on the current mod_index, gather modports already 9580 configured, prior to this index */ 9581 rv = _bcm_stk_index_based_cfg_modport_count(unit, (i+1), 9582 &modport_count); 9583 if (BCM_FAILURE(rv)) { 9584 goto cleanup; 9585 } 9586 9587 /* Make sure there is room to fit the current allocation */ 9588 if ((modport_count + n_ports) > subport_port_max) { 9589 return BCM_E_PARAM; 9590 } 9591 9592 /* Setup the CoE module */ 9593 rv = bcm_kt2_modid_set(unit, (i+1), modid, 1, 9594 (modport_count + pp_port_index_min)); 9595 if (BCM_FAILURE(rv)) { 9596 goto cleanup; 9597 } 9598 } 9599 9600 #endif /* #if defined(BCM_KATANA2_SUPPORT) */ 9601 9602 /* Store the number of ports allocated */ 9603 src_modid_base_index_bk[unit]->num_ports[modid] = n_ports; 9604 9605 /* Record the fact that we have added a CoE module */ 9606 src_modid_base_index_bk[unit]->coe_module_id_list[i] = modid; 9607 9608 /* Record the module id and type that we have added*/ 9609 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 9610 src_modid_base_index_bk[unit]->module_id_type_list[i] = 9611 BCM_MODID_TYPE_COE; 9612 } 9613 9614 cleanup: 9615 9616 /* On a failure, release the allocate resource */ 9617 if (BCM_FAILURE(rv)) { 9618 (void)_src_modid_base_index_free(unit, modid, 9619 src_modid_base_index_bk[unit]->num_ports[modid]); 9620 } 9621 9622 return rv; 9623 } 9624 9625 #endif 9626 9627 /* 9628 * Function: 9629 * bcm_esw_stk_modid_config_add 9630 * Purpose: 9631 * Add a new module or module range 9632 * Parameters: 9633 * unit - (In)SOC unit# 9634 * mod_cfg - (Out)The config parm 9635 * Returns: 9636 * BCM_E_XXX 9637 */ 9638 int 9639 bcm_esw_stk_modid_config_add( 9640 int unit, 9641 bcm_stk_modid_config_t *mod_cfg) 9642 { 9643 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 9644 soc_info_t *si = &SOC_INFO(unit); 9645 #endif /* (BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */ 9646 9647 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 9648 9649 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 9650 /* Parameter check */ 9651 if (mod_cfg == NULL) { 9652 return BCM_E_PARAM; 9653 } 9654 9655 switch (mod_cfg->modid_type) { 9656 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9657 case bcmStkModidTypeMultiNextHops: 9658 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 9659 BCM_IF_ERROR_RETURN 9660 (_bcm_esw_stk_modid_range_config_add(unit, mod_cfg)); 9661 } else { 9662 return BCM_E_UNAVAIL; 9663 } 9664 break; 9665 #endif 9666 case bcmStkModidTypeCoe: 9667 /* If hg_proxy or if (subtag/linkPhy-Coe && stacking-mode) 9668 check the local modid */ 9669 if ((soc_feature(unit, soc_feature_hgproxy_subtag_coe)) || 9670 ((soc_feature(unit, soc_feature_subtag_coe) || 9671 (soc_feature(unit, soc_feature_linkphy_coe))) && 9672 si->coe_stacking_mode)) { 9673 BCM_IF_ERROR_RETURN 9674 (_bcm_esw_stk_modid_config_add(unit, mod_cfg)); 9675 } else { 9676 return BCM_E_UNAVAIL; 9677 } 9678 break; 9679 default: 9680 return BCM_E_UNAVAIL; 9681 } 9682 9683 return BCM_E_NONE; 9684 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT)*/ 9685 9686 return BCM_E_UNAVAIL; 9687 } 9688 9689 9690 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 9691 9692 /* 9693 * Function: 9694 * _bcm_esw_stk_modid_config_delete 9695 * Purpose: 9696 * Add a new module 9697 * Parameters: 9698 * unit - SOC unit# 9699 * my_modid - (IN) The modid value 9700 * force_delete - (IN) True if modid needs to be deleted without checks 9701 * Returns: 9702 * BCM_E_XXX 9703 */ 9704 int 9705 _bcm_esw_stk_modid_config_delete(int unit, int modid, int force_delete) 9706 { 9707 9708 int old_nports = 0, i = 0; 9709 soc_info_t *si = &SOC_INFO(unit); 9710 9711 /* Parameter check */ 9712 if (modid > SOC_MODID_MAX(unit)) { 9713 return BCM_E_PARAM; 9714 } 9715 9716 /* Now check if the dual_mod id mode is enable, if it is, the modid 9717 cannot be a odd, since the modid+1 is always reserved for the second 9718 set of ports */ 9719 if((NUM_MODID(unit) > 1) && ((modid%2) != 0)) { 9720 return BCM_E_PARAM; 9721 } 9722 9723 /* Check if the modid passed in is configured, if it is not 9724 return error */ 9725 if (src_modid_base_index_bk[unit]->num_ports[modid] <= 0) { 9726 return BCM_E_NOT_FOUND; 9727 } 9728 9729 /* Get the index of the CoE array where this mod lives */ 9730 for (i=0; i<si->num_coe_modules; i++) { 9731 if (src_modid_base_index_bk[unit]->coe_module_id_list[i] == 9732 modid) { 9733 break; 9734 } 9735 } 9736 9737 /* No such module configued, send back an error */ 9738 if (i == si->num_coe_modules) { 9739 return BCM_E_PARAM; 9740 } 9741 9742 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9743 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 9744 9745 /* Program the relevant registers */ 9746 _bcm_esw_stk_update_mod_config_by_type(unit, BCM_MODID_TYPE_COE, 9747 i+1, modid, 0, 0); 9748 } 9749 #endif 9750 9751 #if defined(BCM_KATANA2_SUPPORT) 9752 if (si->coe_stacking_mode) { 9753 uint8 mod_cfg = 0; 9754 9755 /* If the 'force_delete' flag is not set, check that the 9756 previous modules are already deleted, this is because 9757 the module are allocated in a sequence */ 9758 if(!force_delete) { 9759 /* Based on the current mod_index, gather modports already 9760 configured, prior to this index */ 9761 BCM_IF_ERROR_RETURN(_bcm_stk_index_based_mod_cfg_check(unit, 9762 (i+1), &mod_cfg)); 9763 if(mod_cfg) { 9764 return BCM_E_CONFIG; 9765 } 9766 } 9767 9768 /* Delete the CoE module info */ 9769 BCM_IF_ERROR_RETURN(bcm_kt2_modid_set(unit, (i+1), 0, 0 /* Not-valid */, 9770 0)); 9771 } 9772 #endif 9773 9774 /* Get the number of ports for this mod id */ 9775 old_nports = src_modid_base_index_bk[unit]->num_ports[modid]; 9776 9777 /* Free the range of modports allocated */ 9778 BCM_IF_ERROR_RETURN 9779 (_src_modid_base_index_free(unit, modid, old_nports)); 9780 9781 /* Reset the number of ports */ 9782 src_modid_base_index_bk[unit]->num_ports[modid] = 0; 9783 9784 /* Record the fact that we this entry is now available */ 9785 src_modid_base_index_bk[unit]->coe_module_id_list[i] = BCM_MODID_INVALID; 9786 9787 /* Reset the module id type*/ 9788 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 9789 src_modid_base_index_bk[unit]->module_id_type_list[i] = 0; 9790 } 9791 9792 return BCM_E_NONE; 9793 } 9794 9795 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */ 9796 9797 /* 9798 * Function: 9799 * bcm_esw_stk_modid_config_delete 9800 * Purpose: 9801 * Delete the specific module 9802 * Parameters: 9803 * unit - SOC unit# 9804 * mod_cfg - (out)the value 9805 * Returns: 9806 * BCM_E_XXX 9807 */ 9808 int 9809 bcm_esw_stk_modid_config_delete(int unit, 9810 bcm_stk_modid_config_t *mod_cfg) 9811 { 9812 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 9813 soc_info_t *si = &SOC_INFO(unit); 9814 #endif /* (BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */ 9815 9816 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 9817 9818 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 9819 /* Parameter check */ 9820 if (mod_cfg == NULL) { 9821 return BCM_E_PARAM; 9822 } 9823 9824 switch (mod_cfg->modid_type) { 9825 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9826 case bcmStkModidTypeMultiNextHops: 9827 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 9828 BCM_IF_ERROR_RETURN 9829 (_bcm_esw_stk_modid_range_config_delete(unit, mod_cfg)); 9830 } else { 9831 return BCM_E_UNAVAIL; 9832 } 9833 break; 9834 #endif 9835 case bcmStkModidTypeCoe: 9836 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) || 9837 si->coe_stacking_mode) { 9838 BCM_IF_ERROR_RETURN 9839 (_bcm_esw_stk_modid_config_delete(unit, mod_cfg->modid, 9840 0 /* Not a force_delete, since this is not 'delete_all' */)); 9841 } else { 9842 return BCM_E_UNAVAIL; 9843 } 9844 break; 9845 default: 9846 return BCM_E_UNAVAIL; 9847 } 9848 9849 return BCM_E_NONE; 9850 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */ 9851 return BCM_E_UNAVAIL; 9852 } 9853 9854 /* 9855 * Function: 9856 * bcm_esw_stk_modid_config_delete_all 9857 * Purpose: 9858 * Add a new module 9859 * Parameters: 9860 * unit - SOC unit# 9861 * my_modid - (out)the value 9862 * Returns: 9863 * BCM_E_XXX 9864 */ 9865 int 9866 bcm_esw_stk_modid_config_delete_all(int unit) 9867 { 9868 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 9869 soc_info_t *si=&SOC_INFO(unit); 9870 #endif /* (BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */ 9871 9872 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 9873 9874 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 9875 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) || 9876 si->coe_stacking_mode) { 9877 9878 int i = 0; 9879 9880 /* Check if the current CoE mod list is full */ 9881 for (i=0; i<si->num_coe_modules; i++) { 9882 if (src_modid_base_index_bk[unit]->coe_module_id_list[i] != 9883 BCM_MODID_INVALID) { 9884 BCM_IF_ERROR_RETURN(_bcm_esw_stk_modid_config_delete(unit, 9885 src_modid_base_index_bk[unit]->coe_module_id_list[i], 9886 1 /* Force_delete, since this is a 'delete_all' */)); 9887 } 9888 } 9889 } 9890 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 9891 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 9892 int i = 0; 9893 bcm_stk_modid_config_t mod_cfg; 9894 bcm_stk_modid_config_t_init(&mod_cfg); 9895 9896 mod_cfg.modid_type = bcmStkModidTypeMultiNextHops; 9897 mod_cfg.modid = BCM_MODID_INVALID; 9898 BCM_IF_ERROR_RETURN 9899 (_bcm_esw_stk_modid_range_config_delete(unit, &mod_cfg)); 9900 9901 for (i = 0; i < si->num_modules; i++) { 9902 if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] != 9903 BCM_MODID_INVALID) { 9904 mod_cfg.modid_type = bcmStkModidTypeMultiNextHops; 9905 mod_cfg.modid = 9906 src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i]; 9907 BCM_IF_ERROR_RETURN 9908 (_bcm_esw_stk_modid_range_config_delete(unit, &mod_cfg)); 9909 } 9910 } 9911 } 9912 #endif 9913 9914 return BCM_E_NONE; 9915 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */ 9916 9917 return BCM_E_UNAVAIL; 9918 } 9919 9920 /* 9921 * Function: 9922 * bcm_esw_stk_modid_config_set 9923 * Purpose: 9924 * Sets a module id 9925 * Parameters: 9926 * unit - SOC unit# 9927 * my_modid - (out)the value 9928 * Returns: 9929 * BCM_E_XXX 9930 */ 9931 9932 int 9933 bcm_esw_stk_modid_config_set(int unit, 9934 bcm_stk_modid_config_t *mod_cfg) 9935 { 9936 return BCM_E_UNAVAIL; 9937 } 9938 9939 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 9940 /* 9941 * Function: 9942 * _bcm_esw_stk_modid_config_get 9943 * Purpose: 9944 * Get the module config 9945 * Parameters: 9946 * unit - (IN)SOC unit# 9947 * mod_cfg - (OUT)the module config 9948 * Returns: 9949 * BCM_E_XXX 9950 */ 9951 int 9952 _bcm_esw_stk_modid_config_get(int unit, 9953 bcm_stk_modid_config_t *mod_cfg) 9954 { 9955 int i = 0; 9956 soc_info_t *si = &SOC_INFO(unit); 9957 9958 /* Parameter check */ 9959 if ((mod_cfg == NULL) || 9960 (mod_cfg->modid < 0) || 9961 (mod_cfg->modid > SOC_MODID_MAX(unit))) { 9962 return BCM_E_PARAM; 9963 } 9964 9965 /* Look for and return details for the mod-id passed in */ 9966 for (i = 0; i < si->num_coe_modules; i++) { 9967 if (src_modid_base_index_bk[unit]->coe_module_id_list[i] == 9968 mod_cfg->modid) { 9969 mod_cfg->num_ports = 9970 src_modid_base_index_bk[unit]->num_ports[mod_cfg->modid]; 9971 break; 9972 } 9973 } 9974 9975 if (i == si->num_coe_modules) { 9976 return BCM_E_NOT_FOUND; 9977 } 9978 9979 return BCM_E_NONE; 9980 } 9981 9982 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) */ 9983 9984 /* 9985 * Function: 9986 * bcm_esw_stk_modid_config_get 9987 * Purpose: 9988 * Get the module config 9989 * Parameters: 9990 * unit - SOC unit# 9991 * my_modid - (out)the value 9992 * Returns: 9993 * BCM_E_XXX 9994 */ 9995 int 9996 bcm_esw_stk_modid_config_get(int unit, 9997 bcm_stk_modid_config_t *mod_cfg) 9998 { 9999 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 10000 soc_info_t *si=&SOC_INFO(unit); 10001 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(KATANA2_SUPPORT) */ 10002 10003 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 10004 10005 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 10006 /* Parameter check */ 10007 if (mod_cfg == NULL) { 10008 return BCM_E_PARAM; 10009 } 10010 10011 switch (mod_cfg->modid_type) { 10012 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 10013 case bcmStkModidTypeMultiNextHops: 10014 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 10015 BCM_IF_ERROR_RETURN 10016 (_bcm_esw_stk_modid_range_config_get(unit, mod_cfg)); 10017 } else { 10018 return BCM_E_UNAVAIL; 10019 } 10020 break; 10021 #endif 10022 case bcmStkModidTypeCoe: 10023 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) || 10024 si->coe_stacking_mode) { 10025 BCM_IF_ERROR_RETURN 10026 (_bcm_esw_stk_modid_config_get(unit, mod_cfg)); 10027 } else { 10028 return BCM_E_UNAVAIL; 10029 } 10030 break; 10031 default: 10032 return BCM_E_UNAVAIL; 10033 } 10034 10035 return BCM_E_NONE; 10036 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(KATANA2_SUPPORT) */ 10037 10038 return BCM_E_UNAVAIL; 10039 } 10040 10041 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 10042 10043 /* 10044 * Function: 10045 * _bcm_stk_aux_modport_info_get 10046 * Purpose: 10047 * Get module info by type 10048 * Parameters: 10049 * unit - SOC unit# 10050 * type - To identify the type of module 10051 * modList - Array that holds the module list 10052 * portNum - Number of ports for each of the modules 10053 * in the modList 10054 * Returns: 10055 * BCM_E_XXX 10056 */ 10057 int 10058 _bcm_stk_aux_modport_info_get(int unit, uint32 type, 10059 bcm_stk_modid_config_t *modIdInfo) 10060 { 10061 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 10062 10063 int i=0, j=0; 10064 soc_info_t *si=&SOC_INFO(unit); 10065 10066 /* Make sure the caller has provided a valid type of module */ 10067 if(!(type & BCM_MODID_TYPE_COE)) { 10068 return BCM_E_INTERNAL; 10069 } 10070 10071 /* Look for and return details for the mod-id passed in */ 10072 for (i=0; i<si->num_coe_modules; i++) { 10073 if (src_modid_base_index_bk[unit]->coe_module_id_list[i] != 10074 BCM_MODID_INVALID) { 10075 /* Assign the module Id */ 10076 modIdInfo[j].modid = src_modid_base_index_bk[unit]-> 10077 coe_module_id_list[i]; 10078 /* Assign ports configured on that moduleId */ 10079 modIdInfo[j].num_ports = src_modid_base_index_bk[unit]-> 10080 num_ports[modIdInfo[j].modid]; 10081 10082 /* Increment module counter*/ 10083 j++; 10084 } 10085 } 10086 } 10087 10088 return BCM_E_NONE; 10089 } 10090 10091 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(KATANA2_SUPPORT)*/ 10092 10093 /* 10094 * Function: 10095 * bcm_esw_stk_modid_config_get_all 10096 * Purpose: 10097 * Add a new module 10098 * Parameters: 10099 * unit - SOC unit# 10100 * my_modid - (out)the value 10101 * Returns: 10102 * BCM_E_XXX 10103 */ 10104 int 10105 bcm_esw_stk_modid_config_get_all(int unit, 10106 int modid_max, 10107 bcm_stk_modid_config_t *modid_array, 10108 int *modid_count) 10109 { 10110 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 10111 soc_info_t *si=&SOC_INFO(unit); 10112 #endif /* #if BCM_TRIDENT2PLUS_SUPPORT || defined(BCM_KATANA2_SUPPORT) */ 10113 10114 BCM_STK_API_TH3_SUPPORT_CHECK(unit); 10115 10116 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 10117 if(modid_count) { 10118 *modid_count = 0; 10119 } else { 10120 return BCM_E_PARAM; 10121 } 10122 10123 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 10124 if (soc_feature(unit, soc_feature_multi_next_hops_on_port)) { 10125 int i = 0; 10126 bcm_stk_modid_config_t mod_cfg; 10127 mod_cfg.modid_type = bcmStkModidTypeMultiNextHops; 10128 mod_cfg.modid = BCM_MODID_INVALID; 10129 BCM_IF_ERROR_RETURN 10130 (bcm_esw_stk_modid_config_get(unit, &mod_cfg)); 10131 if (mod_cfg.modid != BCM_MODID_INVALID) { 10132 if(modid_max == 0) { 10133 (*modid_count)++; 10134 } else { 10135 if(modid_max && modid_array) { 10136 modid_array[*modid_count].modid = mod_cfg.modid; 10137 modid_array[*modid_count].num_mods = mod_cfg.num_mods; 10138 modid_array[*modid_count].modid_type = bcmStkModidTypeMultiNextHops; 10139 modid_array[*modid_count].num_ports = 0; 10140 10141 /* Keep incrementing the number of modules processed */ 10142 (*modid_count)++; 10143 /* Keep decrementing the number of mods requested */ 10144 if(modid_max > 0) { 10145 --modid_max; 10146 } 10147 } 10148 } 10149 } 10150 10151 /* If the 'modid_max' is 0, the user only wants to get a count of modIds */ 10152 if(modid_max == 0) { 10153 for (i = 0; i < si->num_modules; i++) { 10154 if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] != 10155 BCM_MODID_INVALID) { 10156 /* Keep incrementing the number of modules processed */ 10157 (*modid_count)++; 10158 } 10159 } 10160 } else { 10161 /* Run through the CoE mod list and fill in needed data */ 10162 for (i = 0; i < si->num_modules; i++) { 10163 if (src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i] == 10164 BCM_MODID_INVALID) { 10165 continue; 10166 } 10167 10168 /* Fill in the modid data if the modid_max is non-zero and the 10169 *data place holder is allocated 10170 */ 10171 if(modid_max && modid_array) { 10172 modid_array[*modid_count].modid = 10173 src_modid_base_index_bk[unit]->multi_nexthop_module_id_list[i]; 10174 modid_array[*modid_count].num_ports = 10175 src_modid_base_index_bk[unit]->num_ports[modid_array[*modid_count].modid]; 10176 modid_array[*modid_count].modid_type = 10177 bcmStkModidTypeMultiNextHops; 10178 modid_array[*modid_count].num_mods = 1; 10179 10180 /* Keep incrementing the number of modules processed */ 10181 (*modid_count)++; 10182 /* Keep decrementing the number of mods requested */ 10183 if(modid_max > 0) { 10184 --modid_max; 10185 } 10186 } 10187 } 10188 } 10189 } 10190 #endif 10191 10192 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) || 10193 si->coe_stacking_mode) { 10194 10195 int i = 0; 10196 /* If the 'modid_max' is 0, the user only wants to get a count of modIds */ 10197 if(modid_max == 0) { 10198 for (i=0; i<si->num_coe_modules; i++) { 10199 if (src_modid_base_index_bk[unit]->coe_module_id_list[i] != 10200 BCM_MODID_INVALID) { 10201 /* Keep incrementing the number of modules processed */ 10202 (*modid_count)++; 10203 } 10204 } 10205 return BCM_E_NONE; 10206 } 10207 10208 /* Run through the CoE mod list and fill in needed data */ 10209 for (i=0; i<si->num_coe_modules; i++) { 10210 if (src_modid_base_index_bk[unit]->coe_module_id_list[i] != 10211 BCM_MODID_INVALID) { 10212 10213 /* Fill in the modid data if the modid_max is non-zero and the 10214 data place holder is allocated */ 10215 if(modid_max && modid_array) { 10216 modid_array[*modid_count].modid = src_modid_base_index_bk[unit]-> 10217 coe_module_id_list[i]; 10218 modid_array[*modid_count].num_ports = src_modid_base_index_bk[unit]-> 10219 num_ports[modid_array[i].modid]; 10220 modid_array[*modid_count].modid_type = bcmStkModidTypeCoe; 10221 10222 /* Keep incrementing the number of modules processed */ 10223 (*modid_count)++; 10224 /* Keep decrementing the number of mods requested */ 10225 if(modid_max > 0) { 10226 --modid_max; 10227 } 10228 } 10229 } 10230 } 10231 } 10232 10233 return BCM_E_NONE; 10234 #endif /* #if BCM_TRIDENT2PLUS_SUPPORT */ 10235 10236 return BCM_E_UNAVAIL; 10237 } 10238 10239 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 10240 10241 int _bcm_stk_aux_modport_valid(int unit, uint32 type, 10242 int modid, bcm_port_t port) 10243 { 10244 int num_ports = 0, i = 0; 10245 soc_info_t *si=&SOC_INFO(unit); 10246 10247 /* Make sure the caller has provided a valid type of module */ 10248 if(!(type & BCM_MODID_TYPE_COE)) { 10249 return BCM_E_INTERNAL; 10250 } 10251 10252 for (i=0; i<si->num_coe_modules; i++) { 10253 /* First check if the modId passed in is one of the CoE modIds */ 10254 if (src_modid_base_index_bk[unit]->coe_module_id_list[i] == 10255 modid) { 10256 num_ports = src_modid_base_index_bk[unit]-> 10257 num_ports[modid]; 10258 10259 /* If the num_ports for the mod is valid, check if 10260 the passed in 'port' is within range */ 10261 if(num_ports <= 0) { 10262 return BCM_E_NOT_FOUND; 10263 } else if((port >= 0) && (port < num_ports)) { 10264 return BCM_E_NONE; 10265 } 10266 } 10267 } 10268 10269 /* Send back a 'Not_Found' by default */ 10270 return BCM_E_NOT_FOUND; 10271 } 10272 10273 int _bcm_stk_aux_mod_valid(int unit, uint32 type, int modid) 10274 { 10275 int i = 0; 10276 soc_info_t *si=&SOC_INFO(unit); 10277 10278 /* Make sure the caller has provided a valid type of module */ 10279 if(!(type & BCM_MODID_TYPE_COE)) { 10280 return BCM_E_INTERNAL; 10281 } 10282 10283 for (i=0; i<si->num_coe_modules; i++) { 10284 /* First check if the modId passed in is one of the CoE modIds */ 10285 if (src_modid_base_index_bk[unit]->coe_module_id_list[i] == 10286 modid) { 10287 return BCM_E_NONE; 10288 } 10289 } 10290 10291 if(i == si->num_coe_modules) { 10292 return BCM_E_NOT_FOUND; 10293 } 10294 10295 /* Send back a 'Not_Found' by default */ 10296 return BCM_E_NOT_FOUND; 10297 } 10298 10299 #endif /* #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(KATANA2_SUPPORT) */ 10300 10301 /* 10302 * Function: 10303 * bcm_esw_stk_module_control_set 10304 * Purpose: 10305 * Set module controls. 10306 * Parameters: 10307 * unit - Device unit number 10308 * flags - Flags with options 10309 * module - The module on which the contrl needs to be set 10310 * control - The actual control to be set 10311 * arg - The value for the control to be set 10312 * Returns: 10313 * None 10314 */ 10315 10316 int 10317 bcm_esw_stk_module_control_set(int unit, 10318 uint32 flags, 10319 bcm_module_t module, 10320 bcm_stk_module_control_t control, 10321 int arg) 10322 { 10323 10324 int rv = BCM_E_UNAVAIL; 10325 10326 if (soc_feature(unit, soc_feature_hg_proxy_module_config)) { 10327 10328 soc_info_t *si = &SOC_INFO(unit); 10329 source_mod_proxy_table_entry_t source_mod_proxy_entry; 10330 soc_mem_t mem = SOURCE_MOD_PROXY_TABLEm; 10331 int rv; 10332 10333 /* The only supported control currently is 10334 'bcmStkModuleMHPriorityUse' */ 10335 if (control != bcmStkModuleMHPriorityUse) { 10336 return BCM_E_UNAVAIL; 10337 } 10338 10339 /* Ensure the module is within range */ 10340 if ((module < 0) || (module > si->modid_max)) { 10341 return BCM_E_PARAM; 10342 } 10343 10344 /* Ensure the arg is no greater than '1' */ 10345 if ((arg < 0) || (arg > 1)) { 10346 return BCM_E_PARAM; 10347 } 10348 10349 /* Get the mem entry and write the desired value */ 10350 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, module, 10351 &source_mod_proxy_entry); 10352 if (SOC_FAILURE(rv)) { 10353 LOG_ERROR(BSL_LS_BCM_STK, 10354 (BSL_META_U(unit, 10355 "ERROR:SOURCE_MOD_PROXYm read failed\n"))); 10356 return rv; 10357 } 10358 10359 rv = soc_mem_field32_modify(unit, mem , module, USE_MH_PRIORITYf, 10360 arg); 10361 10362 if (SOC_FAILURE(rv)) { 10363 LOG_ERROR(BSL_LS_BCM_STK, 10364 (BSL_META_U(unit, 10365 "ERROR: MH Priority setting failed" 10366 "for module %d\n"), 10367 module)); 10368 return rv; 10369 } 10370 10371 return rv; 10372 10373 } 10374 10375 return rv; 10376 } 10377 10378 /* 10379 * Function: 10380 * bcm_esw_stk_module_control_get 10381 * Purpose: 10382 * Get module controls. 10383 * Parameters: 10384 * unit - Device unit number 10385 * flags - Flags with options 10386 * module - The module from which the control value needs to be got from 10387 * control - The actual control to be retrirved 10388 * arg - The value for the control to be set 10389 * Returns: 10390 * None 10391 */ 10392 10393 int 10394 bcm_esw_stk_module_control_get(int unit, 10395 uint32 flags, 10396 bcm_module_t module, 10397 bcm_stk_module_control_t control, 10398 int *arg) 10399 { 10400 10401 int rv = BCM_E_UNAVAIL; 10402 10403 if (soc_feature(unit, soc_feature_hg_proxy_module_config)) { 10404 10405 soc_info_t *si = &SOC_INFO(unit); 10406 source_mod_proxy_table_entry_t source_mod_proxy_entry; 10407 soc_mem_t mem = SOURCE_MOD_PROXY_TABLEm; 10408 10409 /* The only supported control currently is 10410 'bcmStkModuleMHPriorityUse' */ 10411 if (control != bcmStkModuleMHPriorityUse) { 10412 return BCM_E_UNAVAIL; 10413 } 10414 10415 /* Ensure the module is within range */ 10416 if ((module < 0) || (module > si->modid_max)) { 10417 return BCM_E_PARAM; 10418 } 10419 10420 /* Get the mem entry and read the desired field */ 10421 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, module, 10422 &source_mod_proxy_entry); 10423 10424 if (SOC_FAILURE(rv)) { 10425 LOG_ERROR(BSL_LS_BCM_STK, 10426 (BSL_META_U(unit, 10427 "ERROR:SOURCE_MOD_PROXYm read failed" 10428 "for module %d\n"), 10429 module)); 10430 return rv; 10431 } 10432 10433 *arg = soc_mem_field32_get(unit, mem, &source_mod_proxy_entry, 10434 USE_MH_PRIORITYf); 10435 10436 10437 return rv; 10438 10439 } 10440 10441 return rv; 10442 10443 } 10444 10445 10446 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 10447 /* 10448 * Function: 10449 * _bcm_stk_sw_dump 10450 * Purpose: 10451 * Displays Stack software structure information. 10452 * Parameters: 10453 * unit - Device unit number 10454 * Returns: 10455 * None 10456 */ 10457 void 10458 _bcm_stk_sw_dump(int unit) 10459 { 10460 char pfmt[SOC_PBMP_FMT_LEN]; 10461 10462 LOG_CLI((BSL_META_U(unit, 10463 "\nSW Information Stack - Unit %d\n\n"), unit)); 10464 10465 /* Source module id */ 10466 LOG_CLI((BSL_META_U(unit, 10467 " Source Module Id: %d\n\n"), SOC_BASE_MODID(unit))); 10468 10469 /* Stack port bitmaps */ 10470 LOG_CLI((BSL_META_U(unit, 10471 " Stack Ports\n"))); 10472 LOG_CLI((BSL_META_U(unit, 10473 " Current : %s\n"), 10474 SOC_PBMP_FMT(SOC_PBMP_STACK_CURRENT(unit), pfmt))); 10475 LOG_CLI((BSL_META_U(unit, 10476 " Inactive: %s\n"), 10477 SOC_PBMP_FMT(SOC_PBMP_STACK_INACTIVE(unit), pfmt))); 10478 LOG_CLI((BSL_META_U(unit, 10479 " Previous: %s\n"), 10480 SOC_PBMP_FMT(SOC_PBMP_STACK_PREVIOUS(unit), pfmt))); 10481 LOG_CLI((BSL_META_U(unit, 10482 "\n"))); 10483 10484 #if defined(BCM_TRX_SUPPORT) 10485 /* Modport profile */ 10486 /* Display those entries with reference count > 0 */ 10487 if (modport_profile[unit] != NULL) { 10488 int i; 10489 int num_entries; 10490 int ref_count; 10491 int entries_per_set; 10492 int modid_count; 10493 uint32 index; 10494 pbmp_t hg_pbmp; 10495 modport_map_entry_t *entry_p; 10496 int dest_is_hg_pbmp = 0; 10497 int p; 10498 int profile_index; 10499 bcmi_trx_modport_map_profile_t profile; 10500 int istrunk, dest; 10501 10502 num_entries = soc_mem_index_count 10503 (unit, modport_profile[unit]->tables[0].mem); 10504 LOG_CLI((BSL_META_U(unit, 10505 " Stack Modport Profile\n"))); 10506 LOG_CLI((BSL_META_U(unit, 10507 " Number of entries: %d\n"), num_entries)); 10508 LOG_CLI((BSL_META_U(unit, 10509 " Index RefCount EntriesPerSet - " 10510 "HIGIG_PORT_BITMAP\n"))); 10511 10512 sal_memset(&profile, 0x0, sizeof(profile)); 10513 if (soc_feature(unit, soc_feature_modport_map_dest_is_hg_port_bitmap)) { 10514 dest_is_hg_pbmp = 1; 10515 } 10516 10517 modid_count = SOC_MODID_MAX(unit) + 1; 10518 for (index = 0; index < num_entries; index += modid_count) { 10519 if (SOC_FAILURE 10520 (soc_profile_mem_ref_count_get(unit, 10521 modport_profile[unit], 10522 index, &ref_count))) { 10523 break; 10524 } 10525 10526 if (ref_count <= 0) { 10527 continue; 10528 } 10529 10530 if (dest_is_hg_pbmp) { 10531 profile_index = (index / modid_count); 10532 profile = TRX_MODPORT_MAP_PROFILE(unit, profile_index); 10533 } 10534 for (i = 0; i < modid_count; i++) { 10535 entries_per_set = 10536 modport_profile[unit]->tables[0].entries[index+i].entries_per_set; 10537 LOG_CLI((BSL_META_U(unit, 10538 " %5d %8d %13d "), 10539 index + i, ref_count, entries_per_set)); 10540 10541 switch (BCM_CHIP_FAMILY(unit)) { 10542 case BCM_FAMILY_TRIUMPH: 10543 case BCM_FAMILY_TRIUMPH2: 10544 entry_p = SOC_PROFILE_MEM_ENTRY(unit, 10545 modport_profile[unit], 10546 modport_map_entry_t *, 10547 index + i); 10548 soc_mem_pbmp_field_get(unit, MODPORT_MAPm, entry_p, 10549 HIGIG_PORT_BITMAPf, &hg_pbmp); 10550 LOG_CLI((BSL_META_U(unit, 10551 "%s\n"), SOC_PBMP_FMT(hg_pbmp, pfmt))); 10552 10553 if (dest_is_hg_pbmp) { 10554 if (profile.ref_count == 0) { 10555 continue; 10556 } 10557 for (p = 0; p < SOC_MAX_NUM_PORTS; p++) { 10558 if (SOC_PORT_VALID(unit, p)) { 10559 istrunk = 10560 profile.entry_array[i].dest_istrunk[p]; 10561 dest = profile.entry_array[i].dest[p]; 10562 if (dest != 0) { 10563 LOG_CLI((BSL_META_U(unit, 10564 "dest_istrunk[%d]=%d, " 10565 "dest[%d]=%d\n"), 10566 p, istrunk, p, dest)); 10567 } 10568 } 10569 } 10570 } 10571 break; 10572 default: 10573 BCM_PBMP_CLEAR(hg_pbmp); 10574 LOG_CLI((BSL_META_U(unit, 10575 "%s\n"), SOC_PBMP_FMT(hg_pbmp, pfmt))); 10576 break; 10577 } 10578 } 10579 } 10580 } 10581 #endif /* BCM_TRX_SUPPORT */ 10582 10583 #if defined(BCM_TRIDENT_SUPPORT) 10584 if (soc_feature(unit, soc_feature_modport_map_dest_is_port_or_trunk)) { 10585 bcm_td_modport_map_sw_dump(unit); 10586 } 10587 #endif /* BCM_TRIDENT_SUPPORT */ 10588 10589 #if defined(LOCAL_MODMAP_SUPPORT) 10590 /* Modmap information */ 10591 if (mod_map_data[unit] != NULL) { 10592 int i; 10593 int num; 10594 int count; 10595 10596 LOG_CLI((BSL_META_U(unit, 10597 "\n Stack Modmap Data\n"))); 10598 10599 count = 0; 10600 num = COUNTOF(mod_map_data[unit]->l_modid); 10601 LOG_CLI((BSL_META_U(unit, 10602 " l_modid: "))); 10603 for (i = 0; i < num; i++) { 10604 if ((count > 0) && (!(count % 10))) { 10605 LOG_CLI((BSL_META_U(unit, 10606 "\n "))); 10607 } 10608 LOG_CLI((BSL_META_U(unit, 10609 " %4d"), mod_map_data[unit]->l_modid[i])); 10610 count++; 10611 } 10612 LOG_CLI((BSL_META_U(unit, 10613 "\n"))); 10614 10615 count = 0; 10616 num = COUNTOF(mod_map_data[unit]->thresh_d); 10617 LOG_CLI((BSL_META_U(unit, 10618 " thresh_d:"))); 10619 for (i = 0; i < num; i++) { 10620 if ((count > 0) && (!(count % 10))) { 10621 LOG_CLI((BSL_META_U(unit, 10622 "\n "))); 10623 } 10624 LOG_CLI((BSL_META_U(unit, 10625 " %4d"), mod_map_data[unit]->thresh_d[i])); 10626 count++; 10627 } 10628 LOG_CLI((BSL_META_U(unit, 10629 "\n"))); 10630 10631 count = 0; 10632 LOG_CLI((BSL_META_U(unit, 10633 " fmod0: "))); 10634 num = COUNTOF(mod_map_data[unit]->fmod0); 10635 for (i = 0; i < num; i++) { 10636 if ((count > 0) && (!(count % 10))) { 10637 LOG_CLI((BSL_META_U(unit, 10638 "\n "))); 10639 } 10640 LOG_CLI((BSL_META_U(unit, 10641 " %4d"), mod_map_data[unit]->fmod0[i])); 10642 count++; 10643 } 10644 LOG_CLI((BSL_META_U(unit, 10645 "\n"))); 10646 } 10647 #endif /* MODMAP_SUPPORT */ 10648 10649 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 10650 if (soc_feature(unit, soc_feature_src_modid_base_index)) { 10651 int i, rv, base_index; 10652 source_trunk_map_modbase_entry_t stm_modbase_entry; 10653 10654 LOG_CLI((BSL_META_U(unit, 10655 "\n Stack Source Trunk Map Modbase Data\n"))); 10656 10657 for (i = 0; i <= SOC_MODID_MAX(unit) ; i++) { 10658 rv = READ_SOURCE_TRUNK_MAP_MODBASEm(unit, MEM_BLOCK_ANY, i, 10659 &stm_modbase_entry); 10660 if (SOC_FAILURE(rv)) { 10661 continue; 10662 } 10663 base_index = soc_SOURCE_TRUNK_MAP_MODBASEm_field32_get(unit, 10664 &stm_modbase_entry, BASEf); 10665 if (src_modid_base_index_bk[unit]->default_base_idx == base_index) { 10666 continue; 10667 } 10668 LOG_CLI((BSL_META_U(unit, 10669 " Modid %3d, "), i)); 10670 LOG_CLI((BSL_META_U(unit, 10671 "source trunk map modbase index %4d, "), base_index)); 10672 LOG_CLI((BSL_META_U(unit, 10673 "num_ports %2d\n"), 10674 src_modid_base_index_bk[unit]->num_ports[i])); 10675 } 10676 10677 if (src_modid_base_index_bk[unit]->coe_module_id_list) { 10678 LOG_CLI((BSL_META_U(unit, "CoE mod list: %3d %3d %3d %3d %3d\n"), 10679 src_modid_base_index_bk[unit]->coe_module_id_list[0], 10680 src_modid_base_index_bk[unit]->coe_module_id_list[1], 10681 src_modid_base_index_bk[unit]->coe_module_id_list[2], 10682 src_modid_base_index_bk[unit]->coe_module_id_list[3], 10683 src_modid_base_index_bk[unit]->coe_module_id_list[4])); 10684 } 10685 } 10686 #endif /* BCM_TRIDENT_SUPPORT || BCM_HURRICANE3_SUPPORT */ 10687 10688 #ifdef BCM_RPC_SUPPORT 10689 #if defined(BROADCOM_DEBUG) 10690 bcm_rlink_dump(); 10691 atp_dump(1); 10692 #endif 10693 #endif 10694 10695 return; 10696 } 10697 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 10698