stack.c (79559B)
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: This file manages MODPORT_MAP_SW table in Trident. 9 */ 10 11 #include <soc/defs.h> 12 #include <sal/core/libc.h> 13 #include <shared/bsl.h> 14 #if defined(BCM_TRIDENT_SUPPORT) 15 16 #include <soc/mem.h> 17 #include <soc/drv.h> 18 19 #include <bcm/error.h> 20 #include <bcm/types.h> 21 #include <bcm/trunk.h> 22 23 #include <bcm_int/esw_dispatch.h> 24 #include <bcm_int/esw/stack.h> 25 26 #if defined(BCM_KATANA2_SUPPORT) 27 #include <bcm_int/esw/katana2.h> 28 #endif 29 30 #define _BCM_TD_STK_HGT_GROUP_MAX 128 31 32 #define _BCM_STK_HGT_GROUP_MAX _BCM_TD_STK_HGT_GROUP_MAX 33 34 typedef struct _bcm_td_modport_map_entry_s { 35 uint8 dest_enable[2]; 36 uint8 dest_istrunk[2]; 37 uint8 dest[2]; 38 SHR_BITDCL higig_trunk_override[_SHR_BITDCLSIZE(_BCM_STK_HGT_GROUP_MAX)]; 39 uint8 voq_cos_valid; 40 uint8 voq_group_id; 41 } _bcm_td_modport_map_entry_t; 42 43 typedef struct _bcm_td_modport_map_profile_s { 44 int ref_count; 45 int num_entries; 46 _bcm_td_modport_map_entry_t *entry_array; 47 } _bcm_td_modport_map_profile_t; 48 49 typedef struct _bcm_td_modport_map_info_s { 50 int auto_include_disable; /* Disables automatic inclusion of all members 51 of a Higig trunk group when one of its members 52 is specified as the steering destination for 53 a remote module */ 54 int num_profiles; 55 _bcm_td_modport_map_profile_t *profile_array; 56 } _bcm_td_modport_map_info_t; 57 58 STATIC _bcm_td_modport_map_info_t _bcm_td_modport_map_info[BCM_MAX_NUM_UNITS]; 59 60 #define MODPORT_MAP_INFO(unit) _bcm_td_modport_map_info[unit] 61 #define MODPORT_MAP_PROFILE(unit, index) \ 62 _bcm_td_modport_map_info[unit].profile_array[index] 63 64 /* 65 * Function: 66 * _bcm_td_modport_map_mirror_profile_hw_copy 67 * Purpose: 68 * Copy modport map profile from MODPORT_MAP_SW to MODPORT_MAP_MIRROR. 69 * Parameters: 70 * unit - SOC unit #. 71 * index_min - Staring index. 72 * index_max - Ending index. 73 * modport_map_sw_buf - Buffer of MODPORT_MAP_SW. 74 * Returns: 75 * BCM_E_XXX 76 */ 77 STATIC int 78 _bcm_td_modport_map_mirror_profile_hw_copy(int unit, int index_min, 79 int index_max, uint8 *modport_map_sw_buf) 80 { 81 int rv = BCM_E_NONE; 82 int num_entries; 83 int mirror_buf_size; 84 uint8 *mirror_buf = NULL; 85 int i; 86 modport_map_sw_entry_t *modport_map_sw_entry; 87 int enable, istrunk, dest; 88 modport_map_mirror_entry_t *mirror_entry; 89 90 num_entries = index_max - index_min + 1; 91 mirror_buf_size = num_entries * 92 soc_mem_entry_words(unit, MODPORT_MAP_MIRRORm) * 4; 93 mirror_buf = soc_cm_salloc(unit, mirror_buf_size, 94 "modport map mirror buffer"); 95 if (NULL == mirror_buf) { 96 return BCM_E_MEMORY; 97 } 98 sal_memset(mirror_buf, 0, mirror_buf_size); 99 100 for (i = 0; i < num_entries; i++) { 101 modport_map_sw_entry = soc_mem_table_idx_to_pointer(unit, MODPORT_MAP_SWm, 102 modport_map_sw_entry_t *, modport_map_sw_buf, i); 103 enable = soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry, 104 ENABLE0f); 105 istrunk = soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry, 106 ISTRUNK0f); 107 dest = soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry, 108 DEST0f); 109 110 mirror_entry = soc_mem_table_idx_to_pointer(unit, MODPORT_MAP_MIRRORm, 111 modport_map_mirror_entry_t *, mirror_buf, i); 112 soc_MODPORT_MAP_MIRRORm_field32_set(unit, mirror_entry, 113 ENABLEf, enable); 114 soc_MODPORT_MAP_MIRRORm_field32_set(unit, mirror_entry, 115 ISTRUNKf, istrunk); 116 soc_MODPORT_MAP_MIRRORm_field32_set(unit, mirror_entry, 117 DESTf, dest); 118 } 119 rv = soc_mem_write_range(unit, MODPORT_MAP_MIRRORm, MEM_BLOCK_ALL, 120 index_min, index_max, mirror_buf); 121 soc_cm_sfree(unit, mirror_buf); 122 123 124 #ifdef BCM_TRIDENT2PLUS_SUPPORT 125 if (SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT3X(unit)) { 126 modport_map_subport_mirror_entry_t subport_m_entry; 127 int port; 128 129 sal_memset(&subport_m_entry, 0, sizeof(subport_m_entry)); 130 soc_mem_field32_set(unit, MODPORT_MAP_SUBPORT_M0m, &subport_m_entry, ENABLEf, 1); 131 132 /* my_modid and other modid related initialization */ 133 PBMP_ALL_ITER(unit, port) { 134 /* configure logical subport mirror numbers */ 135 soc_mem_field32_set(unit, MODPORT_MAP_SUBPORT_M0m, &subport_m_entry, DESTf, port); 136 SOC_IF_ERROR_RETURN 137 (WRITE_MODPORT_MAP_SUBPORT_M0m(unit, MEM_BLOCK_ALL, port, &subport_m_entry)); 138 SOC_IF_ERROR_RETURN 139 (WRITE_MODPORT_MAP_SUBPORT_M1m(unit, MEM_BLOCK_ALL, port, &subport_m_entry)); 140 SOC_IF_ERROR_RETURN 141 (WRITE_MODPORT_MAP_SUBPORT_M2m(unit, MEM_BLOCK_ALL, port, &subport_m_entry)); 142 SOC_IF_ERROR_RETURN 143 (WRITE_MODPORT_MAP_SUBPORT_M3m(unit, MEM_BLOCK_ALL, port, &subport_m_entry)); 144 145 } 146 } 147 #endif 148 return rv; 149 } 150 151 /* 152 * Function: 153 * _bcm_td_modport_map_profile_hw_write 154 * Purpose: 155 * Write modport map profile to hardware. 156 * Parameters: 157 * unit - SOC unit #. 158 * profile_index - Profile number. 159 * profile - Modport map profile. 160 * Returns: 161 * BCM_E_XXX 162 */ 163 STATIC int 164 _bcm_td_modport_map_profile_hw_write(int unit, int profile_index, 165 _bcm_td_modport_map_profile_t *profile) 166 { 167 int rv = BCM_E_NONE; 168 int profile_buf_size; 169 uint8 *profile_buf = NULL; 170 int i, j; 171 modport_map_sw_entry_t *modport_map_entry; 172 _bcm_td_modport_map_entry_t profile_entry; 173 soc_field_t enable_field[2] = {ENABLE0f, ENABLE1f}; 174 soc_field_t istrunk_field[2] = {ISTRUNK0f, ISTRUNK1f}; 175 soc_field_t dest_field[2] = {DEST0f, DEST1f}; 176 bcm_gport_t gport; 177 bcm_trunk_t tid; 178 bcm_trunk_chip_info_t chip_info; 179 int hg_trunk_group; 180 int index_min, index_max; 181 int dest[2] = {0}; 182 #if defined(BCM_SABER2_SUPPORT) 183 int mask1 = 0, bitlen1 = 0 , mask2 = 0, bitlen2= 0; 184 #endif 185 profile_buf_size = profile->num_entries * 186 soc_mem_entry_words(unit, MODPORT_MAP_SWm) * 4; 187 profile_buf = soc_cm_salloc(unit, profile_buf_size, "modport map buffer"); 188 if (NULL == profile_buf) { 189 return BCM_E_MEMORY; 190 } 191 sal_memset(profile_buf, 0, profile_buf_size); 192 193 for (i = 0; i < profile->num_entries; i++) { 194 modport_map_entry = soc_mem_table_idx_to_pointer(unit, MODPORT_MAP_SWm, 195 modport_map_sw_entry_t *, profile_buf, i); 196 profile_entry = profile->entry_array[i]; 197 198 if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, VOQ_COS_VALIDf)) { 199 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 200 VOQ_COS_VALIDf, profile_entry.voq_cos_valid); 201 } 202 if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, VOQ_GRP_IDf)) { 203 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 204 VOQ_GRP_IDf, profile_entry.voq_group_id); 205 } 206 207 for (j = 0; j < 2; j++) { 208 if (profile_entry.dest_enable[j] == 0) { 209 continue; 210 } 211 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 212 enable_field[j], profile_entry.dest_enable[j]); 213 214 if (profile_entry.dest_istrunk[j]) { 215 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 216 istrunk_field[j], 1); 217 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 218 dest_field[j], profile_entry.dest[j]); 219 } else { 220 #if defined(BCM_KATANA2_SUPPORT) 221 if (soc_feature(unit, soc_feature_linkphy_coe) || 222 soc_feature(unit, soc_feature_subtag_coe)) { 223 224 /* For SB2, DEST0 11:0 225 ISTRUNK0 = 0: 226 11:7: Egress Physical Port 227 6:0: Egress PP_PORT 228 ISTRUNK0 = 1: 229 2:0: Egress HiGig Trunk Group ID */ 230 #ifdef BCM_SABER2_SUPPORT 231 if (SOC_IS_SABER2(unit)) { 232 bitlen1 = soc_mem_field_length(unit, MODPORT_MAP_SWm, PHYSICAL_PORT1f); 233 mask1 = (1 << bitlen1) - 1; 234 bitlen2 = soc_mem_field_length(unit, MODPORT_MAP_SWm, PP_PORT1f); 235 mask2 = ( 1 << bitlen2) - 1; 236 dest[j] = ((profile_entry.dest[j] & mask1) << bitlen2) | 237 (profile_entry.dest[j] & mask2); 238 } else 239 #endif 240 if (SOC_IS_KATANA2(unit)){ 241 242 /* DEST0 13:0 243 ISTRUNK0 = 0: 244 13:8: Egress Physical Port 245 7:0: Egress PP_PORT 246 ISTRUNK0 = 1: 247 3:0: Egress HiGig Trunk Group ID */ 248 /* For KT2 physical port to pp_port is 1:1 mapped */ 249 dest[j] = ((profile_entry.dest[j] & 0x3f) << 8) | 250 (profile_entry.dest[j] & 0xff); 251 } else { 252 LOG_ERROR(BSL_LS_BCM_COMMON, 253 (BSL_META_U(unit, 254 "TODO: DEST0 to be programmed in required format\n"))); 255 dest[j] = profile_entry.dest[j]; 256 } 257 } else 258 #endif 259 { 260 dest[j] = profile_entry.dest[j]; 261 } 262 if (MODPORT_MAP_INFO(unit).auto_include_disable) { 263 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 264 istrunk_field[j], 0); 265 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 266 dest_field[j], dest[j]); 267 } else { 268 SOC_GPORT_LOCAL_SET(gport, profile_entry.dest[j]); 269 rv = bcm_esw_trunk_find(unit, 0, gport, &tid); 270 if (rv == BCM_E_NOT_FOUND) { 271 /* dest is not a member of a Higig trunk group */ 272 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 273 istrunk_field[j], 0); 274 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 275 dest_field[j], dest[j]); 276 } else if (BCM_FAILURE(rv)) { 277 goto cleanup; 278 } else { 279 /* dest is a member of a Higig trunk group */ 280 rv = bcm_esw_trunk_chip_info_get(unit, &chip_info); 281 if (BCM_FAILURE(rv)) { 282 goto cleanup; 283 } 284 if (tid < chip_info.trunk_fabric_id_min) { 285 rv = BCM_E_PARAM; 286 goto cleanup; 287 } 288 hg_trunk_group = tid - chip_info.trunk_fabric_id_min; 289 290 if (SHR_BITGET( 291 profile_entry.higig_trunk_override, 292 hg_trunk_group)) { 293 soc_MODPORT_MAP_SWm_field32_set(unit, 294 modport_map_entry, 295 istrunk_field[j], 0); 296 soc_MODPORT_MAP_SWm_field32_set(unit, 297 modport_map_entry, 298 dest_field[j], dest[j]); 299 } else { 300 soc_MODPORT_MAP_SWm_field32_set(unit, 301 modport_map_entry, 302 istrunk_field[j], 1); 303 soc_MODPORT_MAP_SWm_field32_set(unit, 304 modport_map_entry, 305 dest_field[j], hg_trunk_group); 306 } 307 } 308 } 309 } 310 } 311 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 312 /* Set the HW entries to 0 if the link status is down */ 313 if (soc_feature(unit, soc_feature_epc_linkflap_recover) && 314 profile_entry.dest_enable[0] == 1 && 315 profile_entry.dest_enable[1] == 1) { 316 int k; 317 for (k = 0; k < 2; k++) { 318 int link = -1; 319 bcm_esw_port_link_status_get(unit, profile_entry.dest[k], &link); 320 if (link == 0 && !profile_entry.dest_istrunk[k]) { 321 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 322 enable_field[k], 0); 323 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_entry, 324 dest_field[k], 0); 325 } 326 } 327 } 328 #endif /*defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT)*/ 329 } 330 331 index_min = profile_index * profile->num_entries; 332 index_max = index_min + profile->num_entries - 1; 333 rv = soc_mem_write_range(unit, MODPORT_MAP_SWm, MEM_BLOCK_ALL, 334 index_min, index_max, profile_buf); 335 if (BCM_FAILURE(rv)) { 336 goto cleanup; 337 } 338 rv = _bcm_td_modport_map_mirror_profile_hw_copy(unit, index_min, index_max, 339 profile_buf); 340 if (BCM_FAILURE(rv)) { 341 goto cleanup; 342 } 343 344 cleanup: 345 if (NULL != profile_buf) { 346 soc_cm_sfree(unit, profile_buf); 347 } 348 349 return rv; 350 } 351 352 /* 353 * Function: 354 * _bcm_td_modport_map_profile_add 355 * Purpose: 356 * Add a modport map profile. 357 * Parameters: 358 * unit - SOC unit #. 359 * profile - Modport map profile. 360 * profile_index - (OUT) Profile number. 361 * Returns: 362 * BCM_E_XXX 363 */ 364 STATIC int 365 _bcm_td_modport_map_profile_add(int unit, 366 _bcm_td_modport_map_profile_t *profile, 367 int *profile_index) 368 { 369 int i; 370 371 /* Check if the given profile matches any existing profile */ 372 373 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 374 if (MODPORT_MAP_PROFILE(unit, i).ref_count == 0) { 375 continue; 376 } 377 if (MODPORT_MAP_PROFILE(unit, i).num_entries != profile->num_entries) { 378 return BCM_E_INTERNAL; 379 } 380 if (0 == sal_memcmp(MODPORT_MAP_PROFILE(unit, i).entry_array, 381 profile->entry_array, 382 profile->num_entries * sizeof(_bcm_td_modport_map_entry_t))) { 383 MODPORT_MAP_PROFILE(unit, i).ref_count++; 384 *profile_index = i; 385 return BCM_E_NONE; 386 } 387 } 388 389 /* The given profile does not match any existing profile */ 390 391 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 392 if (MODPORT_MAP_PROFILE(unit, i).ref_count == 0) { 393 MODPORT_MAP_PROFILE(unit, i).num_entries = profile->num_entries; 394 sal_memcpy(MODPORT_MAP_PROFILE(unit, i).entry_array, 395 profile->entry_array, 396 profile->num_entries * sizeof(_bcm_td_modport_map_entry_t)); 397 MODPORT_MAP_PROFILE(unit, i).ref_count++; 398 *profile_index = i; 399 BCM_IF_ERROR_RETURN 400 (_bcm_td_modport_map_profile_hw_write(unit, i, profile)); 401 return BCM_E_NONE; 402 } 403 } 404 405 /* No available profile */ 406 return BCM_E_RESOURCE; 407 } 408 409 /* 410 * Function: 411 * _bcm_td_modport_map_profile_delete 412 * Purpose: 413 * Delete a modport map profile. 414 * Parameters: 415 * unit - SOC unit #. 416 * profile_index - Profile number. 417 * Returns: 418 * BCM_E_XXX 419 */ 420 STATIC int 421 _bcm_td_modport_map_profile_delete(int unit, int profile_index) 422 { 423 if (MODPORT_MAP_PROFILE(unit, profile_index).ref_count == 0) { 424 return BCM_E_INTERNAL; 425 } 426 427 MODPORT_MAP_PROFILE(unit, profile_index).ref_count--; 428 429 if (MODPORT_MAP_PROFILE(unit, profile_index).ref_count == 0) { 430 sal_memset(MODPORT_MAP_PROFILE(unit, profile_index).entry_array, 0, 431 sizeof(_bcm_td_modport_map_entry_t) * 432 MODPORT_MAP_PROFILE(unit, profile_index).num_entries); 433 BCM_IF_ERROR_RETURN(_bcm_td_modport_map_profile_hw_write(unit, 434 profile_index, 435 &MODPORT_MAP_PROFILE(unit, profile_index))); 436 } 437 438 return BCM_E_NONE; 439 } 440 441 /* 442 * Function: 443 * _bcm_td_modport_map_free_resources 444 * Purpose: 445 * Free resources of modport map profiles. 446 * Parameters: 447 * unit - SOC unit #. 448 * Returns: 449 * None 450 */ 451 STATIC void 452 _bcm_td_modport_map_free_resources(int unit) 453 { 454 int i; 455 456 if (MODPORT_MAP_INFO(unit).profile_array) { 457 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 458 if (MODPORT_MAP_PROFILE(unit, i).entry_array) { 459 sal_free(MODPORT_MAP_PROFILE(unit, i).entry_array); 460 MODPORT_MAP_PROFILE(unit, i).entry_array = NULL; 461 } 462 } 463 sal_free(MODPORT_MAP_INFO(unit).profile_array); 464 MODPORT_MAP_INFO(unit).profile_array = NULL; 465 } 466 } 467 468 /* 469 * Function: 470 * bcm_td_modport_map_init 471 * Purpose: 472 * Initialize modport map profiles. 473 * Parameters: 474 * unit - SOC unit #. 475 * Returns: 476 * BCM_E_xxx 477 */ 478 int 479 bcm_td_modport_map_init(int unit) 480 { 481 int rv = BCM_E_NONE; 482 int i; 483 _bcm_td_modport_map_profile_t profile; 484 int profile_index; 485 int port_count; 486 bcm_port_t port; 487 bcm_pbmp_t all_pbmp; 488 489 BCM_PBMP_CLEAR(all_pbmp); 490 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 491 #if defined(BCM_KATANA2_SUPPORT) 492 if (soc_feature(unit, soc_feature_linkphy_coe) || 493 soc_feature(unit, soc_feature_subtag_coe)) { 494 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 495 } 496 if (SOC_IS_KATANA2(unit)) { 497 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 498 } 499 #endif 500 501 sal_memset(&MODPORT_MAP_INFO(unit), 0, 502 sizeof(_bcm_td_modport_map_info_t)); 503 504 /* By default, all members of a Higig trunk group is automatically 505 * included if one of its members is specified as the steering 506 * destination for a remote module. 507 */ 508 MODPORT_MAP_INFO(unit).auto_include_disable = 0; 509 510 MODPORT_MAP_INFO(unit).num_profiles = 511 soc_mem_index_count(unit, MODPORT_MAP_SWm) / (SOC_MODID_MAX(unit) + 1); 512 513 if (NULL == MODPORT_MAP_INFO(unit).profile_array) { 514 MODPORT_MAP_INFO(unit).profile_array = 515 sal_alloc(sizeof(_bcm_td_modport_map_profile_t) * 516 MODPORT_MAP_INFO(unit).num_profiles, "modport map profiles"); 517 if (NULL == MODPORT_MAP_INFO(unit).profile_array) { 518 _bcm_td_modport_map_free_resources(unit); 519 return BCM_E_MEMORY; 520 } 521 } 522 sal_memset(MODPORT_MAP_INFO(unit).profile_array, 0, 523 sizeof(_bcm_td_modport_map_profile_t) * 524 MODPORT_MAP_INFO(unit).num_profiles); 525 526 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 527 MODPORT_MAP_PROFILE(unit, i).num_entries = SOC_MODID_MAX(unit) + 1; 528 if (NULL == MODPORT_MAP_PROFILE(unit, i).entry_array) { 529 MODPORT_MAP_PROFILE(unit, i).entry_array = 530 sal_alloc(sizeof(_bcm_td_modport_map_entry_t) * 531 MODPORT_MAP_PROFILE(unit, i).num_entries, "modport map entries"); 532 if (NULL == MODPORT_MAP_PROFILE(unit, i).entry_array) { 533 _bcm_td_modport_map_free_resources(unit); 534 return BCM_E_MEMORY; 535 } 536 } 537 sal_memset(MODPORT_MAP_PROFILE(unit, i).entry_array, 0, 538 sizeof(_bcm_td_modport_map_entry_t) * 539 MODPORT_MAP_PROFILE(unit, i).num_entries); 540 } 541 542 if (!SOC_WARM_BOOT(unit)) { 543 /* Create a profile of all zeroes and have all ports point to it */ 544 545 profile.num_entries = SOC_MODID_MAX(unit) + 1; 546 profile.entry_array = sal_alloc(sizeof(_bcm_td_modport_map_entry_t) * 547 profile.num_entries, "profile entry array"); 548 if (NULL == profile.entry_array) { 549 return BCM_E_MEMORY; 550 } 551 sal_memset(profile.entry_array, 0, sizeof(_bcm_td_modport_map_entry_t) * 552 profile.num_entries); 553 rv = _bcm_td_modport_map_profile_add(unit, &profile, &profile_index); 554 sal_free(profile.entry_array); 555 if (BCM_FAILURE(rv)) { 556 return rv; 557 } 558 559 port_count = 0; 560 PBMP_ITER(all_pbmp, port) { 561 BCM_IF_ERROR_RETURN(WRITE_MODPORT_MAP_SELr(unit, port, profile_index)); 562 port_count++; 563 } 564 MODPORT_MAP_PROFILE(unit, profile_index).ref_count = port_count; 565 } 566 567 return rv; 568 } 569 570 /* 571 * Function: 572 * bcm_td_modport_map_detach 573 * Purpose: 574 * Detach modport map profiles. 575 * Parameters: 576 * unit - SOC unit #. 577 * Returns: 578 * BCM_E_xxx 579 */ 580 int 581 bcm_td_modport_map_detach(int unit) 582 { 583 _bcm_td_modport_map_free_resources(unit); 584 return BCM_E_NONE; 585 } 586 587 int 588 bcm_td_modport_map_hw_write_entry(int unit, int index, 589 int select_index, bcm_port_t dest_port, int set) 590 { 591 int rv = BCM_E_NONE; 592 uint8 *profile_buf = NULL; 593 int profile_buf_size; 594 modport_map_sw_entry_t *modport_map_sw_entry; 595 int enable[2]; 596 int dest[2]; 597 soc_field_t enable_field[2] = {ENABLE0f, ENABLE1f}; 598 soc_field_t dest_field[2] = {DEST0f, DEST1f}; 599 int i, num_dest_supported; 600 601 num_dest_supported = 2; 602 sal_memset(enable, 0, sizeof(int) * 2); 603 sal_memset(dest, 0, sizeof(int) * 2); 604 605 /* 1 Entry x 1 Word x 4 (bytes) */ 606 profile_buf_size = 1 * 4 * soc_mem_entry_words(unit, MODPORT_MAP_SWm); 607 profile_buf = soc_cm_salloc(unit, profile_buf_size, 608 "modport map entry buffer"); 609 if (NULL == profile_buf) { 610 return BCM_E_MEMORY; 611 } 612 613 rv = soc_mem_read(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY, 614 index, profile_buf); 615 if (BCM_FAILURE(rv)) { 616 soc_cm_sfree(unit, profile_buf); 617 return BCM_E_RESOURCE; 618 } 619 modport_map_sw_entry = soc_mem_table_idx_to_pointer(unit, 620 MODPORT_MAP_SWm, modport_map_sw_entry_t *, profile_buf, 0); 621 622 for (i = 0; i < num_dest_supported; i++) { 623 if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, enable_field[i])) { 624 enable[i] = soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry, 625 enable_field[i]); 626 } 627 if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, dest_field[i])) { 628 dest[i] = soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry, 629 dest_field[i]); 630 } 631 } 632 if ((set == 1)) { 633 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_sw_entry, 634 enable_field[select_index], set); 635 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_sw_entry, 636 dest_field[select_index], dest_port); 637 } else if (enable[select_index] && (dest[select_index] == dest_port)) { 638 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_sw_entry, 639 enable_field[select_index], 0); 640 soc_MODPORT_MAP_SWm_field32_set(unit, modport_map_sw_entry, 641 dest_field[select_index], 0); 642 } else { 643 soc_cm_sfree(unit, profile_buf); 644 return BCM_E_INTERNAL; 645 } 646 rv = soc_mem_write(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY, 647 index, profile_buf); 648 if (BCM_FAILURE(rv)) { 649 soc_cm_sfree(unit, profile_buf); 650 return BCM_E_RESOURCE; 651 } 652 rv = _bcm_td_modport_map_mirror_profile_hw_copy(unit, index, index, 653 profile_buf); 654 if (BCM_FAILURE(rv)) { 655 soc_cm_sfree(unit, profile_buf); 656 return BCM_E_RESOURCE; 657 } 658 soc_cm_sfree(unit, profile_buf); 659 return BCM_E_NONE; 660 } 661 662 /* 663 * Function: 664 * _bcm_td_stk_is_port_hgtid_member 665 * Purpose: 666 * Helper function to find if the hgtid 667 * (got from MODPORT_MAP_SW.DEST for trunk case) 668 * has the port as its member. 669 * Also returns the corresponding trunk id if the port 670 * is member of HGTID. 671 * Parameters: 672 * unit - (IN) SOC unit # 673 * hgtid - (IN) Higig Trunk id (index of HG_TRUNK_BITMAP) 674 * port - (IN) Member port 675 * trunkid - (OUT) trunk id of the given port 676 * Returns: 677 * True - Port is a member of hgtid 678 * False - Port is not a member of hgtid 679 */ 680 STATIC int 681 _bcm_td_stk_is_port_hgtid_member(int unit, int hgtid, 682 bcm_port_t port, int *trunkid) 683 { 684 int tid, rv, mymodid; 685 bcm_trunk_chip_info_t chip_info; 686 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 687 if (chip_info.trunk_fabric_id_min == -1) { 688 return 0; 689 } 690 rv = bcm_esw_stk_my_modid_get(unit, &mymodid); 691 if (BCM_FAILURE(rv)) { 692 return 0; 693 } 694 rv = bcm_esw_trunk_find(unit, mymodid, port, &tid); 695 if (BCM_FAILURE(rv)) { 696 return 0; 697 } 698 tid -= chip_info.trunk_fabric_id_min; 699 if (hgtid == tid) { 700 *trunkid = tid + chip_info.trunk_fabric_id_min; 701 return 1; 702 } 703 return 0; 704 } 705 706 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 707 STATIC int 708 _bcm_td_sdk_is_port_set_in_epc_link_bmap(int unit, bcm_port_t port, 709 int *set) 710 { 711 epc_link_bmap_entry_t epc_link_bmap_entry; 712 soc_pbmp_t link_pbmp; 713 714 SOC_PBMP_CLEAR(link_pbmp); 715 716 BCM_IF_ERROR_RETURN(READ_EPC_LINK_BMAPm( 717 unit, MEM_BLOCK_ANY, 0, &epc_link_bmap_entry)); 718 soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, 719 &epc_link_bmap_entry, PORT_BITMAPf,&link_pbmp); 720 if (SOC_PBMP_MEMBER(link_pbmp, port)) { 721 /* port is there in EPC_LINK_BMAP */ 722 *set = 1; 723 } else { 724 *set = 0; 725 } 726 return BCM_E_NONE; 727 } 728 /* 729 * Function: 730 * _bcm_td_stk_modport_map_is_member_link_handler 731 * Purpose: 732 * Called from bcm_esw_trunk_set and bcm_esw_trunk_member_add 733 * to check if this member shall be added. 734 * Parameters: 735 * unit - (IN) SOC unit # 736 * gport - (IN) gport for member port 737 * trunk_id - (IN) trunk identifier 738 * test_only - (IN) if set to 1 no need to update cache. 739 * status - (OUT)set to 1 if port needs to be added to trunk. 740 * else set to 0. 741 * Returns: 742 * BCM_E_XXXX 743 */ 744 int 745 _bcm_td_stk_modport_map_member_link_handler(int unit, 746 bcm_gport_t gport, 747 bcm_trunk_t trunk_id, 748 int test_only, 749 int *status) 750 { 751 int i, j, k; 752 int enable[2]; 753 int dest[2]; 754 int istrunk[2]; 755 int num_dest_supported; 756 int set = 1; 757 int rv = BCM_E_NONE; 758 bcm_port_t port; 759 _bcm_td_modport_map_profile_t *profile; 760 761 if (!status) { 762 return BCM_E_PARAM; 763 } 764 765 num_dest_supported = 2; 766 rv = bcm_esw_port_local_get(unit, gport, &port); 767 if (rv != BCM_E_NONE) { 768 *status = 1; 769 return BCM_E_NONE; 770 } 771 772 /* if port is not local hg port return */ 773 if (!IS_ST_PORT(unit, port)) { 774 *status = 1; 775 return BCM_E_NONE; 776 } 777 778 rv = _bcm_td_sdk_is_port_set_in_epc_link_bmap(unit, port, &set); 779 if (rv != BCM_E_NONE) { 780 *status = 1; 781 return BCM_E_NONE; 782 } 783 if (set) { 784 *status = 1; 785 return BCM_E_NONE; 786 } 787 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 788 if (MODPORT_MAP_PROFILE(unit, i).ref_count != 0) { 789 profile = &MODPORT_MAP_PROFILE(unit, i); 790 for (j = 0; j < profile->num_entries; j++) { 791 for (k = 0; k < num_dest_supported; k++) { 792 enable[k] = profile->entry_array[j].dest_enable[k]; 793 dest[k] = profile->entry_array[j].dest[k]; 794 istrunk[k] = profile->entry_array[j].dest_istrunk[k]; 795 } 796 for (k = 0; k < num_dest_supported; k++) { 797 int port_is_cached = 0; 798 bcm_trunk_t dummy_tid; 799 if (enable[k] && istrunk[k] && 800 enable[(k+1)%num_dest_supported]) { 801 if (_bcm_td_stk_is_port_hgtid_member( 802 unit, dest[k], port, &dummy_tid)) { 803 int mymodid; 804 rv = bcm_esw_stk_my_modid_get(unit, &mymodid); 805 if (BCM_FAILURE(rv)) { 806 return rv; 807 } 808 } 809 if ((trunk_id == -1) && 810 (_BCM_PORT_TRUNK_LINKFLAP_GET(unit, port) != 811 BCM_TRUNK_INVALID)) { 812 port_is_cached = 1; 813 trunk_id = 814 _BCM_PORT_TRUNK_LINKFLAP_GET(unit, port); 815 } 816 if (trunk_id != -1) { 817 if (!port_is_cached) { 818 if (!test_only) { 819 _BCM_PORT_TRUNK_LINKFLAP_SET( 820 unit, port, trunk_id); 821 } 822 *status = 0; 823 } else { 824 *status = 1; 825 } 826 } 827 } 828 } 829 } 830 } 831 } 832 return BCM_E_NONE; 833 } 834 835 /* 836 * Function: 837 * _bcm_td_stk_modport_map_linkscan_handler 838 * Purpose: 839 * Called from linkscan handler when port toggles. 840 * Enables and Disables the port in MODPORT_MAP_SW. 841 * Parameters: 842 * unit - (IN) SOC unit # 843 * info - (IN) port info 844 * Returns: 845 * None 846 */ 847 int 848 _bcm_td_stk_modport_map_linkscan_handler(int unit, 849 bcm_port_t port, bcm_port_info_t *info) 850 { 851 int i, j, k; 852 int enable[2]; 853 int dest[2]; 854 int istrunk[2]; 855 int num_dest_supported; 856 _bcm_td_modport_map_profile_t *profile; 857 int index, set; 858 int rv = BCM_E_NONE; 859 860 if (!info) { 861 return BCM_E_PARAM; 862 } 863 864 num_dest_supported = 2; 865 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 866 if (MODPORT_MAP_PROFILE(unit, i).ref_count != 0) { 867 profile = &MODPORT_MAP_PROFILE(unit, i); 868 for (j = 0; j < profile->num_entries; j++) { 869 for (k = 0; k < num_dest_supported; k++) { 870 enable[k] = profile->entry_array[j].dest_enable[k]; 871 dest[k] = profile->entry_array[j].dest[k]; 872 istrunk[k] = profile->entry_array[j].dest_istrunk[k]; 873 } 874 /* For cases where the profile points to a trunk 875 * and the port in question is a member of the trunk, 876 * the port is removed from the trunk group when it is shut. 877 * This state is saved so that upon port enable, the port is added 878 * back to the trunk group. 879 */ 880 for (k = 0; k < num_dest_supported; k++) { 881 int port_is_cached = 0; 882 bcm_trunk_t trunk_id = -1; 883 /* Remove the port from trunk, only if both DEST are enabled */ 884 if (enable[k] && istrunk[k] && enable[(k+1)%num_dest_supported]) { 885 if (_bcm_td_stk_is_port_hgtid_member(unit, dest[k], port, &trunk_id)) { 886 int mymodid; 887 rv = bcm_esw_stk_my_modid_get(unit, &mymodid); 888 if (BCM_FAILURE(rv)) { 889 return rv; 890 } 891 } 892 if ((trunk_id == -1) && 893 (_BCM_PORT_TRUNK_LINKFLAP_GET(unit, port) != BCM_TRUNK_INVALID)) { 894 port_is_cached = 1; 895 trunk_id = _BCM_PORT_TRUNK_LINKFLAP_GET(unit, port); 896 } 897 if (trunk_id != -1) { 898 bcm_trunk_member_t p_trunk_member; 899 bcm_trunk_member_t_init(&p_trunk_member); 900 BCM_GPORT_LOCAL_SET(p_trunk_member.gport, port); 901 if ((!port_is_cached) && 902 (info->linkstatus == BCM_PORT_LINK_STATUS_DOWN)) { 903 rv = bcm_esw_trunk_member_delete(unit, trunk_id, &p_trunk_member); 904 if (BCM_FAILURE(rv)) { 905 return rv; 906 } 907 _BCM_PORT_TRUNK_LINKFLAP_SET(unit, port, trunk_id); 908 } else if ((port_is_cached) && 909 (info->linkstatus == BCM_PORT_LINK_STATUS_UP)) { 910 /* Check if EPC_PORT_BMAP is updated */ 911 BCM_IF_ERROR_RETURN(_bcm_td_sdk_is_port_set_in_epc_link_bmap( 912 unit, port, &set)); 913 if (set) { 914 rv = bcm_esw_trunk_member_add(unit, trunk_id, &p_trunk_member); 915 if (BCM_FAILURE(rv)) { 916 return rv; 917 } 918 _BCM_PORT_TRUNK_LINKFLAP_CLEAR(unit, port); 919 } 920 921 } 922 continue; 923 } 924 } 925 } 926 /* Max Number of destination for a modid is currently 2 */ 927 if (!istrunk[0] && !istrunk[1] && enable[0] && enable[1]) { 928 int select; 929 if (dest[0] == port) { 930 select = 0; 931 } else if (dest[1] == port) { 932 select = 1; 933 } else { 934 continue; 935 } 936 index = (i * profile->num_entries) + j; 937 if (info->linkstatus == BCM_PORT_LINK_STATUS_DOWN) { 938 rv = bcm_td_modport_map_hw_write_entry(unit, index, 939 select, port, 0); 940 } else if (info->linkstatus == BCM_PORT_LINK_STATUS_UP) { 941 rv = bcm_td_modport_map_hw_write_entry(unit, index, 942 select, port, 1); 943 } 944 if (BCM_FAILURE(rv)){ 945 return rv; 946 } 947 } 948 } 949 } 950 } 951 return BCM_E_NONE; 952 } 953 #endif 954 955 /* 956 * Function: 957 * bcm_td_stk_port_modport_op 958 * Purpose: 959 * Set, add, or delete modport mappings. 960 * Parameters: 961 * unit - SOC unit #. 962 * op - Set, add, or delete. 963 * ing_port - Ingress port. 964 * dest_modid - Destination module ID. 965 * dest_port - Array of destination Higig ports. 966 * dest_port_count - Size of dest_port array. 967 * Returns: 968 * BCM_E_xxx 969 */ 970 int 971 bcm_td_stk_port_modport_op(int unit, int op, bcm_port_t ing_port, 972 bcm_module_t dest_modid, bcm_port_t *dest_port, 973 int dest_port_count) 974 { 975 int rv = BCM_E_NONE; 976 int num_dest_supported; 977 int modid_count, modid_min, modid_max; 978 int hgtid[SOC_MAX_NUM_PORTS]; 979 int i, k, j; 980 bcm_trunk_t tid; 981 bcm_trunk_chip_info_t chip_info; 982 uint32 rval; 983 int profile_index, new_profile_index; 984 _bcm_td_modport_map_profile_t profile; 985 int entry_array_size; 986 int enable[2]; 987 int istrunk[2]; 988 int dest[2]; 989 int match; 990 991 #ifdef BCM_TOMAHAWK3_SUPPORT 992 if (SOC_IS_TOMAHAWK3(unit)) { 993 return BCM_E_UNAVAIL; 994 } 995 #endif 996 997 if (op <= 0 || op >= _BCM_STK_PORT_MODPORT_OP_COUNT) { 998 return BCM_E_PARAM; 999 } 1000 1001 if (BCM_GPORT_IS_SET(ing_port)) { 1002 BCM_IF_ERROR_RETURN( 1003 bcm_esw_port_local_get(unit, ing_port, &ing_port)); 1004 } 1005 if (!SOC_PORT_VALID(unit, ing_port)) { 1006 return BCM_E_PORT; 1007 } 1008 1009 modid_count = SOC_MODID_MAX(unit) + 1; 1010 if (dest_modid == -1) { 1011 modid_min = 0; 1012 modid_max = modid_count - 1; 1013 } else { 1014 if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) { 1015 return BCM_E_PARAM; 1016 } 1017 modid_min = modid_max = dest_modid; 1018 } 1019 1020 num_dest_supported = 2; 1021 if (dest_port_count > num_dest_supported) { 1022 return BCM_E_RESOURCE; 1023 } 1024 1025 sal_memset(hgtid, 0, sizeof(hgtid)); 1026 for (i = 0; i < dest_port_count; i++) { 1027 if (BCM_GPORT_IS_TRUNK(dest_port[i])) { 1028 tid = SOC_GPORT_TRUNK_GET(dest_port[i]); 1029 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 1030 if (chip_info.trunk_fabric_id_min >= 0 && 1031 tid >= chip_info.trunk_fabric_id_min) { /* fabric trunk */ 1032 hgtid[i] = tid - chip_info.trunk_fabric_id_min; 1033 } else { 1034 return BCM_E_PARAM; 1035 } 1036 } else { 1037 if (!SOC_PORT_VALID(unit, dest_port[i])) { 1038 return BCM_E_PORT; 1039 } 1040 } 1041 } 1042 1043 soc_mem_lock(unit, MODPORT_MAP_SWm); 1044 1045 /* Get ingress port's current profile index */ 1046 rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval); 1047 if (BCM_FAILURE(rv)) { 1048 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1049 return rv; 1050 } 1051 profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 1052 MODPORT_MAP_INDEX_UPPERf); 1053 1054 /* Get current profile */ 1055 profile.num_entries = MODPORT_MAP_PROFILE(unit, profile_index).num_entries; 1056 entry_array_size = profile.num_entries * sizeof(_bcm_td_modport_map_entry_t); 1057 profile.entry_array = sal_alloc(entry_array_size, "modport map profile entry array"); 1058 if (NULL == profile.entry_array) { 1059 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1060 return BCM_E_MEMORY; 1061 } 1062 sal_memcpy(profile.entry_array, 1063 MODPORT_MAP_PROFILE(unit, profile_index).entry_array, 1064 entry_array_size); 1065 1066 /* Modify profile */ 1067 for (i = modid_min; i <= modid_max; i++) { 1068 for (k = 0; k < num_dest_supported; k++) { 1069 enable[k] = profile.entry_array[i].dest_enable[k]; 1070 istrunk[k] = profile.entry_array[i].dest_istrunk[k]; 1071 dest[k] = profile.entry_array[i].dest[k]; 1072 } 1073 1074 switch (op) { 1075 case _BCM_STK_PORT_MODPORT_OP_SET: 1076 for (k = 0; k < dest_port_count; k++) { 1077 enable[k] = 1; 1078 if (BCM_GPORT_IS_TRUNK(dest_port[k])) { 1079 istrunk[k] = 1; 1080 dest[k] = hgtid[k]; 1081 } else { 1082 istrunk[k] = 0; 1083 dest[k] = dest_port[k]; 1084 } 1085 } 1086 for (k = dest_port_count; k < num_dest_supported; k++) { 1087 enable[k] = 0; 1088 istrunk[k] = 0; 1089 dest[k] = 0; 1090 } 1091 break; 1092 1093 case _BCM_STK_PORT_MODPORT_OP_ADD: 1094 for (k = 0; k < dest_port_count; k++) { 1095 /* Find the first free destination */ 1096 for (j = 0; j < num_dest_supported; j++) { 1097 if (enable[j] == 0) { 1098 break; 1099 } 1100 } 1101 if (j == num_dest_supported) { 1102 /* A free destination cannot be found */ 1103 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1104 sal_free(profile.entry_array); 1105 return BCM_E_RESOURCE; 1106 } 1107 enable[j] = 1; 1108 if (BCM_GPORT_IS_TRUNK(dest_port[k])) { 1109 istrunk[j] = 1; 1110 dest[j] = hgtid[k]; 1111 } else { 1112 istrunk[j] = 0; 1113 dest[j] = dest_port[k]; 1114 } 1115 } 1116 break; 1117 1118 case _BCM_STK_PORT_MODPORT_OP_DELETE: 1119 for (k = 0; k < dest_port_count; k++) { 1120 /* Find the matching destination */ 1121 match = 0; 1122 for (j = 0; j < num_dest_supported; j++) { 1123 if (enable[j] == 1) { 1124 if (BCM_GPORT_IS_TRUNK(dest_port[k])) { 1125 if (istrunk[j] == 1 && 1126 dest[j] == hgtid[k]) { 1127 match = 1; 1128 } 1129 } else { 1130 if (istrunk[j] == 0 && 1131 dest[j] == dest_port[k]) { 1132 match = 1; 1133 } 1134 } 1135 if (match) { 1136 enable[j] = 0; 1137 istrunk[j] = 0; 1138 dest[j] = 0; 1139 break; 1140 } 1141 } 1142 } 1143 if (!match) { 1144 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1145 sal_free(profile.entry_array); 1146 return BCM_E_NOT_FOUND; 1147 } 1148 } 1149 break; 1150 1151 default: 1152 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1153 sal_free(profile.entry_array); 1154 return BCM_E_INTERNAL; 1155 } 1156 1157 for (k = 0; k < num_dest_supported; k++) { 1158 profile.entry_array[i].dest_enable[k] = enable[k]; 1159 profile.entry_array[i].dest_istrunk[k] = istrunk[k]; 1160 profile.entry_array[i].dest[k] = dest[k]; 1161 } 1162 } 1163 1164 /* Add modified profile */ 1165 rv = _bcm_td_modport_map_profile_add(unit, &profile, &new_profile_index); 1166 if (BCM_FAILURE(rv)) { 1167 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1168 sal_free(profile.entry_array); 1169 return rv; 1170 } 1171 1172 /* Update ingress port's profile index */ 1173 soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval, 1174 MODPORT_MAP_INDEX_UPPERf, new_profile_index); 1175 rv = WRITE_MODPORT_MAP_SELr(unit, ing_port, rval); 1176 if (BCM_FAILURE(rv)) { 1177 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1178 sal_free(profile.entry_array); 1179 return rv; 1180 } 1181 1182 /* Remove old profile */ 1183 rv = _bcm_td_modport_map_profile_delete(unit, profile_index); 1184 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1185 sal_free(profile.entry_array); 1186 return rv; 1187 } 1188 1189 /* 1190 * Function: 1191 * bcm_td_stk_port_modport_get 1192 * Purpose: 1193 * Get modport mappings. 1194 * Parameters: 1195 * unit - SOC unit #. 1196 * ing_port - Ingress port. 1197 * dest_modid - Destination module ID. 1198 * dest_port_max - Size of dest_port_array. 1199 * dest_port_array - (OUT) Array of destination Higig ports. 1200 * dest_port_count - (OUT) Number of ports returned in dest_port array. 1201 * Returns: 1202 * BCM_E_xxx 1203 */ 1204 int 1205 bcm_td_stk_port_modport_get(int unit, bcm_port_t ing_port, 1206 bcm_module_t dest_modid, int dest_port_max, 1207 bcm_port_t *dest_port_array, 1208 int *dest_port_count) 1209 { 1210 uint32 rval; 1211 int profile_index; 1212 _bcm_td_modport_map_profile_t profile; 1213 int count; 1214 int num_dest_supported; 1215 int i; 1216 int enable, istrunk, dest; 1217 bcm_trunk_chip_info_t chip_info; 1218 bcm_trunk_t tid; 1219 1220 if (BCM_GPORT_IS_SET(ing_port)) { 1221 BCM_IF_ERROR_RETURN( 1222 bcm_esw_port_local_get(unit, ing_port, &ing_port)); 1223 } 1224 if (!SOC_PORT_VALID(unit, ing_port)) { 1225 return BCM_E_PORT; 1226 } 1227 1228 if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) { 1229 return BCM_E_PARAM; 1230 } 1231 1232 if (dest_port_max < 0 || dest_port_array == NULL || 1233 dest_port_count == NULL) { 1234 return BCM_E_PARAM; 1235 } 1236 1237 BCM_IF_ERROR_RETURN(READ_MODPORT_MAP_SELr(unit, ing_port, &rval)); 1238 profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 1239 MODPORT_MAP_INDEX_UPPERf); 1240 profile = MODPORT_MAP_PROFILE(unit, profile_index); 1241 1242 count= 0; 1243 num_dest_supported = 2; 1244 for (i = 0; i < num_dest_supported; i++) { 1245 enable = profile.entry_array[dest_modid].dest_enable[i]; 1246 istrunk = profile.entry_array[dest_modid].dest_istrunk[i]; 1247 dest = profile.entry_array[dest_modid].dest[i]; 1248 1249 if (enable) { 1250 if (dest_port_max > count) { 1251 if (istrunk) { 1252 BCM_IF_ERROR_RETURN 1253 (bcm_esw_trunk_chip_info_get(unit, &chip_info)); 1254 tid = dest + chip_info.trunk_fabric_id_min; 1255 BCM_GPORT_TRUNK_SET(dest_port_array[count], tid); 1256 } else { 1257 dest_port_array[count] = dest; 1258 } 1259 } 1260 if ((dest_port_max != 0) && 1261 (dest_port_max == count)) { 1262 break; 1263 } 1264 count++; 1265 } 1266 } 1267 *dest_port_count = count; 1268 1269 return *dest_port_count ? BCM_E_NONE : BCM_E_NOT_FOUND; 1270 } 1271 1272 /* 1273 * Function: 1274 * bcm_td_stk_modport_voq_op 1275 * Purpose: 1276 * Set/get VoQ info. 1277 * Parameters: 1278 * unit - SOC unit #. 1279 * ing_port - Ingress port. 1280 * dest_modid - Destination module ID. 1281 * grp_id - (IN/OUT) VoQ group ID. 1282 * op - Set/get. 1283 * Returns: 1284 * BCM_E_xxx 1285 */ 1286 int 1287 bcm_td_stk_modport_voq_op(int unit, bcm_port_t ing_port, 1288 bcm_module_t dest_modid, int *grp_id, int op) 1289 { 1290 int rv = BCM_E_NONE; 1291 int modid_count, modid_min, modid_max; 1292 uint32 rval; 1293 int profile_index, new_profile_index; 1294 _bcm_td_modport_map_profile_t profile; 1295 int entry_array_size; 1296 int voq_cos_valid, voq_group_id; 1297 int i; 1298 1299 if (BCM_GPORT_IS_SET(ing_port)) { 1300 BCM_IF_ERROR_RETURN( 1301 bcm_esw_port_local_get(unit, ing_port, &ing_port)); 1302 } 1303 if (!SOC_PORT_VALID(unit, ing_port)) { 1304 return BCM_E_PORT; 1305 } 1306 1307 modid_count = SOC_MODID_MAX(unit) + 1; 1308 if (dest_modid == -1 && op == _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_SET) { 1309 modid_min = 0; 1310 modid_max = modid_count - 1; 1311 } else { 1312 if (!SOC_MODID_ADDRESSABLE(unit, dest_modid)) { 1313 return BCM_E_PARAM; 1314 } 1315 modid_min = modid_max = dest_modid; 1316 } 1317 1318 if (op <= 0 || op >= _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_COUNT) { 1319 return BCM_E_PARAM; 1320 } 1321 1322 soc_mem_lock(unit, MODPORT_MAP_SWm); 1323 1324 /* Get ingress port's current profile index */ 1325 rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval); 1326 if (BCM_FAILURE(rv)) { 1327 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1328 return rv; 1329 } 1330 profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 1331 MODPORT_MAP_INDEX_UPPERf); 1332 1333 /* Get current profile */ 1334 profile.num_entries = MODPORT_MAP_PROFILE(unit, profile_index).num_entries; 1335 entry_array_size = profile.num_entries * sizeof(_bcm_td_modport_map_entry_t); 1336 profile.entry_array = sal_alloc(entry_array_size, "modport map profile entry array"); 1337 if (NULL == profile.entry_array) { 1338 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1339 return BCM_E_MEMORY; 1340 } 1341 sal_memcpy(profile.entry_array, 1342 MODPORT_MAP_PROFILE(unit, profile_index).entry_array, 1343 entry_array_size); 1344 1345 if (op == _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_SET) { 1346 voq_cos_valid = (*grp_id >= 0) ? 1: 0; 1347 voq_group_id = (*grp_id >= 0) ? *grp_id : 0; 1348 1349 /* Modify profile */ 1350 for (i = modid_min; i <= modid_max; i++) { 1351 profile.entry_array[i].voq_cos_valid = voq_cos_valid; 1352 profile.entry_array[i].voq_group_id = voq_group_id; 1353 } 1354 1355 /* Add modified profile */ 1356 rv = _bcm_td_modport_map_profile_add(unit, &profile, &new_profile_index); 1357 if (BCM_FAILURE(rv)) { 1358 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1359 sal_free(profile.entry_array); 1360 return rv; 1361 } 1362 1363 /* Update ingress port's profile index */ 1364 soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval, 1365 MODPORT_MAP_INDEX_UPPERf, new_profile_index); 1366 rv = WRITE_MODPORT_MAP_SELr(unit, ing_port, rval); 1367 if (BCM_FAILURE(rv)) { 1368 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1369 sal_free(profile.entry_array); 1370 return rv; 1371 } 1372 1373 /* Remove old profile */ 1374 rv = _bcm_td_modport_map_profile_delete(unit, profile_index); 1375 if (BCM_FAILURE(rv)) { 1376 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1377 sal_free(profile.entry_array); 1378 return rv; 1379 } 1380 } else if (op == _BCM_STK_PORT_MODPORT_DMVOQ_GRP_OP_GET) { 1381 voq_cos_valid = profile.entry_array[dest_modid].voq_cos_valid; 1382 voq_group_id = profile.entry_array[dest_modid].voq_group_id; 1383 *grp_id = (voq_cos_valid) ? voq_group_id: -1; 1384 } 1385 1386 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1387 sal_free(profile.entry_array); 1388 return rv; 1389 } 1390 1391 /* 1392 * Function: 1393 * bcm_td_stk_modport_map_update 1394 * Purpose: 1395 * Update modport map profiles due to changes in Higig trunk membership. 1396 * Parameters: 1397 * unit - SOC unit #. 1398 * Returns: 1399 * BCM_E_xxx 1400 */ 1401 int 1402 bcm_td_stk_modport_map_update(int unit) 1403 { 1404 int i; 1405 1406 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 1407 if (MODPORT_MAP_PROFILE(unit, i).ref_count == 0) { 1408 continue; 1409 } 1410 BCM_IF_ERROR_RETURN(_bcm_td_modport_map_profile_hw_write(unit, i, 1411 &MODPORT_MAP_PROFILE(unit, i))); 1412 } 1413 1414 return BCM_E_NONE; 1415 } 1416 1417 /* 1418 * Function: 1419 * bcm_td_stk_trunk_override_ucast_set 1420 * Purpose: 1421 * Set/clear HiGig Trunk Override in modport map profile. 1422 * Parameters: 1423 * unit - SOC unit 1424 * ing_port - Ingress Port 1425 * hgtid - Higig Trunk ID 1426 * modid - Module ID 1427 * enable - HighGig Trunk Override set/clear flag. 1428 * Returns: 1429 * BCM_E_XXX 1430 */ 1431 int 1432 bcm_td_stk_trunk_override_ucast_set(int unit, bcm_port_t ing_port, 1433 bcm_trunk_t hgtid, int modid, int enable) 1434 { 1435 int rv = BCM_E_NONE; 1436 uint32 rval; 1437 int profile_index, new_profile_index; 1438 _bcm_td_modport_map_profile_t profile; 1439 int entry_array_size; 1440 1441 if (BCM_GPORT_IS_SET(ing_port)) { 1442 BCM_IF_ERROR_RETURN( 1443 bcm_esw_port_local_get(unit, ing_port, &ing_port)); 1444 } 1445 if (!SOC_PORT_VALID(unit, ing_port)) { 1446 return BCM_E_PORT; 1447 } 1448 1449 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 1450 return BCM_E_PARAM; 1451 } 1452 1453 soc_mem_lock(unit, MODPORT_MAP_SWm); 1454 1455 /* Get ingress port's current profile index */ 1456 rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval); 1457 if (BCM_FAILURE(rv)) { 1458 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1459 return rv; 1460 } 1461 profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 1462 MODPORT_MAP_INDEX_UPPERf); 1463 1464 /* Get current profile */ 1465 profile.num_entries = MODPORT_MAP_PROFILE(unit, profile_index).num_entries; 1466 entry_array_size = profile.num_entries * sizeof(_bcm_td_modport_map_entry_t); 1467 profile.entry_array = sal_alloc(entry_array_size, "modport map profile entry array"); 1468 if (NULL == profile.entry_array) { 1469 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1470 return BCM_E_MEMORY; 1471 } 1472 sal_memcpy(profile.entry_array, 1473 MODPORT_MAP_PROFILE(unit, profile_index).entry_array, 1474 entry_array_size); 1475 1476 /* Modify profile */ 1477 if (enable) { 1478 SHR_BITSET(profile.entry_array[modid].higig_trunk_override, hgtid); 1479 } else { 1480 SHR_BITCLR(profile.entry_array[modid].higig_trunk_override, hgtid); 1481 } 1482 1483 /* Add modified profile */ 1484 rv = _bcm_td_modport_map_profile_add(unit, &profile, &new_profile_index); 1485 if (BCM_FAILURE(rv)) { 1486 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1487 sal_free(profile.entry_array); 1488 return rv; 1489 } 1490 1491 /* Update ingress port's profile index */ 1492 soc_reg_field_set(unit, MODPORT_MAP_SELr, &rval, 1493 MODPORT_MAP_INDEX_UPPERf, new_profile_index); 1494 rv = WRITE_MODPORT_MAP_SELr(unit, ing_port, rval); 1495 if (BCM_FAILURE(rv)) { 1496 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1497 sal_free(profile.entry_array); 1498 return rv; 1499 } 1500 1501 /* Remove old profile */ 1502 rv = _bcm_td_modport_map_profile_delete(unit, profile_index); 1503 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1504 sal_free(profile.entry_array); 1505 return rv; 1506 } 1507 1508 /* 1509 * Function: 1510 * bcm_td_stk_trunk_override_ucast_get 1511 * Purpose: 1512 * Get HiGig Trunk Override from modport map profile. 1513 * Parameters: 1514 * unit - SOC unit 1515 * ing_port - Ingress Port 1516 * hgtid - Trunk ID 1517 * modid - Module ID 1518 * enable - HighGig Trunk Override flag. 1519 * Returns: 1520 * BCM_E_XXX 1521 */ 1522 int 1523 bcm_td_stk_trunk_override_ucast_get(int unit, bcm_port_t ing_port, 1524 bcm_trunk_t hgtid, int modid, int *enable) 1525 { 1526 int rv = BCM_E_NONE; 1527 uint32 rval; 1528 int profile_index; 1529 _bcm_td_modport_map_profile_t profile; 1530 int entry_array_size; 1531 1532 if (BCM_GPORT_IS_SET(ing_port)) { 1533 BCM_IF_ERROR_RETURN( 1534 bcm_esw_port_local_get(unit, ing_port, &ing_port)); 1535 } 1536 if (!SOC_PORT_VALID(unit, ing_port)) { 1537 return BCM_E_PORT; 1538 } 1539 1540 if (!SOC_MODID_ADDRESSABLE(unit, modid)) { 1541 return BCM_E_PARAM; 1542 } 1543 1544 soc_mem_lock(unit, MODPORT_MAP_SWm); 1545 1546 /* Get ingress port's current profile index */ 1547 rv = READ_MODPORT_MAP_SELr(unit, ing_port, &rval); 1548 if (BCM_FAILURE(rv)) { 1549 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1550 return rv; 1551 } 1552 profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, rval, 1553 MODPORT_MAP_INDEX_UPPERf); 1554 1555 /* Get current profile */ 1556 profile.num_entries = MODPORT_MAP_PROFILE(unit, profile_index).num_entries; 1557 entry_array_size = profile.num_entries * sizeof(_bcm_td_modport_map_entry_t); 1558 profile.entry_array = sal_alloc(entry_array_size, "modport map profile entry array"); 1559 if (NULL == profile.entry_array) { 1560 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1561 return BCM_E_MEMORY; 1562 } 1563 sal_memcpy(profile.entry_array, 1564 MODPORT_MAP_PROFILE(unit, profile_index).entry_array, 1565 entry_array_size); 1566 1567 /* Modify profile */ 1568 *enable = SHR_BITGET(profile.entry_array[modid].higig_trunk_override, 1569 hgtid) ? 1 : 0; 1570 1571 soc_mem_unlock(unit, MODPORT_MAP_SWm); 1572 sal_free(profile.entry_array); 1573 return rv; 1574 } 1575 1576 /* 1577 * Function: 1578 * bcm_td_modport_map_mode_set 1579 * Purpose: 1580 * Set modport map mode. 1581 * Parameters: 1582 * unit - (IN) SOC unit number. 1583 * type - (IN) Configuration parameter type. 1584 * arg - (IN) Configuration paramter value. 1585 * Returns: 1586 * BCM_E_xxx 1587 */ 1588 int 1589 bcm_td_modport_map_mode_set(int unit, bcm_switch_control_t type, int arg) 1590 { 1591 switch (type) { 1592 case bcmSwitchFabricTrunkAutoIncludeDisable: 1593 MODPORT_MAP_INFO(unit).auto_include_disable = arg; 1594 break; 1595 1596 default: 1597 return BCM_E_PARAM; 1598 } 1599 1600 return BCM_E_NONE; 1601 } 1602 1603 /* 1604 * Function: 1605 * bcm_td_modport_map_mode_get 1606 * Purpose: 1607 * Get modport map mode. 1608 * Parameters: 1609 * unit - (IN) SOC unit number. 1610 * type - (IN) Configuration parameter type. 1611 * arg - (OUT) Configuration paramter value. 1612 * Returns: 1613 * BCM_E_xxx 1614 */ 1615 int 1616 bcm_td_modport_map_mode_get(int unit, bcm_switch_control_t type, int *arg) 1617 { 1618 switch (type) { 1619 case bcmSwitchFabricTrunkAutoIncludeDisable: 1620 *arg = MODPORT_MAP_INFO(unit).auto_include_disable; 1621 break; 1622 1623 default: 1624 return BCM_E_PARAM; 1625 } 1626 1627 return BCM_E_NONE; 1628 } 1629 1630 /* 1631 * Function: 1632 * bcm_td_stk_modport_map_port_attach 1633 * Purpose: 1634 * Initialize modport map profiles ptr on new port that added 1635 * during flexport operation. 1636 * Parameters: 1637 * unit - (IN) Unit number. 1638 * port - (IN) Logical port. 1639 * Returns: 1640 * SOC_E_XXX 1641 */ 1642 int 1643 bcm_td_stk_modport_map_port_attach(int unit, bcm_port_t port) 1644 { 1645 _bcm_td_modport_map_profile_t profile; 1646 int profile_index; 1647 int rv; 1648 1649 /* Get the profile_index of default profile */ 1650 profile.num_entries = SOC_MODID_MAX(unit) + 1; 1651 profile.entry_array = sal_alloc(sizeof(_bcm_td_modport_map_entry_t) * 1652 profile.num_entries, "profile entry array"); 1653 if (NULL == profile.entry_array) { 1654 return BCM_E_MEMORY; 1655 } 1656 sal_memset(profile.entry_array, 0, sizeof(_bcm_td_modport_map_entry_t) * 1657 profile.num_entries); 1658 rv = _bcm_td_modport_map_profile_add(unit, &profile, &profile_index); 1659 sal_free(profile.entry_array); 1660 if (BCM_FAILURE(rv)) { 1661 return rv; 1662 } 1663 1664 /* Set the profile ptr to the port */ 1665 BCM_IF_ERROR_RETURN(WRITE_MODPORT_MAP_SELr(unit, port, profile_index)); 1666 MODPORT_MAP_PROFILE(unit, profile_index).ref_count++; 1667 1668 return BCM_E_NONE; 1669 } 1670 1671 /* 1672 * Function: 1673 * bcm_td_stk_modport_map_port_detach 1674 * Purpose: 1675 * Detach port from modport map profiles. 1676 * Parameters: 1677 * unit - (IN) Unit number. 1678 * port - (IN) Logical port. 1679 * Returns: 1680 * SOC_E_XXX 1681 */ 1682 int 1683 bcm_td_stk_modport_map_port_detach(int unit, bcm_port_t port) 1684 { 1685 int profile_index; 1686 uint32 val; 1687 1688 SOC_IF_ERROR_RETURN(READ_MODPORT_MAP_SELr(unit, port, &val)); 1689 profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val, 1690 MODPORT_MAP_INDEX_UPPERf); 1691 1692 MODPORT_MAP_PROFILE(unit, profile_index).ref_count--; 1693 1694 /* Clear the profile ptr */ 1695 BCM_IF_ERROR_RETURN(WRITE_MODPORT_MAP_SELr(unit, port, 0)); 1696 1697 return BCM_E_NONE; 1698 } 1699 1700 #ifdef BCM_WARM_BOOT_SUPPORT 1701 /* 1702 * Function: 1703 * bcm_td_modport_map_scache_size_get 1704 * Purpose: 1705 * Get scache size needed to store modport map profile state. 1706 * Parameters: 1707 * unit - Device unit number 1708 * size - (OUT) Scache size needed. 1709 * Returns: 1710 * None 1711 */ 1712 int 1713 bcm_td_modport_map_scache_size_get(int unit, int *size) 1714 { 1715 1716 #if defined(BCM_KATANA2_SUPPORT) 1717 if (SOC_IS_KATANA2(unit)) { 1718 /* For each MODPORT_MAP_SWm entry, 8 bytes of internal 1719 * state need to be stored: 1720 * - First 2 bytes: bit 14 = dest_istrunk[0], bits 13-0 = dest[0]. 1721 * - Next 2 bytes: bit 14 = dest_istrunk[1], bits 13-0 = dest[1]. 1722 * - Next 4 bytes: 32-bit higig_trunk_override. 1723 */ 1724 *size = (2 * sizeof(uint16) + sizeof(SHR_BITDCL)) 1725 * soc_mem_index_count(unit, MODPORT_MAP_SWm); 1726 } else 1727 #endif /* BCM_KATANA2_SUPPORT */ 1728 { 1729 /* For each MODPORT_MAP_SWm entry, 6 bytes of internal 1730 * state need to be stored: 1731 * - First byte: bit 7 = dest_istrunk[0], bits 6-0 = dest[0]. 1732 * - Second byte: bit 7 = dest_istrunk[1], bits 6-0 = dest[1]. 1733 * - Next 4 bytes: 32-bit higig_trunk_override. 1734 */ 1735 *size = (2 * sizeof(uint8) + sizeof(SHR_BITDCL)) 1736 * soc_mem_index_count(unit, MODPORT_MAP_SWm); 1737 } 1738 return BCM_E_NONE; 1739 } 1740 1741 /* 1742 * Function: 1743 * bcm_td_modport_map_sync 1744 * Purpose: 1745 * Store modport map profile state to scache. 1746 * Parameters: 1747 * unit - Device unit number 1748 * scache_ptr - Scache pointer. 1749 * Returns: 1750 * None 1751 */ 1752 int 1753 bcm_td_modport_map_sync(int unit, uint8 **scache_ptr) 1754 { 1755 int i, j, k; 1756 _bcm_td_modport_map_profile_t profile; 1757 int istrunk, dest; 1758 SHR_BITDCL higig_trunk_override; 1759 uint8 dest_byte; 1760 #if defined(BCM_KATANA2_SUPPORT) 1761 uint16 kt2_dest_byte; 1762 int isenable; 1763 #endif 1764 1765 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 1766 profile = MODPORT_MAP_PROFILE(unit, i); 1767 for (j = 0; j < profile.num_entries; j++) { 1768 for (k = 0; k < 2; k++) { 1769 istrunk = profile.entry_array[j].dest_istrunk[k]; 1770 dest = profile.entry_array[j].dest[k]; 1771 #if defined(BCM_KATANA2_SUPPORT) 1772 if (SOC_IS_KATANA2(unit)) { 1773 /* DEST0 13:0 1774 * if ISTRUNK0 == 0 then 1775 * 13:8: Egress Physical Port; 7:0: Egress PP_PORT 1776 * else if ISTRUNK0 == 1 then 1777 * 3:0: Egress HiGig Trunk Group ID. 1778 * note: KT2 physical port to pp_port is 1:1 mapped. 1779 */ 1780 isenable = profile.entry_array[j].dest_enable[k]; 1781 kt2_dest_byte = ((isenable & 0x1) << 15) | 1782 ((istrunk & 0x1) << 14) | 1783 ((dest & 0x3f) << 8) | (dest & 0xff); 1784 sal_memcpy(*scache_ptr, &kt2_dest_byte, 1785 sizeof(kt2_dest_byte)); 1786 *scache_ptr += sizeof(kt2_dest_byte); 1787 } else 1788 #endif /* BCM_KATANA2_SUPPORT */ 1789 { 1790 dest_byte = ((istrunk & 0x1) << 7) | (dest & 0x7f); 1791 sal_memcpy(*scache_ptr, &dest_byte, sizeof(dest_byte)); 1792 *scache_ptr += sizeof(dest_byte); 1793 } 1794 } 1795 1796 higig_trunk_override = profile.entry_array[j].higig_trunk_override[0]; 1797 sal_memcpy(*scache_ptr, &higig_trunk_override, 1798 sizeof(higig_trunk_override)); 1799 *scache_ptr += sizeof(higig_trunk_override); 1800 } 1801 } 1802 1803 return BCM_E_NONE; 1804 } 1805 1806 /* 1807 * Function: 1808 * bcm_td_modport_map_reinit 1809 * Purpose: 1810 * Retrieve modport map profile state from hardware and scache. 1811 * Parameters: 1812 * unit - Device unit number 1813 * scache_ptr - Scache pointer. 1814 * Returns: 1815 * None 1816 */ 1817 int 1818 bcm_td_modport_map_reinit(int unit, uint8 **scache_ptr) 1819 { 1820 int rv = BCM_E_NONE; 1821 bcm_port_t ing_port; 1822 uint32 val; 1823 int profile_index; 1824 int i, j, k; 1825 _bcm_td_modport_map_profile_t profile; 1826 int profile_buf_size; 1827 uint8 *profile_buf = NULL; 1828 int index_min, index_max; 1829 modport_map_sw_entry_t *modport_map_sw_entry; 1830 soc_field_t enable_field[2] = {ENABLE0f, ENABLE1f}; 1831 soc_field_t istrunk_field[2] = {ISTRUNK0f, ISTRUNK1f}; 1832 soc_field_t dest_field[2] = {DEST0f, DEST1f}; 1833 #if defined(BCM_KATANA2_SUPPORT) 1834 uint16 kt2_dest_byte; 1835 #endif 1836 uint8 dest_byte; 1837 1838 bcm_gport_t gport; 1839 bcm_trunk_t tid; 1840 bcm_trunk_chip_info_t chip_info; 1841 int hg_tid; 1842 bcm_pbmp_t all_pbmp; 1843 1844 BCM_PBMP_CLEAR(all_pbmp); 1845 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 1846 #if defined(BCM_KATANA2_SUPPORT) 1847 if (soc_feature(unit, soc_feature_linkphy_coe) || 1848 soc_feature(unit, soc_feature_subtag_coe)) { 1849 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 1850 } 1851 if (SOC_IS_KATANA2(unit)) { 1852 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 1853 } 1854 #endif 1855 1856 1857 /* Recover each profile's reference count */ 1858 PBMP_ITER(all_pbmp, ing_port) { 1859 SOC_IF_ERROR_RETURN(READ_MODPORT_MAP_SELr(unit, ing_port, &val)); 1860 profile_index = soc_reg_field_get(unit, MODPORT_MAP_SELr, val, 1861 MODPORT_MAP_INDEX_UPPERf); 1862 MODPORT_MAP_PROFILE(unit, profile_index).ref_count++; 1863 } 1864 1865 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 1866 profile = MODPORT_MAP_PROFILE(unit, i); 1867 if (profile.ref_count == 0) { 1868 /* Skip the scache region containing the state of this profile */ 1869 if (*scache_ptr != NULL) { 1870 #if defined(BCM_KATANA2_SUPPORT) 1871 if (SOC_IS_KATANA2(unit)) { 1872 *scache_ptr += profile.num_entries * 1873 (2 * sizeof(kt2_dest_byte) + sizeof(SHR_BITDCL)); 1874 } else 1875 #endif 1876 { 1877 *scache_ptr += profile.num_entries * 1878 (2 * sizeof(dest_byte) + sizeof(SHR_BITDCL)); 1879 } 1880 } 1881 continue; 1882 } 1883 1884 /* Read profile from MODPOR_MAP_SWm */ 1885 1886 profile_buf_size = profile.num_entries * 1887 soc_mem_entry_words(unit, MODPORT_MAP_SWm) * 4; 1888 profile_buf = soc_cm_salloc(unit, profile_buf_size, 1889 "modport map buffer"); 1890 if (NULL == profile_buf) { 1891 return BCM_E_MEMORY; 1892 } 1893 1894 index_min = i * profile.num_entries; 1895 index_max = index_min + profile.num_entries - 1; 1896 rv = soc_mem_read_range(unit, MODPORT_MAP_SWm, MEM_BLOCK_ANY, 1897 index_min, index_max, profile_buf); 1898 if (SOC_FAILURE(rv)) { 1899 soc_cm_sfree(unit, profile_buf); 1900 return rv; 1901 } 1902 1903 /* Recover profile state */ 1904 1905 for (j = 0; j < profile.num_entries; j++) { 1906 modport_map_sw_entry = soc_mem_table_idx_to_pointer(unit, 1907 MODPORT_MAP_SWm, modport_map_sw_entry_t *, profile_buf, j); 1908 1909 for (k = 0; k < 2; k++) { 1910 profile.entry_array[j].dest_enable[k] = 1911 soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry, 1912 enable_field[k]); 1913 if (*scache_ptr != NULL) { 1914 #if defined(BCM_KATANA2_SUPPORT) 1915 if (SOC_IS_KATANA2(unit)) { 1916 sal_memcpy(&kt2_dest_byte, *scache_ptr, 1917 sizeof(kt2_dest_byte)); 1918 *scache_ptr += sizeof(kt2_dest_byte); 1919 1920 profile.entry_array[j].dest_istrunk[k] = 1921 (kt2_dest_byte >> 14) & 0x1; 1922 profile.entry_array[j].dest[k] = kt2_dest_byte & 0xff; 1923 } else 1924 #endif /* BCM_KATANA2_SUPPORT */ 1925 { 1926 sal_memcpy(&dest_byte, *scache_ptr, sizeof(dest_byte)); 1927 *scache_ptr += sizeof(dest_byte); 1928 profile.entry_array[j].dest_istrunk[k] = 1929 (dest_byte >> 7) & 0x1; 1930 profile.entry_array[j].dest[k] = dest_byte & 0x7f; 1931 } 1932 } else { 1933 profile.entry_array[j].dest_istrunk[k] = 1934 soc_MODPORT_MAP_SWm_field32_get(unit, 1935 modport_map_sw_entry, istrunk_field[k]); 1936 #if defined(BCM_KATANA2_SUPPORT) 1937 if (SOC_IS_KATANA2(unit)) { 1938 profile.entry_array[j].dest[k] = 1939 (soc_MODPORT_MAP_SWm_field32_get(unit, 1940 modport_map_sw_entry, dest_field[k])) & 0xff; 1941 } else 1942 #endif /* BCM_KATANA2_SUPPORT */ 1943 { 1944 profile.entry_array[j].dest[k] = 1945 soc_MODPORT_MAP_SWm_field32_get(unit, 1946 modport_map_sw_entry, dest_field[k]); 1947 } 1948 1949 /* Infer Higig trunk override info */ 1950 if (profile.entry_array[j].dest_enable[k] && 1951 !profile.entry_array[j].dest_istrunk[k]) { 1952 SOC_GPORT_LOCAL_SET(gport, profile.entry_array[j].dest[k]); 1953 rv = bcm_esw_trunk_find(unit, 0, gport, &tid); 1954 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1955 soc_cm_sfree(unit, profile_buf); 1956 return rv; 1957 } 1958 if (BCM_SUCCESS(rv)) { 1959 /* Port belongs to a Higig trunk group. */ 1960 rv = bcm_esw_trunk_chip_info_get(unit, &chip_info); 1961 if (BCM_FAILURE(rv)) { 1962 soc_cm_sfree(unit, profile_buf); 1963 return rv; 1964 } 1965 if (tid >= chip_info.trunk_fabric_id_min && 1966 tid <= chip_info.trunk_fabric_id_max) { 1967 hg_tid = tid - chip_info.trunk_fabric_id_min; 1968 SHR_BITSET( 1969 profile.entry_array[j].higig_trunk_override, 1970 hg_tid); 1971 } else { 1972 soc_cm_sfree(unit, profile_buf); 1973 return BCM_E_INTERNAL; 1974 } 1975 } 1976 } 1977 } 1978 } 1979 1980 if (*scache_ptr != NULL) { 1981 sal_memcpy(profile.entry_array[j].higig_trunk_override, 1982 *scache_ptr, sizeof(SHR_BITDCL)); 1983 *scache_ptr += sizeof(SHR_BITDCL); 1984 } 1985 1986 if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, VOQ_COS_VALIDf)) { 1987 profile.entry_array[j].voq_cos_valid = 1988 soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry, 1989 VOQ_COS_VALIDf); 1990 } 1991 if (soc_mem_field_valid(unit, MODPORT_MAP_SWm, VOQ_GRP_IDf)) { 1992 profile.entry_array[j].voq_group_id = 1993 soc_MODPORT_MAP_SWm_field32_get(unit, modport_map_sw_entry, 1994 VOQ_GRP_IDf); 1995 } 1996 } 1997 1998 soc_cm_sfree(unit, profile_buf); 1999 } 2000 2001 return BCM_E_NONE; 2002 } 2003 2004 /* 2005 * Function: 2006 * bcm_td_modport_map_enable_scache_size_get 2007 * Purpose: 2008 * Get scache size needed to store modport map profile enable field. 2009 * Parameters: 2010 * unit - Device unit number 2011 * size - (OUT) Scache size needed. 2012 * Returns: 2013 * None 2014 */ 2015 int 2016 bcm_td_modport_map_enable_scache_size_get(int unit, int *size) 2017 { 2018 2019 /* For each MODPORT_MAP_SWm entry, 1 bytes of internal 2020 * state need to be stored: 2021 * One byte - bit 1 = enable[1], bit 0 = enable[0]. 2022 */ 2023 *size = (1 * sizeof(uint8)) * 2024 soc_mem_index_count(unit, MODPORT_MAP_SWm); 2025 return BCM_E_NONE; 2026 } 2027 2028 /* 2029 * Function: 2030 * bcm_td_modport_map_enable_sync 2031 * Purpose: 2032 * Store modport map profile enable field to scache. 2033 * Parameters: 2034 * unit - Device unit number 2035 * scache_ptr - Scache pointer. 2036 * Returns: 2037 * None 2038 */ 2039 int 2040 bcm_td_modport_map_enable_sync(int unit, uint8 **scache_ptr) 2041 { 2042 int i, j; 2043 _bcm_td_modport_map_profile_t profile; 2044 uint8 enable_byte; 2045 2046 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 2047 profile = MODPORT_MAP_PROFILE(unit, i); 2048 for (j = 0; j < profile.num_entries; j++) { 2049 enable_byte = ((profile.entry_array[j].dest_enable[1] & 0x1) << 1) | 2050 (profile.entry_array[j].dest_enable[0] & 0x1); 2051 sal_memcpy(*scache_ptr, &enable_byte, sizeof(enable_byte)); 2052 *scache_ptr += sizeof(enable_byte); 2053 } 2054 } 2055 2056 return BCM_E_NONE; 2057 } 2058 2059 /* 2060 * Function: 2061 * bcm_td_modport_map_enable_reinit 2062 * Purpose: 2063 * Retrieve modport map enable field from hardware and scache. 2064 * Parameters: 2065 * unit - Device unit number 2066 * scache_ptr - Scache pointer. 2067 * Returns: 2068 * None 2069 */ 2070 int 2071 bcm_td_modport_map_enable_reinit(int unit, uint8 **scache_ptr) 2072 { 2073 int i, j; 2074 _bcm_td_modport_map_profile_t profile; 2075 uint8 enable_byte; 2076 2077 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 2078 profile = MODPORT_MAP_PROFILE(unit, i); 2079 for (j = 0; j < profile.num_entries; j++) { 2080 sal_memcpy(&enable_byte, *scache_ptr, sizeof(enable_byte)); 2081 *scache_ptr += sizeof(enable_byte); 2082 profile.entry_array[j].dest_enable[0] = (enable_byte & 0x1); 2083 profile.entry_array[j].dest_enable[1] = ((enable_byte >> 1) & 0x1); 2084 } 2085 } 2086 2087 return BCM_E_NONE; 2088 } 2089 2090 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HELIX4_SUPPORT) 2091 /* 2092 * Function: 2093 * bcm_td_linkflap_trunk_map_scache_size_get 2094 * Purpose: 2095 * Get scache size needed to store port to trunk mapping 2096 * Parameters: 2097 * unit - Device unit number 2098 * size - (OUT) Scache size needed. 2099 * Returns: 2100 * None 2101 */ 2102 int 2103 bcm_td_linkflap_trunk_map_scache_size_get(int unit, int *size) 2104 { 2105 *size = (sizeof(int)) * SOC_MAX_NUM_PORTS; 2106 return BCM_E_NONE; 2107 } 2108 2109 /* 2110 * Function: 2111 * bcm_td_linkflap_trunk_map_sync 2112 * Purpose: 2113 * Store linkflap port to trunk mapping. 2114 * Parameters: 2115 * unit - Device unit number 2116 * scache_ptr - Scache pointer. 2117 * Returns: 2118 * None 2119 */ 2120 int 2121 bcm_td_linkflap_trunk_map_sync(int unit, uint8 **scache_ptr) 2122 { 2123 bcm_port_t p; 2124 int trunk; 2125 PBMP_PORT_ITER(unit, p) { 2126 trunk = _BCM_PORT_TRUNK_LINKFLAP_GET(unit, p); 2127 sal_memcpy(*scache_ptr, &trunk, sizeof(int)); 2128 *scache_ptr += sizeof(int); 2129 } 2130 return BCM_E_NONE; 2131 } 2132 2133 /* 2134 * Function: 2135 * bcm_td_linkflap_trunk_map_reinit 2136 * Purpose: 2137 * Retrieve linkflap port to trunk mapping 2138 * Parameters: 2139 * unit - Device unit number 2140 * scache_ptr - Scache pointer. 2141 * Returns: 2142 * None 2143 */ 2144 int 2145 bcm_td_linkflap_trunk_map_reinit(int unit, uint8 **scache_ptr) 2146 { 2147 bcm_port_t p; 2148 int trunk; 2149 PBMP_PORT_ITER(unit, p) { 2150 sal_memcpy(&trunk, *scache_ptr, sizeof(int)); 2151 *scache_ptr += sizeof(int); 2152 _BCM_PORT_TRUNK_LINKFLAP_SET(unit, p, trunk); 2153 } 2154 return BCM_E_NONE; 2155 } 2156 #endif 2157 2158 /* 2159 * Function: 2160 * bcm_td_stk_trunk_override_hi_scache_size_get 2161 * Purpose: 2162 * Get scache size needed to store modport map profile state. 2163 * Parameters: 2164 * unit - Device unit number 2165 * size - (OUT) Scache size needed. 2166 * Returns: 2167 * None 2168 */ 2169 int 2170 bcm_td_stk_trunk_override_hi_scache_size_get(int unit, int *size) 2171 { 2172 uint32 higig_trunk_override_hi_size; 2173 2174 higig_trunk_override_hi_size = SHR_BITALLOCSIZE(_BCM_STK_HGT_GROUP_MAX) 2175 - sizeof(SHR_BITDCL); 2176 *size = higig_trunk_override_hi_size * 2177 soc_mem_index_count(unit, MODPORT_MAP_SWm); 2178 2179 return BCM_E_NONE; 2180 } 2181 2182 /* 2183 * Function: 2184 * bcm_td_stk_trunk_override_hi_sync 2185 * Purpose: 2186 * Store stk trunk override high bitmap to scache. 2187 * Parameters: 2188 * unit - Device unit number 2189 * scache_ptr - Scache pointer. 2190 * Returns: 2191 * None 2192 */ 2193 int 2194 bcm_td_stk_trunk_override_hi_sync(int unit, uint8 **scache_ptr) 2195 { 2196 int i, j; 2197 uint32 higig_trunk_override_hi_size; 2198 _bcm_td_modport_map_profile_t profile; 2199 SHR_BITDCL *higig_trunk_override_hi; 2200 2201 higig_trunk_override_hi_size = SHR_BITALLOCSIZE(_BCM_STK_HGT_GROUP_MAX) 2202 - sizeof(SHR_BITDCL); 2203 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 2204 profile = MODPORT_MAP_PROFILE(unit, i); 2205 for (j = 0; j < profile.num_entries; j++) { 2206 higig_trunk_override_hi = 2207 &profile.entry_array[j].higig_trunk_override[1]; 2208 sal_memcpy(*scache_ptr, 2209 higig_trunk_override_hi, higig_trunk_override_hi_size); 2210 *scache_ptr += higig_trunk_override_hi_size; 2211 } 2212 } 2213 2214 return BCM_E_NONE; 2215 } 2216 2217 /* 2218 * Function: 2219 * bcm_td_stk_trunk_override_hi_reinit 2220 * Purpose: 2221 * Retrieve stk trunk override high bitmap scache. 2222 * Parameters: 2223 * unit - Device unit number 2224 * scache_ptr - Scache pointer. 2225 * Returns: 2226 * None 2227 */ 2228 int 2229 bcm_td_stk_trunk_override_hi_reinit(int unit, uint8 **scache_ptr) 2230 { 2231 int i, j; 2232 uint32 higig_trunk_override_hi_size; 2233 _bcm_td_modport_map_profile_t profile; 2234 2235 higig_trunk_override_hi_size = SHR_BITALLOCSIZE(_BCM_STK_HGT_GROUP_MAX) 2236 - sizeof(SHR_BITDCL); 2237 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 2238 profile = MODPORT_MAP_PROFILE(unit, i); 2239 if (profile.ref_count == 0) { 2240 *scache_ptr += profile.num_entries * higig_trunk_override_hi_size; 2241 continue; 2242 } 2243 2244 for (j = 0; j < profile.num_entries; j++) { 2245 sal_memcpy(&profile.entry_array[j].higig_trunk_override[1], 2246 *scache_ptr, higig_trunk_override_hi_size); 2247 *scache_ptr += higig_trunk_override_hi_size; 2248 } 2249 } 2250 2251 return BCM_E_NONE; 2252 } 2253 2254 2255 #endif /* BCM_WARM_BOOT_SUPPORT */ 2256 2257 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 2258 /* 2259 * Function: 2260 * bcm_td_modport_map_sw_dump 2261 * Purpose: 2262 * Displays modport map software structure information. 2263 * Parameters: 2264 * unit - Device unit number 2265 * Returns: 2266 * None 2267 */ 2268 void 2269 bcm_td_modport_map_sw_dump(int unit) 2270 { 2271 int num_entries; 2272 int i, j, word; 2273 int entry_index; 2274 _bcm_td_modport_map_profile_t profile; 2275 int enable, istrunk, dest; 2276 2277 LOG_CLI((BSL_META_U(unit, 2278 " Stack Modport Higig Trunk Auto Include Disable = %d\n"), 2279 MODPORT_MAP_INFO(unit).auto_include_disable)); 2280 2281 LOG_CLI((BSL_META_U(unit, 2282 " Stack Modport Profile\n"))); 2283 2284 num_entries = 0; 2285 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 2286 num_entries += MODPORT_MAP_PROFILE(unit, i).num_entries; 2287 } 2288 LOG_CLI((BSL_META_U(unit, 2289 " Number of entries: %d\n"), num_entries)); 2290 2291 LOG_CLI((BSL_META_U(unit, 2292 " Index RefCount EntriesPerSet - HIGIG PORT or TRUNK\n"))); 2293 entry_index = 0; 2294 for (i = 0; i < MODPORT_MAP_INFO(unit).num_profiles; i++) { 2295 profile = MODPORT_MAP_PROFILE(unit, i); 2296 if (profile.ref_count == 0) { 2297 entry_index += profile.num_entries; 2298 continue; 2299 } 2300 2301 for (j = 0; j < profile.num_entries; j++) { 2302 LOG_CLI((BSL_META_U(unit, 2303 " %5d %8d %13d "), 2304 entry_index++, profile.ref_count, profile.num_entries)); 2305 2306 enable = profile.entry_array[j].dest_enable[0]; 2307 istrunk = profile.entry_array[j].dest_istrunk[0]; 2308 dest = profile.entry_array[j].dest[0]; 2309 LOG_CLI((BSL_META_U(unit, 2310 "enable0=%d, istrunk0=%d, dest0=%d, "), 2311 enable, istrunk, dest)); 2312 2313 enable = profile.entry_array[j].dest_enable[1]; 2314 istrunk = profile.entry_array[j].dest_istrunk[1]; 2315 dest = profile.entry_array[j].dest[1]; 2316 LOG_CLI((BSL_META_U(unit, 2317 "enable1=%d, istrunk1=%d, dest1=%d, "), 2318 enable, istrunk, dest)); 2319 2320 LOG_CLI((BSL_META_U(unit, 2321 "higig_trunk_override=0x"))); 2322 for (word = _SHR_BITDCLSIZE(_BCM_STK_HGT_GROUP_MAX) - 1; 2323 word >= 0; word--) { 2324 LOG_CLI((BSL_META_U(unit, 2325 "%08x%s"), 2326 profile.entry_array[j].higig_trunk_override[word], 2327 word ? "_" : "\n")); 2328 } 2329 } 2330 } 2331 } 2332 2333 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 2334 2335 #endif /* BCM_TRIDENT_SUPPORT */