failover.c (106184B)
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: failover.c 8 * Purpose: Handle trident2plus specific failover APIs 9 */ 10 11 12 #include <shared/bsl.h> 13 14 #include <soc/defs.h> 15 #include <sal/core/libc.h> 16 17 #if defined(BCM_TRIDENT2PLUS_SUPPORT) && defined(INCLUDE_L3) 18 19 #include <soc/drv.h> 20 #include <soc/mem.h> 21 #include <soc/util.h> 22 #include <soc/debug.h> 23 24 #include <bcm/types.h> 25 #include <bcm/module.h> 26 #include <soc/scache.h> 27 #include <bcm/error.h> 28 #include <bcm/failover.h> 29 #include <bcm/extender.h> 30 31 #include <bcm_int/esw/firebolt.h> 32 #include <bcm_int/esw/trident2plus.h> 33 #include <bcm_int/esw/switch.h> 34 #include <bcm_int/common/multicast.h> 35 #include <bcm_int/esw/failover.h> 36 #include <bcm_int/esw/triumph2.h> 37 #include <bcm_int/esw/l3.h> 38 #ifdef BCM_TRIDENT3_SUPPORT 39 #include <bcm_int/esw/trident3.h> 40 #endif 41 42 /* Need L3 related information to clean dependent failover state */ 43 #define L3_INFO(unit) (&_bcm_l3_bk_info[unit]) 44 45 #define _bcm_td2p_failover_bk_info _bcm_failover_bk_info 46 typedef _bcm_failover_bookkeeping_t _bcm_td2p_failover_bookkeeping_t; 47 48 /* sw state for multi level failover */ 49 bcmi_failover_multi_level_info_t *bcmi_multi_level_sw_state[BCM_MAX_NUM_UNITS]; 50 51 52 #ifdef BCM_WARM_BOOT_SUPPORT 53 54 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 55 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 56 57 /* 58 * Function: 59 * bcmi_failover_wb_alloc 60 * Purpose: 61 * Allocate space for failover 62 * Parameters: 63 * unit - Device Number 64 * Returns: 65 * BCM_E_XXX 66 */ 67 STATIC int 68 bcmi_failover_wb_alloc(int unit) 69 { 70 soc_scache_handle_t scache_handle; 71 uint8 *scache_ptr; 72 int rv, alloc_size = 0; 73 soc_mem_t prot_group_mem; 74 int num_entry, prot_group_num_entry; 75 76 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 77 return BCM_E_NONE; 78 } 79 80 prot_group_mem = TX_PROT_GROUP_1_TABLEm; 81 82 prot_group_num_entry = (soc_mem_index_count(unit, prot_group_mem)) ; 83 84 /* Get the max range */ 85 num_entry = (soc_mem_index_count(unit, 86 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm)); 87 88 /* Allocate space for multi level attach info */ 89 alloc_size += sizeof(bcmi_failover_multi_level_info_t) * num_entry; 90 alloc_size += SHR_BITALLOCSIZE(num_entry); 91 92 /* Alocate space for init prot to multi failover id mapping */ 93 alloc_size += (sizeof(int) * (num_entry * 2)); 94 /* Allocated space for level-2 failover Ids */ 95 alloc_size += SHR_BITALLOCSIZE(prot_group_num_entry); 96 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0); 97 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 98 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 99 100 if (rv == BCM_E_NOT_FOUND) { 101 rv = BCM_E_NONE; 102 } 103 104 return rv; 105 } 106 107 108 /* 109 * Function: 110 * bcmi_failover_sync 111 * Purpose: 112 * Sync level-2 state in scache 113 * Parameters: 114 * unit - Device Number 115 * Returns: 116 * BCM_E_XXX 117 */ 118 119 int 120 bcmi_failover_sync(int unit) 121 { 122 soc_scache_handle_t scache_handle; 123 uint8 *scache_ptr, *ptr; 124 uint32 index; 125 int num_entry, prot_group_num_entry; 126 bcmi_failover_multi_level_info_t *multi_level_sw_state; 127 int alloc_size = 0; 128 soc_mem_t prot_group_mem; 129 130 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 131 return BCM_E_NONE; 132 } 133 134 prot_group_mem = TX_PROT_GROUP_1_TABLEm; 135 136 prot_group_num_entry = (soc_mem_index_count(unit, prot_group_mem)); 137 138 /* Get the max range */ 139 num_entry = (soc_mem_index_count(unit, 140 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm)); 141 142 /* Allocate space for multi level attach info */ 143 alloc_size += sizeof(bcmi_failover_multi_level_info_t) * num_entry; 144 145 alloc_size += SHR_BITALLOCSIZE(num_entry); 146 /* Alocate space for init prot to multi failover id mapping */ 147 alloc_size += (sizeof(int) * (num_entry * 2)); 148 149 /* Allocated space for level-2 failover Ids */ 150 alloc_size += SHR_BITALLOCSIZE(prot_group_num_entry); 151 152 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0); 153 BCM_IF_ERROR_RETURN 154 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, alloc_size, 155 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 156 157 158 ptr = scache_ptr; 159 for (index = 0; index < num_entry; index++) 160 { 161 multi_level_sw_state = (&(bcmi_multi_level_sw_state[unit][index])); 162 *(((uint32 *)ptr)) = multi_level_sw_state->parent_failover_id; 163 ptr += sizeof(bcm_failover_t); 164 *(((uint32 *)ptr)) = multi_level_sw_state->parent_failover_type; 165 ptr += sizeof(uint32); 166 *(((uint32 *)ptr)) = multi_level_sw_state->child_group_1; 167 ptr += sizeof(bcm_failover_t); 168 *(((uint32 *)ptr)) = multi_level_sw_state->child_group_2; 169 ptr += sizeof(bcm_failover_t); 170 } 171 172 sal_memcpy(ptr, BCM_MULTI_LEVEL_FAILOVER_BITMAP(unit), 173 SHR_BITALLOCSIZE(num_entry)); 174 ptr += SHR_BITALLOCSIZE(num_entry); 175 176 sal_memcpy(ptr, BCM_MULTI_LEVEL_FAILOVER_ID_MAP(unit), 177 (sizeof(int) * num_entry * 2)); 178 ptr += (sizeof(int) * (num_entry *2)); 179 180 sal_memcpy(ptr, BCM_FAILOVER_PROT_GROUP_MAP(unit), 181 SHR_BITALLOCSIZE(prot_group_num_entry)); 182 ptr += SHR_BITALLOCSIZE(prot_group_num_entry); 183 184 185 return BCM_E_NONE; 186 } 187 188 189 /* 190 * Function: 191 * bcmi_failover_reinit 192 * Purpose: 193 * re construct failover state from scache 194 * Parameters: 195 * unit - Device Number 196 * Returns: 197 * BCM_E_XXX 198 */ 199 200 STATIC int 201 bcmi_failover_reinit(int unit) 202 { 203 soc_scache_handle_t scache_handle; 204 uint8 *scache_ptr, *ptr; 205 int stable_size, rv; 206 uint16 recovered_ver; 207 int index; 208 bcmi_failover_multi_level_info_t *multi_level_sw_state; 209 int num_entry, prot_group_num_entry; 210 int alloc_size = 0; 211 soc_mem_t prot_group_mem; 212 213 214 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 215 return BCM_E_NONE; 216 } 217 218 /* Get the max range */ 219 num_entry = (soc_mem_index_count(unit, 220 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm)); 221 222 prot_group_mem = TX_PROT_GROUP_1_TABLEm; 223 224 prot_group_num_entry = (soc_mem_index_count(unit, prot_group_mem)); 225 226 /* Allocate space for multi level attach info */ 227 alloc_size += sizeof(bcmi_failover_multi_level_info_t) * num_entry; 228 229 alloc_size += SHR_BITALLOCSIZE(num_entry); 230 /* Alocate space for init prot to multi failover id mapping */ 231 alloc_size += (sizeof(int) * (num_entry * 2)); 232 233 /* Allocated space for level-2 failover Ids */ 234 alloc_size += SHR_BITALLOCSIZE(prot_group_num_entry); 235 236 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 237 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 238 /* multil level failover warmboot requires extended scache support 239 * level2 warmboot must be enabled 240 */ 241 return BCM_E_NONE; 242 } 243 244 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0); 245 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, alloc_size, &scache_ptr, 246 BCM_WB_DEFAULT_VERSION, &recovered_ver); 247 if (BCM_E_NOT_FOUND == rv) { 248 /* Upgrading from SDK release that does not have warmboot state */ 249 BCM_IF_ERROR_RETURN(bcmi_failover_wb_alloc(unit)); 250 return BCM_E_NONE; 251 } else if (BCM_FAILURE(rv)) { 252 return rv; 253 } 254 255 ptr = scache_ptr; 256 257 for (index = 0; index < num_entry; index++) 258 { 259 multi_level_sw_state = (&(bcmi_multi_level_sw_state[unit][index])); 260 multi_level_sw_state->parent_failover_id = *((uint32 *)ptr); 261 ptr += sizeof(bcm_failover_t); 262 multi_level_sw_state->parent_failover_type = *((uint32 *)ptr); 263 ptr += sizeof(uint32); 264 multi_level_sw_state->child_group_1 = *((uint32 *)ptr); 265 ptr += sizeof(bcm_failover_t); 266 multi_level_sw_state->child_group_2 = *((uint32 *)ptr); 267 ptr += sizeof(bcm_failover_t); 268 } 269 270 271 sal_memcpy(BCM_MULTI_LEVEL_FAILOVER_BITMAP(unit), ptr, 272 SHR_BITALLOCSIZE(num_entry)); 273 ptr += SHR_BITALLOCSIZE(num_entry); 274 275 sal_memcpy(BCM_MULTI_LEVEL_FAILOVER_ID_MAP(unit), ptr, 276 sizeof(int) * (num_entry *2)); 277 ptr += (sizeof(int) * (num_entry *2)); 278 279 sal_memcpy(BCM_FAILOVER_PROT_GROUP_MAP(unit), ptr, 280 SHR_BITALLOCSIZE(prot_group_num_entry)); 281 ptr += SHR_BITALLOCSIZE(prot_group_num_entry); 282 283 return BCM_E_NONE; 284 } 285 #endif 286 /* 287 * Function: 288 * _bcm_td2p_failover_check_init 289 * Purpose: 290 * Check if Failover is initialized 291 * Parameters: 292 * unit - Device Number 293 * Returns: 294 * BCM_E_XXX 295 */ 296 STATIC int 297 _bcm_td2p_failover_check_init (int unit) 298 { 299 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 300 return BCM_E_UNIT; 301 } 302 303 if (!_bcm_td2p_failover_bk_info[unit].initialized) { 304 return BCM_E_INIT; 305 } else { 306 return BCM_E_NONE; 307 } 308 } 309 310 /* 311 * Function: 312 * bcm_failover_lock 313 * Purpose: 314 * Take the Failover Lock Sempahore 315 * Parameters: 316 * unit - Device Number 317 * Returns: 318 * BCM_E_XXX 319 */ 320 int 321 bcm_td2p_failover_lock (int unit) 322 { 323 int rv; 324 325 rv = _bcm_td2p_failover_check_init(unit); 326 327 if ( rv == BCM_E_NONE ) { 328 sal_mutex_take(FAILOVER_INFO((unit))->failover_mutex, 329 sal_mutex_FOREVER); 330 } 331 return rv; 332 } 333 334 /* 335 * Function: 336 * bcm_failover_unlock 337 * Purpose: 338 * Release the Failover Lock Semaphore 339 * Parameters: 340 * unit - Device Number 341 * Returns: 342 * BCM_E_XXX 343 */ 344 void 345 bcm_td2p_failover_unlock (int unit) 346 { 347 int rv; 348 349 rv = _bcm_td2p_failover_check_init(unit); 350 351 if ( rv == BCM_E_NONE ) { 352 sal_mutex_give(FAILOVER_INFO((unit))->failover_mutex); 353 } 354 } 355 356 /* 357 * Function: 358 * bcmi_failover_dependent_free_resources 359 * Purpose: 360 * frees dependednt resources. 361 * Parameters: 362 * unit - (IN)bcm device id 363 * Returns: 364 * NONE 365 */ 366 367 void 368 bcmi_failover_dependent_free_resources(int unit) 369 { 370 _bcm_td2p_failover_bookkeeping_t *failover_info = FAILOVER_INFO(unit); 371 372 if (L3_INFO(unit)->l3_initialized) { 373 return; 374 } 375 376 if (failover_info->initialized) { 377 return; 378 } 379 380 if (failover_info->init_prot_to_multi_failover_id) { 381 sal_free(failover_info->init_prot_to_multi_failover_id); 382 failover_info->init_prot_to_multi_failover_id = NULL; 383 } 384 385 } 386 387 /* 388 * Function: 389 * _bcm_td2p_failover_free_resource 390 * Purpose: 391 * Free all allocated software resources 392 * Parameters: 393 * unit - SOC unit number 394 * Returns: 395 * Nothing 396 */ 397 STATIC void 398 _bcm_td2p_failover_free_resource(int unit, 399 _bcm_td2p_failover_bookkeeping_t *failover_info) 400 { 401 if (!failover_info) { 402 return; 403 } 404 405 if (failover_info->prot_group_bitmap) { 406 sal_free(failover_info->prot_group_bitmap); 407 failover_info->prot_group_bitmap = NULL; 408 } 409 410 if (failover_info->prot_nhi_bitmap) { 411 sal_free(failover_info->prot_nhi_bitmap); 412 failover_info->prot_nhi_bitmap = NULL; 413 } 414 415 if (failover_info->egress_prot_group_bitmap) { 416 sal_free(failover_info->egress_prot_group_bitmap); 417 failover_info->egress_prot_group_bitmap = NULL; 418 } 419 420 if (failover_info->ingress_prot_group_bitmap) { 421 sal_free(failover_info->ingress_prot_group_bitmap); 422 failover_info->ingress_prot_group_bitmap = NULL; 423 } 424 425 if (failover_info->multi_level_failover_bitmap) { 426 sal_free(failover_info->multi_level_failover_bitmap); 427 failover_info->multi_level_failover_bitmap = NULL; 428 } 429 430 if (bcmi_multi_level_sw_state[unit]) { 431 sal_free(bcmi_multi_level_sw_state[unit]); 432 bcmi_multi_level_sw_state[unit] = NULL; 433 } 434 } 435 436 #ifdef BCM_WARM_BOOT_SUPPORT 437 /* 438 * Function: 439 * _bcm_td2p_failover_reinit 440 * Purpose: 441 * Reinit for warm boot. 442 * Parameters: 443 * unit : (IN) Device Unit Number 444 * Returns: 445 * BCM_E_XXX 446 */ 447 STATIC int 448 _bcm_td2p_failover_reinit(int unit) 449 { 450 int idx, index_min, index_max, i , bit_index; 451 tx_initial_prot_group_table_entry_t prot_grp_entry; 452 egr_tx_prot_group_table_entry_t egr_tx_prot_group; 453 rx_prot_group_table_entry_t rx_prot_group_entry; 454 uint32 buf[4]; 455 int value; 456 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 457 uint32 replace_enable_field = REPLACE_ENABLE_BITMAPf; 458 459 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 460 prot_group_mem = TX_PROT_GROUP_1_1_TABLEm; 461 replace_enable_field = REPLACE_ENABLEf; 462 } 463 464 index_min = soc_mem_index_min(unit, prot_group_mem); 465 index_max = soc_mem_index_max(unit, prot_group_mem); 466 467 for (idx = index_min; idx <= index_max; idx++) { 468 469 SOC_IF_ERROR_RETURN(soc_mem_read(unit, prot_group_mem, 470 MEM_BLOCK_ANY, idx, &prot_grp_entry)); 471 472 soc_mem_field_get(unit, prot_group_mem, 473 (uint32 *)&prot_grp_entry, replace_enable_field, buf); 474 for (i = 0; i < BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY; i++) { 475 value = ((buf[i / 32] >> (i % 32)) & 0x1); 476 if (value != 0) { 477 bit_index = (((idx & 0x7) << 7) | (i & 0x7F)); 478 _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, bit_index); 479 } 480 } 481 } 482 483 index_min = soc_mem_index_min(unit, EGR_TX_PROT_GROUP_TABLEm); 484 index_max = soc_mem_index_max(unit, EGR_TX_PROT_GROUP_TABLEm); 485 for (idx = index_min; idx <= index_max; idx++) { 486 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_TX_PROT_GROUP_TABLEm, 487 MEM_BLOCK_ANY, idx, &egr_tx_prot_group)); 488 489 soc_mem_field_get(unit, EGR_TX_PROT_GROUP_TABLEm, 490 (uint32 *)&egr_tx_prot_group, DROP_BITMAPf, buf); 491 for (i = 0; i < BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY; i++) { 492 value = ((buf[i / 32] >> (i % 32)) & 0x1); 493 if (value != 0) { 494 bit_index = (((idx & 0xF) << 7) | (i & 0x7F)); 495 _BCM_FAILOVER_EGRESS_PROT_GROUP_MAP_USED_SET(unit, bit_index); 496 } 497 } 498 } 499 500 index_min = soc_mem_index_min(unit, RX_PROT_GROUP_TABLEm); 501 index_max = soc_mem_index_max(unit, RX_PROT_GROUP_TABLEm); 502 for (idx = index_min; idx <= index_max; idx++) { 503 SOC_IF_ERROR_RETURN(soc_mem_read(unit, RX_PROT_GROUP_TABLEm, 504 MEM_BLOCK_ANY, idx, &rx_prot_group_entry)); 505 soc_mem_field_get(unit, RX_PROT_GROUP_TABLEm, 506 (uint32 *)&rx_prot_group_entry, 507 DROP_DATA_ENABLE_BITMAPf, buf); 508 for (i = 0; i < BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY; i++) { 509 value = ((buf[i / 32] >> (i % 32)) & 0x1); 510 if (value != 0) { 511 bit_index = (((idx & 0x7) << 7) | (i & 0x7F)); 512 _BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_SET(unit, bit_index); 513 } 514 } 515 } 516 return BCM_E_NONE; 517 } 518 #endif /* BCM_WARM_BOOT_SUPPORT */ 519 520 /* 521 * Function: 522 * bcmi_failover_multi_level_failover_offset_init 523 * Purpose: 524 * Initializes offsset table for multi level proteciton 525 * Parameters: 526 * unit - Device Number 527 * Returns: 528 * BCM_E_XXX 529 */ 530 STATIC int 531 bcmi_failover_multi_level_failover_offset_init(int unit) 532 { 533 int rv = BCM_E_NONE; 534 int i = 0; 535 initial_prot_offset_table_entry_t offset_entry; 536 int offset = 0; 537 int num_entries = 0; 538 539 num_entries = soc_mem_index_count(unit, INITIAL_PROT_OFFSET_TABLEm); 540 541 for (; i<num_entries; i++) { 542 offset = 0; 543 544 /* 545 * Offset will be zero if protection is not enabled 546 * at both the levels. 547 */ 548 if ((i & (1 << LVL_1_PROT_ENABLE)) || 549 (i & (1 << LVL_2_PROT_ENABLE))) { 550 551 if ((!(i & (1 << LVL_2_1_REP_ENABLE))) && 552 (!(i & (1 << LVL_2_0_REP_ENABLE))) && 553 (!(i & (1 << LVL_1_REP_ENABLE)))) { 554 555 continue; 556 } 557 558 /* 559 * if protection at both levels are not 560 * enabled, then just put offset as 0. 561 */ 562 if ((i & (1 << LVL_1_PROT_MODE)) && 563 (i & (1 << LVL_2_PROT_MODE))) { 564 /* 565 * Both protection modes are 1+1. 566 * The only offset used will be 0. 567 */ 568 offset = 0; 569 } else if (i & (1 << LVL_2_PROT_MODE)) { 570 /* 571 * THis is 1:1 at level-1 and 1+1 at level-2. 572 */ 573 if (i & (1 << LVL_1_REP_ENABLE)) { 574 offset = 1; 575 } 576 } else if (i & (1 << LVL_1_PROT_MODE)) { 577 /* 578 * This is 1+1 at level 1 and 1:1 at level-2. 579 */ 580 if ((i & (1 << LVL_2_1_REP_ENABLE)) && 581 (i & (1 << LVL_2_0_REP_ENABLE))) { 582 583 offset = 3; 584 } else if (i & (1 << LVL_2_1_REP_ENABLE)) { 585 offset = 2; 586 } else if (i & (1 << LVL_2_0_REP_ENABLE)) { 587 offset = 1; 588 } 589 590 } else { 591 /* 592 * This is 1:1 at level 1 and 1:1 at level-2. 593 */ 594 if (i & (1 << LVL_1_REP_ENABLE)) { 595 596 if (i & (1 << LVL_2_1_REP_ENABLE)) { 597 offset = 3; 598 } else { 599 offset = 2; 600 } 601 } else { 602 if (i & (1 << LVL_2_0_REP_ENABLE)) { 603 offset = 1; 604 } 605 } 606 } 607 } 608 609 soc_mem_field32_set(unit, INITIAL_PROT_OFFSET_TABLEm, 610 &offset_entry, OFFSETf, offset); 611 612 rv = soc_mem_write(unit, INITIAL_PROT_OFFSET_TABLEm, 613 MEM_BLOCK_ALL, i, &offset_entry); 614 615 if (BCM_FAILURE(rv)) { 616 return rv; 617 } 618 } 619 620 return rv; 621 } 622 623 /* 624 * Function: 625 * bcm_td2p_failover_init 626 * Purpose: 627 * Initialize the Failover software module 628 * Parameters: 629 * unit - Device Number 630 * Returns: 631 * BCM_E_XXX 632 */ 633 int 634 bcm_td2p_failover_init (int unit) 635 { 636 int rv = BCM_E_NONE; 637 int num_prot_group, num_prot_nhi; 638 int egress_num_prot_group; 639 int ingress_num_prot_group; 640 _bcm_td2p_failover_bookkeeping_t *failover_info = FAILOVER_INFO(unit); 641 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 642 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 643 int num_double_prot_nhi = 0; 644 #endif 645 646 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 647 prot_group_mem = TX_PROT_GROUP_1_1_TABLEm; 648 } 649 650 /* 651 * allocate resources 652 */ 653 if (failover_info->initialized) { 654 BCM_IF_ERROR_RETURN(bcm_td2p_failover_cleanup(unit)); 655 } 656 657 num_prot_group = (soc_mem_index_count(unit, prot_group_mem) 658 * BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 659 num_prot_nhi = soc_mem_index_count(unit, INITIAL_PROT_NHI_TABLEm); 660 661 failover_info->prot_group_bitmap = 662 sal_alloc(SHR_BITALLOCSIZE(num_prot_group), "prot_group_bitmap"); 663 if (failover_info->prot_group_bitmap == NULL) { 664 _bcm_td2p_failover_free_resource(unit, failover_info); 665 return BCM_E_MEMORY; 666 } 667 668 failover_info->prot_nhi_bitmap = 669 sal_alloc(SHR_BITALLOCSIZE(num_prot_nhi), "prot_nhi_bitmap"); 670 if (failover_info->prot_nhi_bitmap == NULL) { 671 _bcm_td2p_failover_free_resource(unit, failover_info); 672 return BCM_E_MEMORY; 673 } 674 675 /*Egress Prot Group*/ 676 egress_num_prot_group = (soc_mem_index_count(unit, EGR_TX_PROT_GROUP_TABLEm) 677 * BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 678 679 failover_info->egress_prot_group_bitmap = 680 sal_alloc(SHR_BITALLOCSIZE(egress_num_prot_group), 681 "egress_prot_group_bitmap"); 682 if (failover_info->egress_prot_group_bitmap == NULL) { 683 _bcm_td2p_failover_free_resource(unit, failover_info); 684 return BCM_E_MEMORY; 685 } 686 687 /* Rx Prot Group */ 688 ingress_num_prot_group = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 689 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 690 failover_info->ingress_prot_group_bitmap = 691 sal_alloc(SHR_BITALLOCSIZE(ingress_num_prot_group), 692 "ingress_prot_group_bitmap"); 693 if (failover_info->ingress_prot_group_bitmap == NULL) { 694 _bcm_td2p_failover_free_resource(unit, failover_info); 695 return BCM_E_MEMORY; 696 } 697 698 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 699 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 700 num_double_prot_nhi = 701 soc_mem_index_count(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm); 702 703 failover_info->multi_level_failover_bitmap = 704 sal_alloc(SHR_BITALLOCSIZE(num_double_prot_nhi), 705 "ingress_prot_group_bitmap"); 706 if (failover_info->multi_level_failover_bitmap == NULL) { 707 _bcm_td2p_failover_free_resource(unit, failover_info); 708 return BCM_E_MEMORY; 709 } 710 711 if (failover_info->init_prot_to_multi_failover_id == NULL) { 712 failover_info->init_prot_to_multi_failover_id = 713 sal_alloc((num_prot_nhi * sizeof(int)), 714 "init_prot_to_multi_failover_id"); 715 716 if (failover_info->init_prot_to_multi_failover_id == NULL) { 717 _bcm_td2p_failover_free_resource(unit, failover_info); 718 return BCM_E_MEMORY; 719 } 720 } 721 } 722 #endif/*BCM_MULTI_LEVEL_FAILOVER_SUPPORT*/ 723 724 sal_memset(failover_info->prot_group_bitmap, 0, 725 SHR_BITALLOCSIZE(num_prot_group)); 726 sal_memset(failover_info->prot_nhi_bitmap, 0, 727 SHR_BITALLOCSIZE(num_prot_nhi)); 728 sal_memset(failover_info->egress_prot_group_bitmap, 0, 729 SHR_BITALLOCSIZE(egress_num_prot_group)); 730 sal_memset(failover_info->ingress_prot_group_bitmap, 0, 731 SHR_BITALLOCSIZE(ingress_num_prot_group)); 732 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 733 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 734 sal_memset(failover_info->multi_level_failover_bitmap, 0, 735 SHR_BITALLOCSIZE(num_double_prot_nhi)); 736 sal_memset(failover_info->init_prot_to_multi_failover_id, 0, 737 num_prot_nhi * sizeof(int)); 738 739 /* Allocate space for multi level failover s/w state */ 740 bcmi_multi_level_sw_state[unit] = sal_alloc((num_double_prot_nhi * 741 sizeof(bcmi_failover_multi_level_info_t)), "multi level failover"); 742 743 if (bcmi_multi_level_sw_state[unit] == NULL) { 744 _bcm_td2p_failover_free_resource(unit, failover_info); 745 return BCM_E_MEMORY; 746 } 747 sal_memset(bcmi_multi_level_sw_state[unit], 0, 748 (num_double_prot_nhi * 749 sizeof(bcmi_failover_multi_level_info_t))); 750 751 } 752 #endif/*BCM_MULTI_LEVEL_FAILOVER_SUPPORT*/ 753 754 /* Create Failover protection mutex. */ 755 failover_info->failover_mutex = sal_mutex_create("failover_mutex"); 756 if (!failover_info->failover_mutex) { 757 _bcm_td2p_failover_free_resource(unit, failover_info); 758 return BCM_E_MEMORY; 759 } 760 761 #ifdef BCM_WARM_BOOT_SUPPORT 762 if(SOC_WARM_BOOT(unit)) { 763 rv = _bcm_td2p_failover_reinit(unit); 764 if (BCM_FAILURE(rv)){ 765 _bcm_td2p_failover_free_resource(unit, failover_info); 766 return rv; 767 } 768 769 #ifdef BCM_TRIDENT3_SUPPORT 770 if (SOC_IS_TRIDENT3X(unit)) { 771 rv = bcm_td3_failover_reinit(unit); 772 if (BCM_FAILURE(rv)) { 773 _bcm_td2p_failover_free_resource(unit, failover_info); 774 return rv; 775 } 776 } 777 #endif 778 779 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 780 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 781 rv = bcmi_failover_reinit(unit); 782 if (BCM_FAILURE(rv)){ 783 _bcm_td2p_failover_free_resource(unit, failover_info); 784 return rv; 785 } 786 } 787 #endif /*BCM_MULTI_LEVEL_FAILOVER_SUPPORT*/ 788 } else { 789 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 790 rv = bcmi_failover_wb_alloc(unit); 791 if (BCM_FAILURE(rv)){ 792 _bcm_td2p_failover_free_resource(unit, failover_info); 793 return rv; 794 } 795 } 796 #ifdef BCM_TRIDENT3_SUPPORT 797 else if (SOC_IS_TRIDENT3X(unit)) { 798 rv = bcm_td3_failover_alloc(unit); 799 if (BCM_FAILURE(rv)){ 800 _bcm_td2p_failover_free_resource(unit, failover_info); 801 return rv; 802 } 803 } 804 #endif 805 } 806 #endif /* BCM_WARM_BOOT_SUPPORT */ 807 808 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 809 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 810 /* Initialize multi level protection offset table */ 811 rv = bcmi_failover_multi_level_failover_offset_init(unit); 812 if (BCM_FAILURE(rv)){ 813 _bcm_td2p_failover_free_resource(unit, failover_info); 814 return rv; 815 } 816 } 817 #endif /* BCM_MULTI_LEVEL_FAILOVER_SUPPORT */ 818 819 820 /* Mark the state as initialized */ 821 failover_info->initialized = TRUE; 822 823 return rv; 824 } 825 826 /* 827 * Function: 828 * _bcm_td2p_failover_hw_clear 829 * Purpose: 830 * Perform hw tables clean up for failover module. 831 * Parameters: 832 * unit - Device Number 833 * Returns: 834 * BCM_E_XXX 835 */ 836 STATIC int 837 _bcm_td2p_failover_hw_clear (int unit) 838 { 839 int i, rv, rv_error = BCM_E_NONE; 840 int num_entry; 841 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 842 843 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 844 prot_group_mem = TX_PROT_GROUP_1_1_TABLEm; 845 } 846 847 num_entry = (soc_mem_index_count(unit, prot_group_mem) * 848 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 849 850 /* Index-0 is reserved */ 851 for (i = 1; i < num_entry; i++) { 852 if (_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, i)) { 853 rv = bcm_td2p_failover_destroy(unit, i); 854 if (rv < 0) { 855 rv_error = rv; 856 } 857 } 858 } 859 860 if(rv_error != BCM_E_NONE) 861 return rv_error; 862 863 num_entry = (soc_mem_index_count(unit, EGR_TX_PROT_GROUP_TABLEm) * 864 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 865 866 /* Index-0 is reserved */ 867 for (i = 1; i < num_entry; i++) { 868 if (_BCM_FAILOVER_EGRESS_PROT_GROUP_MAP_USED_GET(unit, i)) { 869 /*Encap type is needed to destroy used failoverid*/ 870 _BCM_ENCAP_TYPE_IN_FAILOVER_ID(i, 871 _BCM_FAILOVER_1_1_MC_PROTECTION_MODE); 872 rv = bcm_td2p_failover_destroy(unit, i); 873 if (rv < 0) { 874 rv_error = rv; 875 } 876 } 877 } 878 879 num_entry = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 880 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 881 /* Index-0 is reserved */ 882 for (i = 1; i < num_entry; i++) { 883 if (_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET(unit, i)) { 884 /* Encap type is needed to destroy used failoverid */ 885 _BCM_ENCAP_TYPE_IN_FAILOVER_ID(i, _BCM_FAILOVER_INGRESS); 886 rv = bcm_td2p_failover_destroy(unit, i); 887 if (rv < 0) { 888 rv_error = rv; 889 } 890 } 891 } 892 893 return rv_error; 894 } 895 896 /* 897 * Function: 898 * bcm_td2p_failover_cleanup 899 * Purpose: 900 * DeInit the Failover software module 901 * Parameters: 902 * unit - Device Number 903 * Returns: 904 * BCM_E_XXX 905 */ 906 int 907 bcm_td2p_failover_cleanup (int unit) 908 { 909 _bcm_td2p_failover_bookkeeping_t *failover_info = FAILOVER_INFO(unit); 910 int rv = BCM_E_UNAVAIL; 911 912 if (FALSE == failover_info->initialized) { 913 return (BCM_E_NONE); 914 } 915 916 rv = bcm_td2p_failover_lock(unit); 917 if (BCM_FAILURE(rv)) { 918 return rv; 919 } 920 921 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 922 rv = _bcm_td2p_failover_hw_clear(unit); 923 } 924 925 /* Free software resources */ 926 (void) _bcm_td2p_failover_free_resource(unit, failover_info); 927 928 bcm_td2p_failover_unlock(unit); 929 930 /* Destroy protection mutex. */ 931 sal_mutex_destroy(failover_info->failover_mutex); 932 933 /* Mark the state as uninitialized */ 934 failover_info->initialized = FALSE; 935 936 /* Check for dependent failover state after failover cleanup */ 937 bcmi_failover_dependent_free_resources(unit); 938 939 return rv; 940 } 941 942 943 /* 944 * Function: 945 * _bcm_td2p_failover_get_prot_group_table_index 946 * Purpose: 947 * Obtain Index into INITIAL_PROT_GROUP_TABLE 948 * Parameters: 949 * IN : Unit 950 * OUT : prot_index 951 * Returns: 952 * BCM_E_XXX 953 */ 954 STATIC int 955 _bcm_td2p_failover_get_prot_group_table_index (int unit, int *prot_index) 956 { 957 int i; 958 int num_entry; 959 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 960 961 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 962 prot_group_mem = TX_PROT_GROUP_1_1_TABLEm; 963 } 964 965 num_entry = (soc_mem_index_count(unit, prot_group_mem) * 966 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 967 968 /* Index-0 is reserved */ 969 for (i = 1; i < num_entry; i++) { 970 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, i)) { 971 break; 972 } 973 } 974 975 if (i == num_entry) { 976 return BCM_E_RESOURCE; 977 } 978 _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, i); 979 *prot_index = i; 980 981 return BCM_E_NONE; 982 } 983 984 /* 985 * Function: 986 * _bcm_td2p_failover_clear_prot_group_table_entry 987 * Purpose: 988 * Clear INITIAL_PROT_GROUP_TABLE entry pointed by Index 989 * Parameters: 990 * IN : Unit 991 * IN : prot_index 992 * Returns: 993 * BCM_E_XXX 994 */ 995 STATIC void 996 _bcm_td2p_failover_clear_prot_group_table_entry (int unit, 997 bcm_failover_t prot_index) 998 { 999 _BCM_FAILOVER_PROT_GROUP_MAP_USED_CLR(unit, prot_index); 1000 } 1001 1002 /* 1003 * Function: 1004 * _bcm_td2p_failover_set_prot_group_table_entry 1005 * Purpose: 1006 * Set INITIAL_PROT_GROUP_TABLE entry pointed by Index 1007 * Parameters: 1008 * IN : Unit 1009 * IN : prot_index 1010 * Returns: 1011 * BCM_E_XXX 1012 */ 1013 STATIC void 1014 _bcm_td2p_failover_set_prot_group_table_entry (int unit, 1015 bcm_failover_t prot_index) 1016 { 1017 _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, prot_index); 1018 } 1019 1020 /* 1021 * Function: 1022 * _bcm_td2p_failover_id_validate 1023 * Purpose: 1024 * Validate the failover ID 1025 * Parameters: 1026 * IN : failover_id 1027 * Returns: 1028 * BCM_E_XXX 1029 */ 1030 STATIC int 1031 _bcm_td2p_failover_id_validate (int unit, bcm_failover_t failover_id) 1032 { 1033 int num_entry; 1034 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 1035 1036 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 1037 prot_group_mem = TX_PROT_GROUP_1_1_TABLEm; 1038 } 1039 1040 num_entry = (soc_mem_index_count(unit, prot_group_mem) * 1041 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 1042 1043 if ((failover_id < 1) || (failover_id > num_entry)) { 1044 return BCM_E_PARAM; 1045 } else if (failover_id == num_entry) { 1046 return BCM_E_RESOURCE; 1047 } 1048 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, failover_id)) { 1049 return BCM_E_NOT_FOUND; 1050 } 1051 1052 return BCM_E_NONE; 1053 } 1054 1055 1056 /* 1057 * Function: 1058 * _bcm_td2p_egress_failover_id_validate 1059 * Purpose: 1060 * Validate the egress failover ID 1061 * Parameters: 1062 * IN : failover_id 1063 * Returns: 1064 * BCM_E_XXX 1065 */ 1066 STATIC int 1067 _bcm_td2p_egress_failover_id_validate (int unit, bcm_failover_t failover_id) 1068 { 1069 int num_entry; 1070 1071 num_entry = (soc_mem_index_count(unit, EGR_TX_PROT_GROUP_TABLEm) * 1072 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 1073 1074 if ((failover_id < 1) || (failover_id >= num_entry)) { 1075 return BCM_E_PARAM; 1076 } else if (failover_id == num_entry) { 1077 return BCM_E_RESOURCE; 1078 } 1079 if (!_BCM_FAILOVER_EGRESS_PROT_GROUP_MAP_USED_GET(unit, failover_id)) { 1080 return BCM_E_NOT_FOUND; 1081 } 1082 1083 return BCM_E_NONE; 1084 } 1085 1086 1087 /* 1088 * Function: 1089 * _bcm_td2p_failover_get_egress_prot_group_table_index 1090 * Purpose: 1091 * Obtain Index into EGR_TX_PROT_GROUP_TABLE 1092 * Parameters: 1093 * IN : Unit 1094 * OUT : prot_index 1095 * Returns: 1096 * BCM_E_XXX 1097 */ 1098 STATIC int 1099 _bcm_td2p_failover_get_egress_prot_group_table_index (int unit, 1100 int *prot_index) 1101 { 1102 int i; 1103 int num_entry; 1104 1105 num_entry = (soc_mem_index_count(unit, EGR_TX_PROT_GROUP_TABLEm) * 1106 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 1107 1108 /* Index-0 is reserved */ 1109 for (i = 1; i < num_entry; i++) { 1110 if (!_BCM_FAILOVER_EGRESS_PROT_GROUP_MAP_USED_GET(unit, i)) { 1111 break; 1112 } 1113 } 1114 1115 if (i == num_entry) { 1116 return BCM_E_RESOURCE; 1117 } 1118 1119 *prot_index = i; 1120 return BCM_E_NONE; 1121 } 1122 1123 /* 1124 * Function: 1125 * _bcm_td2p_failover_clear_egress_prot_group_table_index 1126 * Purpose: 1127 * Clear EGR_TX_PROT_GROUP_TABLE entry pointed by Index 1128 * Parameters: 1129 * IN : Unit 1130 * IN : prot_index 1131 * Returns: 1132 * BCM_E_XXX 1133 */ 1134 STATIC void 1135 _bcm_td2p_failover_clear_egress_prot_group_table_index (int unit, 1136 bcm_failover_t prot_index) 1137 { 1138 _BCM_FAILOVER_EGRESS_PROT_GROUP_MAP_USED_CLR(unit, prot_index); 1139 } 1140 1141 /* 1142 * Function: 1143 * _bcm_td2p_failover_set_egress_prot_group_table_index 1144 * Purpose: 1145 * Set EGR_TX_PROT_GROUP_TABLE entry pointed by Index 1146 * Parameters: 1147 * IN : Unit 1148 * IN : prot_index 1149 * Returns: 1150 * BCM_E_XXX 1151 */ 1152 STATIC void 1153 _bcm_td2p_failover_set_egress_prot_group_table_index (int unit, 1154 bcm_failover_t prot_index) 1155 { 1156 _BCM_FAILOVER_EGRESS_PROT_GROUP_MAP_USED_SET(unit,prot_index); 1157 } 1158 1159 /* 1160 * Function: 1161 * _bcm_td2p_failover_ingress_id_validate 1162 * Purpose: 1163 * Validate the ingress failover ID 1164 * Parameters: 1165 * unit : (IN) Device Unit Number 1166 * failover_id : (IN) Ingress failover ID 1167 * Returns: 1168 * BCM_E_XXX 1169 */ 1170 int 1171 _bcm_td2p_failover_ingress_id_validate(int unit, 1172 bcm_failover_t failover_id) 1173 { 1174 int num_entry; 1175 1176 num_entry = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 1177 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 1178 1179 if ((failover_id < 1) || (failover_id >= num_entry)) { 1180 return BCM_E_PARAM; 1181 } 1182 1183 if (!_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET(unit, failover_id)) { 1184 return BCM_E_NOT_FOUND; 1185 } 1186 1187 return BCM_E_NONE; 1188 } 1189 1190 /* 1191 * Function: 1192 * _bcm_td2p_failover_get_ingress_prot_group_table_index 1193 * Purpose: 1194 * Obtain Index into RX_PROT_GROUP_TABLE 1195 * Parameters: 1196 * unit : (IN) Device Unit Number 1197 * prot_index : (OUT) RX_PROT_GROUP_TABLE bit index 1198 * Returns: 1199 * BCM_E_XXX 1200 */ 1201 STATIC int 1202 _bcm_td2p_failover_get_ingress_prot_group_table_index(int unit, 1203 int *prot_index) 1204 { 1205 int i; 1206 int num_entry; 1207 1208 num_entry = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 1209 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 1210 1211 /* Index-0 is reserved */ 1212 for (i = 1; i < num_entry; i++) { 1213 if (!_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET(unit, i)) { 1214 break; 1215 } 1216 } 1217 1218 if (i == num_entry) { 1219 return BCM_E_RESOURCE; 1220 } 1221 1222 *prot_index = i; 1223 return BCM_E_NONE; 1224 } 1225 1226 /* 1227 * Function: 1228 * _bcm_td2p_failover_clear_ingress_prot_group_table_index 1229 * Purpose: 1230 * Clear RX_PROT_GROUP_TABLE entry pointed by Index 1231 * Parameters: 1232 * unit : (IN) Device Unit Number 1233 * prot_index : (IN) RX_PROT_GROUP_TABLE bit index 1234 * Returns: 1235 * BCM_E_XXX 1236 */ 1237 STATIC void 1238 _bcm_td2p_failover_clear_ingress_prot_group_table_index( 1239 int unit, bcm_failover_t prot_index) 1240 { 1241 _BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_CLR(unit, prot_index); 1242 } 1243 1244 /* 1245 * Function: 1246 * _bcm_td2p_failover_set_ingress_prot_group_table_index 1247 * Purpose: 1248 * Set RX_PROT_GROUP_TABLE entry pointed by Index 1249 * Parameters: 1250 * unit : (IN) Device Unit Number 1251 * prot_index : (IN) RX_PROT_GROUP_TABLE bit index 1252 * Returns: 1253 * BCM_E_XXX 1254 */ 1255 STATIC void 1256 _bcm_td2p_failover_set_ingress_prot_group_table_index(int unit, 1257 bcm_failover_t prot_index) 1258 { 1259 _BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_SET(unit, prot_index); 1260 } 1261 1262 /* 1263 * Function: 1264 * _bcm_failover_multi_level_index_get 1265 * Purpose: 1266 * Obtain Index for multi level failover 1267 * Parameters: 1268 * IN : Unit 1269 * OUT : index 1270 * Returns: 1271 * BCM_E_XXX 1272 */ 1273 STATIC int 1274 _bcm_failover_multi_level_index_get(int unit, int *index) 1275 { 1276 int i; 1277 int num_entry; 1278 1279 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 1280 return BCM_E_UNAVAIL; 1281 } 1282 num_entry = (soc_mem_index_count(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm)); 1283 1284 /* Index-0 is reserved */ 1285 for (i = 1; i < num_entry; i++) { 1286 if (!_BCM_FAILOVER_MULTI_LEVEL_MAP_USED_GET(unit, i)) { 1287 break; 1288 } 1289 } 1290 1291 if (i == num_entry) { 1292 return BCM_E_RESOURCE; 1293 } 1294 1295 *index = i; 1296 return BCM_E_NONE; 1297 } 1298 1299 /* 1300 * Function: 1301 * _bcm_failover_multi_level_index_set 1302 * Purpose: 1303 * Obtain Index for multi level failover 1304 * Parameters: 1305 * IN : Unit 1306 * IN : index 1307 * Returns: 1308 * BCM_E_XXX 1309 */ 1310 STATIC void 1311 _bcm_failover_multi_level_index_set(int unit, int index) 1312 { 1313 1314 _BCM_FAILOVER_MULTI_LEVEL_MAP_USED_SET(unit, index); 1315 } 1316 1317 /* 1318 * Function: 1319 * _bcm_failover_multi_level_index_validate 1320 * Purpose: 1321 * Obtain Index for multi level failover 1322 * Parameters: 1323 * IN : Unit 1324 * IN : index 1325 * Returns: 1326 * BCM_E_XXX 1327 */ 1328 STATIC int 1329 _bcm_failover_multi_level_index_validate(int unit, int index) 1330 { 1331 int num_entry; 1332 1333 /* Get the max range */ 1334 num_entry = (soc_mem_index_count(unit, 1335 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm)); 1336 1337 /* make sure the given id is valid */ 1338 if ((index < 1) || (index >= num_entry)) { 1339 return BCM_E_PARAM; 1340 } 1341 1342 return BCM_E_NONE; 1343 } 1344 1345 1346 /* 1347 * Function: 1348 * _bcm_failover_multi_level_index_clear 1349 * Purpose: 1350 * Obtain Index for multi level failover 1351 * Parameters: 1352 * IN : Unit 1353 * IN : index 1354 * Returns: 1355 * BCM_E_XXX 1356 */ 1357 STATIC void 1358 _bcm_failover_multi_level_index_clear(int unit, int index) 1359 { 1360 1361 _BCM_FAILOVER_MULTI_LEVEL_MAP_USED_CLR(unit, index); 1362 } 1363 1364 /* 1365 * Function: 1366 * bcm_td2p_failover_create 1367 * Purpose: 1368 * Create a failover object 1369 * Parameters: 1370 * IN : unit 1371 * IN : flags 1372 * OUT : failover_id 1373 * Returns: 1374 * BCM_E_XXX 1375 */ 1376 int 1377 bcm_td2p_failover_create (int unit, uint32 flags, bcm_failover_t *failover_id) 1378 { 1379 int rv = BCM_E_UNAVAIL; 1380 tx_initial_prot_group_table_entry_t tx_init_prot_group_entry; 1381 rx_prot_group_table_entry_t rx_prot_group_entry; 1382 egr_tx_prot_group_table_entry_t egr_tx_prot_group; 1383 int num_entry,local_failover_id; 1384 int failover_type; 1385 uint32 table_index; 1386 uint32 bit_index; 1387 uint32 buf[4]; 1388 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 1389 uint32 replace_enable_field = REPLACE_ENABLE_BITMAPf; 1390 void *prot_group_entry = &tx_init_prot_group_entry; 1391 #if defined(BCM_MULTI_LEVEL_FAILOVER_SUPPORT) 1392 tx_prot_group_1_1_table_entry_t tx_prot_bitmap_entry; 1393 1394 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 1395 prot_group_mem = TX_PROT_GROUP_1_1_TABLEm; 1396 prot_group_entry = &tx_prot_bitmap_entry; 1397 replace_enable_field = REPLACE_ENABLEf; 1398 } 1399 #endif 1400 1401 if (failover_id == NULL) { 1402 return BCM_E_PARAM; 1403 } 1404 1405 /* Check for unsupported Flag */ 1406 if (flags & (~(BCM_FAILOVER_REPLACE | 1407 BCM_FAILOVER_WITH_ID | 1408 BCM_FAILOVER_ENCAP | 1409 BCM_FAILOVER_INGRESS| 1410 BCM_FAILOVER_MULTI_LEVEL_TYPE))) { 1411 return BCM_E_PARAM; 1412 } 1413 1414 if ((flags & BCM_FAILOVER_WITH_ID) || (flags & BCM_FAILOVER_REPLACE)) { 1415 1416 if ((flags & BCM_FAILOVER_ENCAP) && 1417 (!(flags & BCM_FAILOVER_MULTI_LEVEL_TYPE)) && 1418 (!(flags & BCM_FAILOVER_INGRESS))) { 1419 local_failover_id = *failover_id; 1420 1421 /*Allow failoverIds of type _BCM_FAILOVER_1_1_MC_PROTECTION_MODE*/ 1422 _BCM_GET_FAILOVER_TYPE(local_failover_id, failover_type); 1423 if (!(failover_type & _BCM_FAILOVER_1_1_MC_PROTECTION_MODE)) { 1424 return BCM_E_PARAM; 1425 } 1426 1427 _BCM_GET_FAILOVER_ID(local_failover_id); 1428 /* make sure the given id is valid */ 1429 num_entry = (soc_mem_index_count(unit, EGR_TX_PROT_GROUP_TABLEm) * 1430 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 1431 if ((local_failover_id < 1) || (local_failover_id >= num_entry)) { 1432 return BCM_E_PARAM; 1433 } 1434 if (flags & BCM_FAILOVER_WITH_ID) { 1435 if (_BCM_FAILOVER_EGRESS_PROT_GROUP_MAP_USED_GET(unit, local_failover_id)) { 1436 return BCM_E_EXISTS; 1437 } else { 1438 _BCM_FAILOVER_EGRESS_PROT_GROUP_MAP_USED_SET(unit, local_failover_id); 1439 } 1440 } 1441 if (flags & BCM_FAILOVER_REPLACE) { 1442 if (!_BCM_FAILOVER_EGRESS_PROT_GROUP_MAP_USED_GET(unit, local_failover_id)) { 1443 return BCM_E_NOT_FOUND; 1444 } 1445 } 1446 } else if ((flags & BCM_FAILOVER_INGRESS) && 1447 (!(flags & BCM_FAILOVER_MULTI_LEVEL_TYPE)) && 1448 (!(flags & BCM_FAILOVER_ENCAP))) { 1449 local_failover_id = *failover_id; 1450 1451 /* Allow failoverIds of type _BCM_FAILOVER_INGRESS */ 1452 _BCM_GET_FAILOVER_TYPE(local_failover_id, failover_type); 1453 if (!(failover_type & _BCM_FAILOVER_INGRESS)) { 1454 return BCM_E_PARAM; 1455 } 1456 1457 _BCM_GET_FAILOVER_ID(local_failover_id); 1458 /* make sure the given id is valid */ 1459 num_entry = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 1460 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 1461 if ((local_failover_id < 1) || (local_failover_id >= num_entry)) { 1462 return BCM_E_PARAM; 1463 } 1464 1465 if (flags & BCM_FAILOVER_WITH_ID) { 1466 if (_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET( 1467 unit, local_failover_id)) { 1468 return BCM_E_EXISTS; 1469 } else { 1470 _BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_SET( 1471 unit, local_failover_id); 1472 } 1473 } 1474 1475 if (flags & BCM_FAILOVER_REPLACE) { 1476 if (!_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET( 1477 unit, local_failover_id)) { 1478 return BCM_E_NOT_FOUND; 1479 } 1480 } 1481 } else if (flags & BCM_FAILOVER_MULTI_LEVEL_TYPE) { 1482 local_failover_id = *failover_id; 1483 1484 /* Allow failoverIds of type _BCM_FAILOVER_INGRESS */ 1485 _BCM_GET_FAILOVER_TYPE(local_failover_id, failover_type); 1486 if (!(failover_type & _BCM_FAILOVER_MULTI_LEVEL)) { 1487 return BCM_E_PARAM; 1488 } 1489 1490 _BCM_GET_FAILOVER_ID(local_failover_id); 1491 rv = _bcm_failover_multi_level_index_validate(unit, local_failover_id); 1492 if (BCM_SUCCESS(rv)) { 1493 if (flags & BCM_FAILOVER_REPLACE) { 1494 if (!_BCM_FAILOVER_MULTI_LEVEL_MAP_USED_GET( 1495 unit, local_failover_id)) { 1496 return BCM_E_NOT_FOUND; 1497 } 1498 } 1499 if (flags & BCM_FAILOVER_WITH_ID) { 1500 if (_BCM_FAILOVER_MULTI_LEVEL_MAP_USED_GET(unit, local_failover_id)) { 1501 if (!(flags & BCM_FAILOVER_REPLACE)) { 1502 return BCM_E_EXISTS; 1503 } 1504 } else { 1505 _bcm_failover_multi_level_index_set(unit, local_failover_id); 1506 if (flags & BCM_FAILOVER_ENCAP) { 1507 bcmi_failover_multi_level_info_t *ml_state; 1508 ml_state = 1509 (&(bcmi_multi_level_sw_state[unit][local_failover_id])); 1510 1511 /* Program everything in the software state */ 1512 ml_state->parent_failover_type = 1513 _BCM_FAILOVER_1_1_MC_PROTECTION_MODE; 1514 } 1515 } 1516 } 1517 /* Nothing to be done for this type of failover. return */ 1518 return rv; 1519 } else { 1520 return BCM_E_PARAM; 1521 } 1522 } else if ((flags & BCM_FAILOVER_ENCAP) && (flags & BCM_FAILOVER_INGRESS)) { 1523 local_failover_id = *failover_id; 1524 1525 /* 1526 * Allow failoverIds of type _BCM_FAILOVER_INGRESS 1527 * and BCM_FAILOVER_ENCAP 1528 */ 1529 _BCM_GET_FAILOVER_TYPE(local_failover_id, failover_type); 1530 if (!(failover_type == _BCM_FAILOVER_ING_MC_PROTECTION_MODE)) { 1531 return BCM_E_PARAM; 1532 } 1533 1534 _BCM_GET_FAILOVER_ID(local_failover_id); 1535 1536 /* make sure the given id is valid */ 1537 num_entry = (soc_mem_index_count(unit, prot_group_mem) * 1538 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 1539 if ((local_failover_id < 1) || (local_failover_id >= num_entry)) { 1540 return BCM_E_PARAM; 1541 } 1542 if (flags & BCM_FAILOVER_WITH_ID) { 1543 if (_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, local_failover_id)) { 1544 if (!(flags & BCM_FAILOVER_REPLACE)) { 1545 return BCM_E_EXISTS; 1546 } 1547 } else { 1548 _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, local_failover_id); 1549 } 1550 } 1551 if (flags & BCM_FAILOVER_REPLACE) { 1552 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, local_failover_id)) { 1553 return BCM_E_NOT_FOUND; 1554 } 1555 } 1556 } else { 1557 /* make sure the given id is valid */ 1558 num_entry = (soc_mem_index_count(unit, prot_group_mem) * 1559 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 1560 if ((*failover_id < 1) || (*failover_id >= num_entry)) { 1561 return BCM_E_PARAM; 1562 } 1563 if (flags & BCM_FAILOVER_WITH_ID) { 1564 if (_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, *failover_id)) { 1565 return BCM_E_EXISTS; 1566 } else { 1567 _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, *failover_id); 1568 } 1569 } 1570 if (flags & BCM_FAILOVER_REPLACE) { 1571 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, *failover_id)) { 1572 return BCM_E_NOT_FOUND; 1573 } 1574 } 1575 } 1576 rv = BCM_E_NONE; 1577 } else if (!flags) { 1578 /* Get Index */ 1579 rv = _bcm_td2p_failover_get_prot_group_table_index(unit, failover_id); 1580 } else if ((flags & BCM_FAILOVER_ENCAP) && (flags & BCM_FAILOVER_INGRESS)) { 1581 rv = _bcm_td2p_failover_get_prot_group_table_index(unit, failover_id); 1582 _BCM_ENCAP_TYPE_IN_FAILOVER_ID(*failover_id, 1583 _BCM_FAILOVER_ING_MC_PROTECTION_MODE); 1584 if (!(BCM_SUCCESS(rv))) { 1585 return rv; 1586 } 1587 } else if ((flags & BCM_FAILOVER_ENCAP) && 1588 (!(flags & BCM_FAILOVER_MULTI_LEVEL_TYPE))) { 1589 rv = _bcm_td2p_failover_get_egress_prot_group_table_index(unit, failover_id); 1590 _BCM_FAILOVER_EGRESS_PROT_GROUP_MAP_USED_SET(unit, *failover_id); 1591 _BCM_ENCAP_TYPE_IN_FAILOVER_ID(*failover_id, _BCM_FAILOVER_1_1_MC_PROTECTION_MODE); 1592 } else if ((flags & BCM_FAILOVER_INGRESS) && 1593 (!(flags & BCM_FAILOVER_MULTI_LEVEL_TYPE))) { 1594 rv = _bcm_td2p_failover_get_ingress_prot_group_table_index(unit, 1595 failover_id); 1596 _BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_SET(unit, *failover_id); 1597 _BCM_ENCAP_TYPE_IN_FAILOVER_ID(*failover_id, _BCM_FAILOVER_INGRESS); 1598 } else if (flags & BCM_FAILOVER_MULTI_LEVEL_TYPE) { 1599 rv = _bcm_failover_multi_level_index_get(unit, failover_id); 1600 if (BCM_SUCCESS(rv)) { 1601 _bcm_failover_multi_level_index_set(unit, *failover_id); 1602 if (flags & BCM_FAILOVER_ENCAP) { 1603 bcmi_failover_multi_level_info_t *ml_state; 1604 ml_state = 1605 (&(bcmi_multi_level_sw_state[unit][*failover_id])); 1606 1607 /* Program everything in the software state */ 1608 ml_state->parent_failover_type = 1609 _BCM_FAILOVER_1_1_MC_PROTECTION_MODE; 1610 } 1611 _BCM_ENCAP_TYPE_IN_FAILOVER_ID(*failover_id, 1612 _BCM_FAILOVER_MULTI_LEVEL); 1613 } 1614 /* Nothing to be done for this type of failover scheme. return */ 1615 return rv; 1616 } 1617 1618 if (BCM_SUCCESS(rv)) { 1619 if ((flags & BCM_FAILOVER_ENCAP) && (!(flags & BCM_FAILOVER_INGRESS))) { 1620 local_failover_id = *failover_id; 1621 _BCM_GET_FAILOVER_ID(local_failover_id); 1622 table_index = ((local_failover_id >> 7) & 0xF); 1623 bit_index = (local_failover_id & 0x7F); 1624 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_TX_PROT_GROUP_TABLEm, 1625 MEM_BLOCK_ANY, table_index, &egr_tx_prot_group)); 1626 sal_memcpy(buf, &egr_tx_prot_group, sizeof(buf)); 1627 1628 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1629 1630 soc_mem_field_set(unit, EGR_TX_PROT_GROUP_TABLEm, 1631 (uint32 *)&egr_tx_prot_group, DROP_BITMAPf,buf); 1632 1633 rv = soc_mem_write(unit, EGR_TX_PROT_GROUP_TABLEm, 1634 MEM_BLOCK_ALL, table_index, &egr_tx_prot_group); 1635 if (rv < 0) { 1636 _bcm_td2p_failover_clear_egress_prot_group_table_index(unit, 1637 local_failover_id); 1638 return rv; 1639 } 1640 } else if ((flags & BCM_FAILOVER_INGRESS) && (!(flags & BCM_FAILOVER_ENCAP))) { 1641 1642 local_failover_id = *failover_id; 1643 _BCM_GET_FAILOVER_ID(local_failover_id); 1644 table_index = ((local_failover_id >> 7) & 0x7F); 1645 bit_index = (local_failover_id & 0x7F); 1646 BCM_IF_ERROR_RETURN ( 1647 soc_mem_read(unit, RX_PROT_GROUP_TABLEm, MEM_BLOCK_ANY, 1648 table_index, &rx_prot_group_entry)); 1649 sal_memcpy(buf, &rx_prot_group_entry, sizeof(buf)); 1650 1651 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1652 1653 soc_mem_field_set(unit, RX_PROT_GROUP_TABLEm, 1654 (uint32 *)&rx_prot_group_entry, 1655 DROP_DATA_ENABLE_BITMAPf, buf); 1656 1657 rv = soc_mem_write(unit, RX_PROT_GROUP_TABLEm, MEM_BLOCK_ALL, 1658 table_index, &rx_prot_group_entry); 1659 if (rv < 0) { 1660 _bcm_td2p_failover_clear_ingress_prot_group_table_index( 1661 unit, local_failover_id); 1662 return rv; 1663 } 1664 } else { 1665 local_failover_id = *failover_id; 1666 _BCM_GET_FAILOVER_ID(*failover_id); 1667 /* Init table entry */ 1668 table_index = ((*failover_id >> 7) & BCMI_TX_PROT_GROUP_MASK(unit)); 1669 bit_index = (*failover_id & 0x7F); 1670 BCM_IF_ERROR_RETURN (soc_mem_read(unit, prot_group_mem, 1671 MEM_BLOCK_ANY, table_index, prot_group_entry)); 1672 sal_memcpy(buf, prot_group_entry, sizeof(buf)); 1673 1674 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1675 1676 soc_mem_field_set(unit, prot_group_mem, 1677 (uint32 *)prot_group_entry, replace_enable_field, buf); 1678 1679 rv = soc_mem_write(unit, prot_group_mem, 1680 MEM_BLOCK_ALL, table_index, prot_group_entry); 1681 if (rv < 0) { 1682 _bcm_td2p_failover_clear_prot_group_table_entry(unit, *failover_id); 1683 return BCM_E_RESOURCE; 1684 } 1685 *failover_id = local_failover_id; 1686 } 1687 } 1688 1689 return rv; 1690 } 1691 1692 /* 1693 * Function: 1694 * bcm_td2_failover_destroy 1695 * Purpose: 1696 * Destroy a failover object 1697 * Parameters: 1698 * IN : unit 1699 * IN : failover_id 1700 * Returns: 1701 * BCM_E_XXX 1702 */ 1703 int 1704 bcm_td2p_failover_destroy (int unit, bcm_failover_t failover_id) 1705 { 1706 int rv = BCM_E_UNAVAIL; 1707 int type = _BCM_FAILOVER_DEFAULT_MODE; 1708 int local_failover_id=0; 1709 tx_initial_prot_group_table_entry_t tx_init_prot_group_entry; 1710 rx_prot_group_table_entry_t rx_prot_group_entry; 1711 egr_tx_prot_group_table_entry_t egr_tx_prot_group; 1712 uint32 table_index; 1713 uint32 bit_index; 1714 uint32 buf[4]; 1715 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 1716 uint32 replace_enable_field = REPLACE_ENABLE_BITMAPf; 1717 bcmi_failover_multi_level_info_t *local_multi_level_state; 1718 void *prot_group_entry = &tx_init_prot_group_entry; 1719 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 1720 tx_prot_group_1_table_entry_t tx_prot_group_entry; 1721 tx_prot_group_1_1_table_entry_t tx_prot_bitmap_entry; 1722 1723 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 1724 prot_group_mem = TX_PROT_GROUP_1_1_TABLEm; 1725 prot_group_entry = &tx_prot_bitmap_entry; 1726 replace_enable_field = REPLACE_ENABLEf; 1727 } 1728 #endif 1729 1730 /*Check failover id type Ingress or Egress Encap*/ 1731 _BCM_GET_FAILOVER_TYPE(failover_id, type); 1732 if ((type & _BCM_FAILOVER_1_1_MC_PROTECTION_MODE) && 1733 (!(type & _BCM_FAILOVER_MULTI_LEVEL))) { 1734 1735 local_failover_id = failover_id; 1736 _BCM_GET_FAILOVER_ID(local_failover_id); 1737 1738 rv = _bcm_td2p_egress_failover_id_validate(unit, local_failover_id); 1739 BCM_IF_ERROR_RETURN(rv); 1740 1741 /*Release software index*/ 1742 _bcm_td2p_failover_clear_egress_prot_group_table_index(unit, 1743 local_failover_id); 1744 1745 /*clear hw entry*/ 1746 table_index = ((local_failover_id >> 7) & 0xF); 1747 bit_index = (local_failover_id & 0x7F); 1748 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_TX_PROT_GROUP_TABLEm, 1749 MEM_BLOCK_ANY, table_index, &egr_tx_prot_group)); 1750 1751 sal_memcpy(buf, &egr_tx_prot_group, sizeof(buf)); 1752 1753 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1754 soc_mem_field_set(unit, EGR_TX_PROT_GROUP_TABLEm, 1755 (uint32 *)&egr_tx_prot_group, DROP_BITMAPf, buf); 1756 1757 rv = soc_mem_write(unit, EGR_TX_PROT_GROUP_TABLEm, MEM_BLOCK_ALL, 1758 table_index, &egr_tx_prot_group); 1759 if (rv < 0) { 1760 _bcm_td2p_failover_set_egress_prot_group_table_index(unit, 1761 local_failover_id); 1762 return rv; 1763 } 1764 } else if ((type & _BCM_FAILOVER_INGRESS) && 1765 (!(type == _BCM_FAILOVER_MULTI_LEVEL))) { 1766 local_failover_id = failover_id; 1767 _BCM_GET_FAILOVER_ID(local_failover_id); 1768 1769 rv = _bcm_td2p_failover_ingress_id_validate(unit, local_failover_id); 1770 BCM_IF_ERROR_RETURN(rv); 1771 1772 /*Release software index*/ 1773 _bcm_td2p_failover_clear_ingress_prot_group_table_index( 1774 unit, local_failover_id); 1775 /*clear hw entry*/ 1776 table_index = ((local_failover_id >> 7) & 0x7F); 1777 bit_index = (local_failover_id & 0x7F); 1778 BCM_IF_ERROR_RETURN ( 1779 soc_mem_read(unit, RX_PROT_GROUP_TABLEm, 1780 MEM_BLOCK_ANY, table_index, &rx_prot_group_entry)); 1781 1782 sal_memcpy(buf, &rx_prot_group_entry, sizeof(buf)); 1783 1784 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1785 soc_mem_field_set(unit, RX_PROT_GROUP_TABLEm, 1786 (uint32 *)&rx_prot_group_entry, 1787 DROP_DATA_ENABLE_BITMAPf, buf); 1788 1789 rv = soc_mem_write(unit, RX_PROT_GROUP_TABLEm, MEM_BLOCK_ALL, 1790 table_index, &rx_prot_group_entry); 1791 if (rv < 0) { 1792 _bcm_td2p_failover_set_ingress_prot_group_table_index( 1793 unit, local_failover_id); 1794 return rv; 1795 } 1796 } else if (type & _BCM_FAILOVER_MULTI_LEVEL) { 1797 local_failover_id = failover_id; 1798 _BCM_GET_FAILOVER_ID(local_failover_id); 1799 1800 rv = _bcm_failover_multi_level_index_validate(unit, local_failover_id); 1801 BCM_IF_ERROR_RETURN(rv); 1802 local_multi_level_state = 1803 (&(bcmi_multi_level_sw_state[unit][local_failover_id])); 1804 1805 local_multi_level_state->parent_failover_id = 0; 1806 local_multi_level_state->child_group_1 = 0; 1807 local_multi_level_state->child_group_2 = 0; 1808 1809 _bcm_failover_multi_level_index_clear(unit, local_failover_id); 1810 1811 } else if (type == _BCM_FAILOVER_ING_MC_PROTECTION_MODE) { 1812 local_failover_id = failover_id; 1813 _BCM_GET_FAILOVER_ID(local_failover_id); 1814 1815 rv = _bcm_td2p_failover_id_validate(unit, local_failover_id); 1816 BCM_IF_ERROR_RETURN(rv); 1817 1818 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, local_failover_id)) { 1819 return BCM_E_NOT_FOUND; 1820 } 1821 1822 /*Release index*/ 1823 _bcm_td2p_failover_clear_prot_group_table_entry(unit, local_failover_id); 1824 1825 /* Clear entry */ 1826 table_index = ((local_failover_id >> 7) & BCMI_TX_PROT_GROUP_MASK(unit)); 1827 bit_index = (local_failover_id & 0x7F); 1828 BCM_IF_ERROR_RETURN (soc_mem_read(unit, prot_group_mem, 1829 MEM_BLOCK_ANY, table_index, prot_group_entry)); 1830 1831 sal_memcpy(buf, prot_group_entry, sizeof(buf)); 1832 1833 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1834 soc_mem_field_set(unit, prot_group_mem, 1835 (uint32 *)prot_group_entry, replace_enable_field, buf); 1836 1837 rv = soc_mem_write(unit, prot_group_mem, MEM_BLOCK_ALL, 1838 table_index, prot_group_entry); 1839 1840 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 1841 1842 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 1843 if (type == _BCM_FAILOVER_ING_MC_PROTECTION_MODE) { 1844 /* Set Mode for level-2 protection group. */ 1845 sal_memset(&tx_prot_group_entry, 0, sizeof(tx_prot_group_1_table_entry_t)); 1846 1847 BCM_IF_ERROR_RETURN (soc_mem_write(unit, TX_PROT_GROUP_1_TABLEm, 1848 MEM_BLOCK_ALL, local_failover_id, &tx_prot_group_entry)); 1849 } 1850 } 1851 #endif 1852 if (rv < 0) { 1853 _bcm_td2p_failover_set_prot_group_table_entry(unit, failover_id); 1854 return BCM_E_RESOURCE; 1855 } 1856 } else { 1857 rv = _bcm_td2p_failover_id_validate(unit, failover_id); 1858 BCM_IF_ERROR_RETURN(rv); 1859 1860 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, failover_id)) { 1861 return BCM_E_NOT_FOUND; 1862 } 1863 1864 /*Release index*/ 1865 _bcm_td2p_failover_clear_prot_group_table_entry(unit, failover_id); 1866 1867 /* Clear entry */ 1868 table_index = ((failover_id >> 7) & BCMI_TX_PROT_GROUP_MASK(unit)); 1869 bit_index = (failover_id & 0x7F); 1870 BCM_IF_ERROR_RETURN (soc_mem_read(unit, prot_group_mem, 1871 MEM_BLOCK_ANY, table_index, prot_group_entry)); 1872 1873 sal_memcpy(buf, prot_group_entry, sizeof(buf)); 1874 1875 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1876 soc_mem_field_set(unit, prot_group_mem, 1877 (uint32 *)prot_group_entry, replace_enable_field, buf); 1878 1879 rv = soc_mem_write(unit, prot_group_mem, MEM_BLOCK_ALL, 1880 table_index, prot_group_entry); 1881 if (rv < 0) { 1882 _bcm_td2p_failover_set_prot_group_table_entry(unit, failover_id); 1883 return BCM_E_RESOURCE; 1884 } 1885 } 1886 1887 return rv; 1888 } 1889 1890 STATIC int 1891 _bcm_td2p_failover_nhi_get(int unit, bcm_gport_t port, int *nh_index) 1892 { 1893 int vp=0xFFFF; 1894 ing_dvp_table_entry_t dvp; 1895 1896 if (!BCM_GPORT_IS_MPLS_PORT(port) && 1897 !BCM_GPORT_IS_MIM_PORT(port) ) { 1898 return BCM_E_PARAM; 1899 } 1900 1901 if ( BCM_GPORT_IS_MPLS_PORT(port)) { 1902 vp = BCM_GPORT_MPLS_PORT_ID_GET(port); 1903 } else if ( BCM_GPORT_IS_MIM_PORT(port)) { 1904 vp = BCM_GPORT_MIM_PORT_ID_GET(port); 1905 } 1906 1907 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 1908 return BCM_E_PARAM; 1909 } 1910 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 1911 1912 /* Next-hop index is used for multicast replication */ 1913 *nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 1914 return BCM_E_NONE; 1915 } 1916 1917 /* 1918 * Function: 1919 * bcm_td2p_failover_status_set 1920 * Purpose: 1921 * Set the parameters for a failover object 1922 * Parameters: 1923 * IN : unit 1924 * IN : failover_id 1925 * IN : value 1926 * Returns: 1927 * BCM_E_XXX 1928 */ 1929 int 1930 bcm_td2p_failover_status_set (int unit, 1931 bcm_failover_element_t *failover, 1932 int value) 1933 { 1934 int rv = BCM_E_UNAVAIL; 1935 int nh_index; 1936 int local_failover_id=0; 1937 uint32 table_index = 0; 1938 uint32 bit_index = 0; 1939 uint32 buf[4]; 1940 tx_initial_prot_group_table_entry_t tx_init_prot_group_entry; 1941 rx_prot_group_table_entry_t rx_prot_group_entry; 1942 initial_prot_nhi_table_1_entry_t prot_nhi_1_entry; 1943 egr_tx_prot_group_table_entry_t egr_tx_prot_group; 1944 egr_l3_next_hop_1_entry_t egr_l3_nhop_1_entry; 1945 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 1946 uint32 replace_enable_field = REPLACE_ENABLE_BITMAPf; 1947 void *prot_group_entry = &tx_init_prot_group_entry; 1948 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 1949 tx_prot_group_1_table_entry_t tx_prot_group_entry; 1950 initial_prot_nhi_table_entry_t prot_nhi_entry; 1951 initial_prot_nhi_double_wide_table_entry_t prot_nhi_double_entry; 1952 tx_prot_group_1_1_table_entry_t tx_prot_bitmap_entry; 1953 1954 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 1955 prot_group_mem = TX_PROT_GROUP_1_1_TABLEm; 1956 prot_group_entry = &tx_prot_bitmap_entry; 1957 replace_enable_field = REPLACE_ENABLEf; 1958 } 1959 #endif 1960 1961 if ((value < 0) || (value > 1)) { 1962 return BCM_E_PARAM; 1963 } 1964 1965 if (failover->failover_id != BCM_FAILOVER_INVALID) { 1966 /* Check for UC or MC protection. 1967 * As we can have multiple flags set together, we 1968 * need to check if this particular failover id 1969 * is equal to a particular type. 1970 * if some other flag is set then it can 1971 * represent other failover type. 1972 */ 1973 if (failover->flags == BCM_FAILOVER_ENCAP) { 1974 /*Egr tx prot group table*/ 1975 local_failover_id = failover->failover_id; 1976 _BCM_GET_FAILOVER_ID(local_failover_id); 1977 BCM_IF_ERROR_RETURN( 1978 _bcm_td2p_egress_failover_id_validate(unit,local_failover_id)); 1979 1980 table_index = ((local_failover_id >> 7) & 0xF); 1981 bit_index = (local_failover_id & 0x7F); 1982 1983 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_TX_PROT_GROUP_TABLEm, 1984 MEM_BLOCK_ANY, table_index, &egr_tx_prot_group)); 1985 1986 sal_memcpy(buf, &egr_tx_prot_group, sizeof(buf)); 1987 if (value == 0) { 1988 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1989 } else { 1990 buf[bit_index / 32] |= (0x1 << (bit_index % 32)); 1991 } 1992 1993 soc_mem_field_set(unit, EGR_TX_PROT_GROUP_TABLEm, 1994 (uint32 *)&egr_tx_prot_group, DROP_BITMAPf, buf); 1995 1996 rv = soc_mem_write(unit, EGR_TX_PROT_GROUP_TABLEm, 1997 MEM_BLOCK_ALL, table_index, &egr_tx_prot_group); 1998 1999 } else if (failover->flags == BCM_FAILOVER_INGRESS) { 2000 /* RX prot group table*/ 2001 local_failover_id = failover->failover_id; 2002 _BCM_GET_FAILOVER_ID(local_failover_id); 2003 BCM_IF_ERROR_RETURN( 2004 _bcm_td2p_failover_ingress_id_validate(unit, local_failover_id)); 2005 2006 table_index = ((local_failover_id >> 7) & 0x7F); 2007 bit_index = (local_failover_id & 0x7F); 2008 2009 BCM_IF_ERROR_RETURN( 2010 soc_mem_read(unit, RX_PROT_GROUP_TABLEm, 2011 MEM_BLOCK_ANY, table_index, &rx_prot_group_entry)); 2012 2013 sal_memcpy(buf, &rx_prot_group_entry, sizeof(buf)); 2014 if (value == 0) { 2015 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 2016 } else { 2017 buf[bit_index / 32] |= (0x1 << (bit_index % 32)); 2018 } 2019 2020 soc_mem_field_set(unit, RX_PROT_GROUP_TABLEm, 2021 (uint32 *)&rx_prot_group_entry, 2022 DROP_DATA_ENABLE_BITMAPf, buf); 2023 2024 rv = soc_mem_write(unit, RX_PROT_GROUP_TABLEm, MEM_BLOCK_ALL, 2025 table_index, &rx_prot_group_entry); 2026 } else { 2027 local_failover_id = failover->failover_id; 2028 _BCM_GET_FAILOVER_ID(local_failover_id); 2029 2030 /* Group protection for Port and Tunnel: Egress and Ingress */ 2031 table_index = ((local_failover_id >> 7) & BCMI_TX_PROT_GROUP_MASK(unit)); 2032 bit_index = (local_failover_id & 0x7F); 2033 2034 BCM_IF_ERROR_RETURN( 2035 _bcm_td2p_failover_id_validate(unit, local_failover_id)); 2036 2037 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 2038 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2039 2040 BCM_IF_ERROR_RETURN (soc_mem_read(unit, TX_PROT_GROUP_1_TABLEm, 2041 MEM_BLOCK_ANY, local_failover_id, &tx_prot_group_entry)); 2042 2043 soc_mem_field32_set(unit, TX_PROT_GROUP_1_TABLEm, 2044 (uint32 *)&tx_prot_group_entry, PROT_ENABLEf, 2045 ((failover->element_flags & 2046 BCM_FAILOVER_ELEMENT_USE_SECONDARY) ? 1 : 0)); 2047 2048 BCM_IF_ERROR_RETURN (soc_mem_write(unit, TX_PROT_GROUP_1_TABLEm, 2049 MEM_BLOCK_ALL, local_failover_id, &tx_prot_group_entry)); 2050 } 2051 #endif 2052 BCM_IF_ERROR_RETURN (soc_mem_read(unit, prot_group_mem, 2053 MEM_BLOCK_ANY, table_index, prot_group_entry)); 2054 2055 sal_memcpy(buf, prot_group_entry, sizeof(buf)); 2056 if (value == 0) { 2057 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 2058 } else { 2059 buf[bit_index / 32] |= (0x1 << (bit_index % 32)); 2060 } 2061 2062 soc_mem_field_set(unit, prot_group_mem, 2063 (uint32 *)prot_group_entry, replace_enable_field, buf); 2064 2065 rv = soc_mem_write(unit, prot_group_mem, 2066 MEM_BLOCK_ALL, table_index, prot_group_entry); 2067 } 2068 2069 } else if (failover->intf != BCM_IF_INVALID) { 2070 /* Only Egress is applicable */ 2071 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, failover->intf)) { 2072 nh_index = failover->intf - BCM_XGS3_EGRESS_IDX_MIN(unit); 2073 } else { 2074 nh_index = failover->intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 2075 } 2076 2077 if (failover->flags == BCM_FAILOVER_ENCAP) { 2078 /*Per NHI Egress Protection*/ 2079 table_index = ((nh_index >> 7) & 0x1FF); 2080 bit_index = (nh_index & 0x7F); 2081 2082 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOP_1m, 2083 MEM_BLOCK_ANY, table_index, &egr_l3_nhop_1_entry)); 2084 2085 sal_memcpy(buf, &egr_l3_nhop_1_entry, sizeof(buf)); 2086 if (value == 0) { 2087 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 2088 } else { 2089 buf[bit_index / 32] |= (0x1 << (bit_index % 32)); 2090 } 2091 2092 soc_mem_field_set(unit, EGR_L3_NEXT_HOP_1m, 2093 (uint32 *)&egr_l3_nhop_1_entry, DROP_BITMAPf, buf); 2094 2095 rv = soc_mem_write(unit, EGR_L3_NEXT_HOP_1m, 2096 MEM_BLOCK_ALL, table_index, &egr_l3_nhop_1_entry); 2097 if (rv < 0) { 2098 return rv; 2099 } 2100 } else { 2101 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 2102 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2103 if (bcmi_l3_nh_multi_count_get(unit, nh_index) > 1) { 2104 2105 BCM_IF_ERROR_RETURN (soc_mem_read(unit, 2106 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2107 MEM_BLOCK_ANY, nh_index/2, &prot_nhi_double_entry)); 2108 2109 soc_mem_field32_set(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2110 &prot_nhi_double_entry, PROT_ENABLEf, 2111 ((failover->element_flags & 2112 BCM_FAILOVER_ELEMENT_USE_SECONDARY) ? 1 : 0)); 2113 2114 rv = soc_mem_write(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2115 MEM_BLOCK_ALL, nh_index/2, &prot_nhi_double_entry); 2116 2117 if (rv < 0) { 2118 return BCM_E_NOT_FOUND; 2119 } 2120 } else if (bcmi_l3_nh_multi_count_get(unit, nh_index - 1) > 1) { 2121 /* cant set failover status on next to base nh index. 2122 * If count is more than 1 then next NH is also used and 2123 * entry is read/written in double wide more. 2124 * Reading in single mode will generate SER errors. 2125 */ 2126 return BCM_E_NONE; 2127 } else { 2128 2129 BCM_IF_ERROR_RETURN (soc_mem_read(unit, 2130 INITIAL_PROT_NHI_TABLEm, 2131 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry)); 2132 2133 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 2134 &prot_nhi_entry, PROT_ENABLEf, 2135 ((failover->element_flags & 2136 BCM_FAILOVER_ELEMENT_USE_SECONDARY) ? 1 : 0)); 2137 2138 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm, 2139 MEM_BLOCK_ALL, nh_index, &prot_nhi_entry); 2140 2141 if (rv < 0) { 2142 return BCM_E_NOT_FOUND; 2143 } 2144 } 2145 } 2146 #endif 2147 table_index = ((nh_index >> 7) & 0x1FF); 2148 bit_index = (nh_index & 0x7F); 2149 2150 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLE_1m, 2151 MEM_BLOCK_ANY, table_index, &prot_nhi_1_entry)); 2152 2153 sal_memcpy(buf, &prot_nhi_1_entry, sizeof(buf)); 2154 if (value == 0) { 2155 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 2156 } else { 2157 buf[bit_index / 32] |= (0x1 << (bit_index % 32)); 2158 } 2159 2160 soc_mem_field_set(unit, INITIAL_PROT_NHI_TABLE_1m, 2161 (uint32 *)&prot_nhi_1_entry, REPLACE_ENABLE_BITMAPf, buf); 2162 2163 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLE_1m, 2164 MEM_BLOCK_ALL, table_index, &prot_nhi_1_entry); 2165 if (rv < 0) { 2166 return rv; 2167 } 2168 } 2169 2170 } else if (failover->port != BCM_GPORT_INVALID) { 2171 /* Individual protection for Pseudo-wire: Egress and Ingress */ 2172 BCM_IF_ERROR_RETURN ( 2173 _bcm_td2p_failover_nhi_get(unit, failover->port , &nh_index)); 2174 2175 table_index = ((nh_index >> 7) & 0x1FF); 2176 bit_index = (nh_index & 0x7F); 2177 2178 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLE_1m, 2179 MEM_BLOCK_ANY, table_index, &prot_nhi_1_entry)); 2180 2181 sal_memcpy(buf, &prot_nhi_1_entry, sizeof(buf)); 2182 if (value == 0) { 2183 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 2184 } else { 2185 buf[bit_index / 32] |= (0x1 << (bit_index % 32)); 2186 } 2187 2188 soc_mem_field_set(unit, INITIAL_PROT_NHI_TABLE_1m, 2189 (uint32 *)&prot_nhi_1_entry, REPLACE_ENABLE_BITMAPf, buf); 2190 2191 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLE_1m, 2192 MEM_BLOCK_ALL, table_index, &prot_nhi_1_entry); 2193 2194 } 2195 return rv; 2196 } 2197 2198 2199 /* 2200 * Function: 2201 * bcm_td2p_failover_status_get 2202 * Purpose: 2203 * Get the parameters for a failover object 2204 * Parameters: 2205 * IN : unit 2206 * IN : failover_id 2207 * OUT : value 2208 * Returns: 2209 * BCM_E_XXX 2210 */ 2211 int 2212 bcm_td2p_failover_status_get (int unit, 2213 bcm_failover_element_t *failover, 2214 int *value) 2215 { 2216 tx_initial_prot_group_table_entry_t tx_init_prot_group_entry; 2217 rx_prot_group_table_entry_t rx_prot_group_entry; 2218 initial_prot_nhi_table_1_entry_t prot_nhi_1_entry; 2219 egr_tx_prot_group_table_entry_t egr_tx_prot_group; 2220 egr_l3_next_hop_1_entry_t egr_l3_nhop_1_entry; 2221 int nh_index; 2222 int local_failover_id=0; 2223 uint32 table_index = 0; 2224 uint32 bit_index = 0; 2225 uint32 buf[4]; 2226 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 2227 uint32 replace_enable_field = REPLACE_ENABLE_BITMAPf; 2228 void *prot_group_entry = &tx_init_prot_group_entry; 2229 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 2230 tx_prot_group_1_table_entry_t tx_prot_group_entry; 2231 initial_prot_nhi_table_entry_t prot_nhi_entry; 2232 initial_prot_nhi_double_wide_table_entry_t prot_nhi_double_entry; 2233 tx_prot_group_1_1_table_entry_t tx_prot_bitmap_entry; 2234 2235 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2236 prot_group_mem = TX_PROT_GROUP_1_1_TABLEm; 2237 prot_group_entry = &tx_prot_bitmap_entry; 2238 replace_enable_field = REPLACE_ENABLEf; 2239 } 2240 #endif 2241 2242 if (failover->failover_id != BCM_FAILOVER_INVALID) { 2243 /* As we can have multiple flags set together, we 2244 * need to check if this particular failover id 2245 * is equal to a particular type. 2246 * if some other flag is set then it can 2247 * represent other failover type. 2248 */ 2249 if (failover->flags == BCM_FAILOVER_ENCAP) { 2250 local_failover_id = failover->failover_id; 2251 _BCM_GET_FAILOVER_ID(local_failover_id); 2252 BCM_IF_ERROR_RETURN( 2253 _bcm_td2p_egress_failover_id_validate(unit,local_failover_id)); 2254 2255 table_index = ((local_failover_id >> 7) & 0xF); 2256 bit_index = (local_failover_id & 0x7F); 2257 2258 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_TX_PROT_GROUP_TABLEm, 2259 MEM_BLOCK_ANY, table_index, &egr_tx_prot_group)); 2260 2261 soc_mem_field_get(unit, EGR_TX_PROT_GROUP_TABLEm, 2262 (uint32 *)&egr_tx_prot_group, DROP_BITMAPf, buf); 2263 *value = ((buf[bit_index / 32] >> (bit_index % 32)) & 0x1); 2264 2265 } else if (failover->flags == BCM_FAILOVER_INGRESS) { 2266 local_failover_id = failover->failover_id; 2267 _BCM_GET_FAILOVER_ID(local_failover_id); 2268 BCM_IF_ERROR_RETURN( 2269 _bcm_td2p_failover_ingress_id_validate(unit, local_failover_id)); 2270 2271 table_index = ((local_failover_id >> 7) & 0x7F); 2272 bit_index = (local_failover_id & 0x7F); 2273 2274 BCM_IF_ERROR_RETURN ( 2275 soc_mem_read(unit, RX_PROT_GROUP_TABLEm, 2276 MEM_BLOCK_ANY, table_index, &rx_prot_group_entry)); 2277 2278 soc_mem_field_get(unit, RX_PROT_GROUP_TABLEm, 2279 (uint32 *)&rx_prot_group_entry, 2280 DROP_DATA_ENABLE_BITMAPf, buf); 2281 *value = ((buf[bit_index / 32] >> (bit_index % 32)) & 0x1); 2282 } else { 2283 local_failover_id = failover->failover_id; 2284 _BCM_GET_FAILOVER_ID(local_failover_id); 2285 2286 BCM_IF_ERROR_RETURN( 2287 _bcm_td2p_failover_id_validate(unit, local_failover_id)); 2288 2289 table_index = ((local_failover_id >> 7) & BCMI_TX_PROT_GROUP_MASK(unit)); 2290 bit_index = (local_failover_id & 0x7F); 2291 2292 BCM_IF_ERROR_RETURN (soc_mem_read(unit, prot_group_mem, 2293 MEM_BLOCK_ANY, table_index, prot_group_entry)); 2294 2295 soc_mem_field_get(unit, prot_group_mem, 2296 (uint32 *)prot_group_entry, replace_enable_field, buf); 2297 *value = ((buf[bit_index / 32] >> (bit_index % 32)) & 0x1); 2298 2299 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 2300 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2301 2302 BCM_IF_ERROR_RETURN (soc_mem_read(unit, TX_PROT_GROUP_1_TABLEm, 2303 MEM_BLOCK_ANY, local_failover_id, &tx_prot_group_entry)); 2304 2305 if (soc_mem_field32_get(unit, TX_PROT_GROUP_1_TABLEm, 2306 &tx_prot_group_entry, PROT_ENABLEf)) { 2307 2308 failover->element_flags |= 2309 BCM_FAILOVER_ELEMENT_USE_SECONDARY; 2310 } 2311 } 2312 #endif 2313 } 2314 2315 } else if (failover->intf != BCM_IF_INVALID) { 2316 2317 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, failover->intf)) { 2318 nh_index = failover->intf - BCM_XGS3_EGRESS_IDX_MIN(unit); 2319 } else { 2320 nh_index = failover->intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 2321 } 2322 2323 if (failover->flags == BCM_FAILOVER_ENCAP) { 2324 table_index = ((nh_index >> 7) & 0x1FF); 2325 bit_index = (nh_index & 0x7F); 2326 2327 BCM_IF_ERROR_RETURN (soc_mem_read(unit, EGR_L3_NEXT_HOP_1m, 2328 MEM_BLOCK_ANY, table_index, &egr_l3_nhop_1_entry)); 2329 2330 soc_mem_field_get(unit, EGR_L3_NEXT_HOP_1m, 2331 (uint32 *)&egr_l3_nhop_1_entry, DROP_BITMAPf, buf); 2332 2333 *value = ((buf[bit_index / 32] >> (bit_index % 32)) & 0x1); 2334 2335 } else { 2336 table_index = ((nh_index >> 7) & 0x1FF); 2337 bit_index = (nh_index & 0x7F); 2338 2339 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLE_1m, 2340 MEM_BLOCK_ANY, table_index, &prot_nhi_1_entry)); 2341 2342 soc_mem_field_get(unit, INITIAL_PROT_NHI_TABLE_1m, 2343 (uint32 *)&prot_nhi_1_entry, REPLACE_ENABLE_BITMAPf, buf); 2344 2345 *value = ((buf[bit_index / 32] >> (bit_index % 32)) & 0x1); 2346 2347 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 2348 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2349 if (bcmi_l3_nh_multi_count_get(unit, nh_index) > 1) { 2350 2351 BCM_IF_ERROR_RETURN (soc_mem_read(unit, 2352 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2353 MEM_BLOCK_ANY, nh_index/2, &prot_nhi_double_entry)); 2354 2355 if (soc_mem_field32_get(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2356 &prot_nhi_double_entry, PROT_ENABLEf)) { 2357 2358 failover->element_flags |= 2359 BCM_FAILOVER_ELEMENT_USE_SECONDARY; 2360 } 2361 } else if (bcmi_l3_nh_multi_count_get(unit, nh_index - 1) > 1) { 2362 /* cant set failover status on next to base nh index. 2363 * If count is more than 1 then next NH is also used and 2364 * entry is read/written in double wide more. 2365 * Reading in single mode will generate SER errors. 2366 */ 2367 return BCM_E_NONE; 2368 } else { 2369 BCM_IF_ERROR_RETURN (soc_mem_read(unit, 2370 INITIAL_PROT_NHI_TABLEm, 2371 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry)); 2372 2373 if (soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 2374 &prot_nhi_entry, PROT_ENABLEf)) { 2375 2376 failover->element_flags |= 2377 BCM_FAILOVER_ELEMENT_USE_SECONDARY; 2378 } 2379 } 2380 } 2381 #endif 2382 } 2383 2384 } else if (failover->port != BCM_GPORT_INVALID) { 2385 2386 BCM_IF_ERROR_RETURN ( 2387 _bcm_td2p_failover_nhi_get(unit, failover->port , &nh_index)); 2388 2389 table_index = ((nh_index >> 7) & 0x1FF); 2390 bit_index = (nh_index & 0x7F); 2391 2392 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLE_1m, 2393 MEM_BLOCK_ANY, table_index, &prot_nhi_1_entry)); 2394 2395 soc_mem_field_get(unit, INITIAL_PROT_NHI_TABLE_1m, 2396 (uint32 *)&prot_nhi_1_entry, REPLACE_ENABLE_BITMAPf, buf); 2397 2398 *value = ((buf[bit_index / 32] >> (bit_index % 32)) & 0x1); 2399 } 2400 return BCM_E_NONE; 2401 } 2402 2403 /* 2404 * Function: 2405 * bcm_td2p_failover_prot_nhi_set 2406 * Purpose: 2407 * Set the parameters for PROT_NHI 2408 * Parameters: 2409 * IN : unit 2410 * IN : Primary Next Hop Index 2411 * IN : Protection Next Hop Index 2412 * IN : Failover Group Index 2413 * Returns: 2414 * BCM_E_XXX 2415 */ 2416 int 2417 bcm_td2p_failover_prot_nhi_set(int unit, uint32 flags, int nh_index, 2418 uint32 prot_nh_index, bcm_multicast_t mc_group, 2419 bcm_failover_t failover_id) 2420 { 2421 initial_prot_nhi_table_entry_t prot_nhi_entry; 2422 int rv; 2423 int l3mc_index; 2424 int replacement_type_field = REPLACEMENT_TYPEf; 2425 int replacement_data_field = REPLACEMENT_DATAf; 2426 int len; 2427 2428 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 2429 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry)); 2430 2431 _BCM_GET_FAILOVER_ID(failover_id); 2432 2433 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2434 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 2435 &prot_nhi_entry, PROT_ENABLEf, 1); 2436 2437 replacement_type_field = PROT_MODEf; 2438 replacement_data_field = NEW_NHI_OR_MC_GROUPf; 2439 2440 /* 2441 * As part of 2 level protection, failover id space is increased 2442 * to 16K. But we can still only pass first 1K failover Ids to 2443 * single level failover. 2444 * It should be okay as we can share failover id in single level 2445 * and double level. 2446 */ 2447 len = soc_mem_field_length(unit, INITIAL_PROT_NHI_TABLEm, PROT_GROUPf); 2448 if (failover_id >= (1 << len)) { 2449 return BCM_E_PARAM; 2450 } 2451 } 2452 2453 /* if mc_group is valid */ 2454 if (_BCM_MULTICAST_IS_SET(mc_group)) { 2455 l3mc_index = _BCM_MULTICAST_ID_GET(mc_group); 2456 if ((l3mc_index >= 0) && (l3mc_index < 2457 soc_mem_index_count(unit, L3_IPMCm))) { 2458 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 2459 &prot_nhi_entry, replacement_data_field, 2460 l3mc_index); 2461 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 2462 &prot_nhi_entry, replacement_type_field, 2463 0x1); 2464 } 2465 } else { 2466 /* if prot_nh_index is valid */ 2467 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 2468 &prot_nhi_entry, replacement_data_field, 2469 prot_nh_index); 2470 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 2471 &prot_nhi_entry, replacement_type_field, 2472 0x0); 2473 } 2474 2475 /* if failover_id is valid */ 2476 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 2477 &prot_nhi_entry, PROT_GROUPf, 2478 (uint32) failover_id); 2479 2480 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm, 2481 MEM_BLOCK_ALL, nh_index, &prot_nhi_entry); 2482 2483 return rv; 2484 2485 } 2486 2487 2488 /* 2489 * Function: bcm_td2p_failover_prot_nhi_get 2490 * Purpose: 2491 * Get the parameters for PROT_NHI 2492 * Parameters: 2493 * IN : unit 2494 * IN : primary Next Hop Index 2495 * OUT : Failover Group Index 2496 * OUT : Protection Next Hop Index 2497 * Returns: 2498 * BCM_E_XXX 2499 */ 2500 int 2501 bcm_td2p_failover_prot_nhi_get(int unit, int nh_index, 2502 bcm_failover_t *failover_id, int *prot_nh_index, 2503 bcm_multicast_t *mc_group) 2504 { 2505 initial_prot_nhi_table_entry_t prot_nhi_entry; 2506 uint32 replacement_type; 2507 int l3mc_index; 2508 int replacement_type_field = REPLACEMENT_TYPEf; 2509 int replacement_data_field = REPLACEMENT_DATAf; 2510 2511 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 2512 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry)); 2513 2514 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2515 replacement_type_field = PROT_MODEf; 2516 replacement_data_field = NEW_NHI_OR_MC_GROUPf; 2517 } 2518 2519 *failover_id = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 2520 &prot_nhi_entry, PROT_GROUPf); 2521 2522 replacement_type = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 2523 &prot_nhi_entry, replacement_type_field); 2524 2525 if (!replacement_type) { 2526 *prot_nh_index = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 2527 &prot_nhi_entry, replacement_data_field); 2528 } else { 2529 l3mc_index = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm, 2530 &prot_nhi_entry, replacement_data_field); 2531 _BCM_MULTICAST_GROUP_SET(*mc_group, 2532 _BCM_MULTICAST_TYPE_EGRESS_OBJECT, 2533 l3mc_index); 2534 } 2535 2536 return BCM_E_NONE; 2537 } 2538 2539 /* 2540 * Function: 2541 * bcm_td2p_failover_prot_nhi_update 2542 * Purpose: 2543 * Update the next_hop entry for failover 2544 * Parameters: 2545 * IN : unit 2546 * IN : Old Failover next hop index 2547 * IN : New Failover next hop index 2548 * Returns: 2549 * BCM_E_XXX 2550 */ 2551 int 2552 bcm_td2p_failover_prot_nhi_update (int unit, int old_nh_index, 2553 int new_nh_index) 2554 { 2555 int rv=BCM_E_NONE; 2556 int num_entry, index; 2557 int prot_nh_index; 2558 uint32 replacement_type; 2559 int replacement_type_field = REPLACEMENT_TYPEf; 2560 int replacement_data_field = REPLACEMENT_DATAf; 2561 uint32 *pprot_nhi = NULL; 2562 uint32 *pprot_nhi_entry = NULL; 2563 int entry_size; 2564 2565 num_entry = soc_mem_index_count(unit, INITIAL_PROT_NHI_TABLEm); 2566 2567 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2568 replacement_type_field = PROT_MODEf; 2569 replacement_data_field = NEW_NHI_OR_MC_GROUPf; 2570 } 2571 2572 entry_size = soc_mem_entry_words(unit, INITIAL_PROT_NHI_TABLEm); 2573 pprot_nhi = soc_cm_salloc(unit, num_entry * entry_size * 4, "temp_buf"); 2574 if (pprot_nhi == NULL) { 2575 return BCM_E_MEMORY; 2576 } 2577 rv = soc_mem_read_range(unit, INITIAL_PROT_NHI_TABLEm, MEM_BLOCK_ANY, 0, 2578 num_entry - 1, pprot_nhi); 2579 if (rv == SOC_E_NONE) { 2580 for (index = 0, pprot_nhi_entry = pprot_nhi; index < num_entry; 2581 index++) { 2582 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2583 if ((bcmi_l3_nh_multi_count_get(unit, index)) > 1) { 2584 /* it is a double wide entry and therefore, 2585 * we can not read it in single mode. 2586 * skip the next index also as double wide mode uses 2587 * two indexes. 2588 */ 2589 index++; 2590 pprot_nhi_entry += entry_size * 2; 2591 continue; 2592 } 2593 } 2594 2595 replacement_type = soc_mem_field32_get(unit, 2596 INITIAL_PROT_NHI_TABLEm, 2597 pprot_nhi_entry, 2598 replacement_type_field); 2599 2600 if (!replacement_type) { 2601 prot_nh_index = soc_mem_field32_get(unit, 2602 INITIAL_PROT_NHI_TABLEm, 2603 pprot_nhi_entry, 2604 replacement_data_field); 2605 2606 if (prot_nh_index == old_nh_index) { 2607 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 2608 pprot_nhi_entry, replacement_data_field, 2609 new_nh_index); 2610 } 2611 } 2612 pprot_nhi_entry += entry_size; 2613 } 2614 rv = soc_mem_write_range(unit, INITIAL_PROT_NHI_TABLEm, MEM_BLOCK_ANY, 2615 0, num_entry - 1, pprot_nhi); 2616 } 2617 if (pprot_nhi) { 2618 soc_cm_sfree(unit, pprot_nhi); 2619 } 2620 2621 if (BCM_FAILURE(rv)) { 2622 return rv; 2623 } 2624 2625 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 2626 return BCM_E_NONE; 2627 } 2628 #if defined(BCM_MULTI_LEVEL_FAILOVER_SUPPORT) 2629 entry_size = soc_mem_entry_words(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm); 2630 pprot_nhi = 2631 soc_cm_salloc(unit, (num_entry / 2) * entry_size * 4, "temp_buf"); 2632 if (pprot_nhi == NULL) { 2633 return BCM_E_MEMORY; 2634 } 2635 rv = soc_mem_read_range(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2636 MEM_BLOCK_ANY, 0, (num_entry / 2) - 1, pprot_nhi); 2637 if (rv == SOC_E_NONE) { 2638 for (index = 0, pprot_nhi_entry = pprot_nhi; index < num_entry; 2639 index++) { 2640 if ((bcmi_l3_nh_multi_count_get(unit, index)) > 1) { 2641 2642 replacement_type = 2643 soc_mem_field32_get(unit, 2644 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2645 pprot_nhi_entry, 2646 replacement_type_field); 2647 if (!replacement_type) { 2648 prot_nh_index = 2649 soc_mem_field32_get(unit, 2650 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2651 pprot_nhi_entry, 2652 replacement_data_field); 2653 2654 if (prot_nh_index == old_nh_index) { 2655 soc_mem_field32_set(unit, 2656 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2657 pprot_nhi_entry, 2658 replacement_data_field, 2659 new_nh_index); 2660 } 2661 } 2662 } 2663 /* move index further if this is double wide entry */ 2664 index++; 2665 pprot_nhi_entry += entry_size; 2666 } 2667 rv = soc_mem_write_range(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2668 MEM_BLOCK_ANY, 0, 2669 (num_entry / 2) - 1, pprot_nhi); 2670 } 2671 if (pprot_nhi) { 2672 soc_cm_sfree(unit, pprot_nhi); 2673 } 2674 #endif 2675 2676 return rv; 2677 } 2678 2679 /* 2680 * Function: 2681 * bcm_td2p_failover_prot_nhi_cleanup 2682 * Purpose: 2683 * Cleanup the entry for PROT_NHI 2684 * Parameters: 2685 * IN : unit 2686 * IN : Primary Next Hop Index 2687 * Returns: 2688 * BCM_E_XXX 2689 */ 2690 int 2691 bcm_td2p_failover_prot_nhi_cleanup (int unit, int nh_index) 2692 { 2693 initial_prot_nhi_table_entry_t prot_nhi_entry; 2694 initial_prot_nhi_table_1_entry_t prot_nhi_1_entry; 2695 uint32 table_index = 0; 2696 uint32 bit_index = 0; 2697 uint32 buf[4]; 2698 int rv; 2699 2700 #ifdef BCM_MULTI_LEVEL_FAILOVER_SUPPORT 2701 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2702 if (bcmi_l3_nh_multi_count_get(unit, nh_index) > 1) { 2703 2704 return bcmi_failover_multi_level_prot_nhi_cleanup(unit, nh_index); 2705 } 2706 } 2707 #endif 2708 2709 rv = soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 2710 MEM_BLOCK_ANY, nh_index, &prot_nhi_entry); 2711 2712 if (rv < 0){ 2713 return BCM_E_NOT_FOUND; 2714 } 2715 2716 sal_memset(&prot_nhi_entry, 0, sizeof(initial_prot_nhi_table_entry_t)); 2717 2718 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm, 2719 MEM_BLOCK_ALL, nh_index, &prot_nhi_entry); 2720 2721 if (rv < 0){ 2722 return rv; 2723 } 2724 2725 table_index = ((nh_index >> 7) & 0x1FF); 2726 bit_index = (nh_index & 0x7F); 2727 2728 rv = soc_mem_read(unit, INITIAL_PROT_NHI_TABLE_1m, 2729 MEM_BLOCK_ANY, table_index, &prot_nhi_1_entry); 2730 if (rv < 0){ 2731 return BCM_E_NOT_FOUND; 2732 } 2733 sal_memcpy(buf, &prot_nhi_1_entry, sizeof(buf)); 2734 2735 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 2736 soc_mem_field_set(unit, INITIAL_PROT_NHI_TABLE_1m, 2737 (uint32 *)&prot_nhi_1_entry, REPLACE_ENABLE_BITMAPf, buf); 2738 2739 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLE_1m, 2740 MEM_BLOCK_ALL, table_index, &prot_nhi_1_entry); 2741 2742 return rv; 2743 2744 } 2745 /* 2746 * Function: 2747 * bcmi_failover_multi_level_attach 2748 * Purpose: 2749 * Attach multi level failover objects. 2750 * Parameters: 2751 * unit - (IN) : BCM device number 2752 * attach_info - (IN) : Information to attach two levels of failover. 2753 * 2754 * Desc: 2755 * This function only keeps all the parameters in s/w copy. 2756 * This software database will be used to setup the hardware 2757 * when multi level failover id is passed to create 2758 * egress object of failover/primary ports. 2759 * Returns: 2760 * BCM_E_XXX 2761 */ 2762 int 2763 bcmi_failover_multi_level_attach(int unit, 2764 bcm_failover_multi_level_t attach_info) 2765 { 2766 int num_entry; 2767 int id; 2768 bcmi_failover_multi_level_info_t *local_multi_level_state; 2769 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 2770 int parent_failover_type = 0; 2771 tx_prot_group_1_table_entry_t tx_prot_group_entry; 2772 int child_failover_id = 0; 2773 int child_failover_type_1 = 0; 2774 int child_failover_type_2 = 0; 2775 2776 _BCM_GET_FAILOVER_TYPE(attach_info.failover_id, parent_failover_type); 2777 if (parent_failover_type != _BCM_FAILOVER_MULTI_LEVEL) { 2778 return BCM_E_PARAM; 2779 } 2780 2781 id = attach_info.failover_id; 2782 _BCM_GET_FAILOVER_ID(id); 2783 2784 BCM_IF_ERROR_RETURN(_bcm_failover_multi_level_index_validate(unit, id)); 2785 2786 if (soc_feature(unit, soc_feature_hierarchical_protection)) { 2787 prot_group_mem = TX_PROT_GROUP_1_1_TABLEm; 2788 } 2789 2790 /* make sure the given id is valid */ 2791 num_entry = (soc_mem_index_count(unit, prot_group_mem) * 2792 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY); 2793 2794 child_failover_id = attach_info.prot_group_1; 2795 _BCM_GET_FAILOVER_ID(child_failover_id); 2796 2797 if ((child_failover_id < 1) || 2798 (child_failover_id >= num_entry)) { 2799 2800 return BCM_E_PARAM; 2801 } 2802 /* We also need to check here that both the groups protection type is of same type */ 2803 2804 2805 child_failover_id = attach_info.prot_group_2; 2806 _BCM_GET_FAILOVER_ID(child_failover_id); 2807 2808 if ((child_failover_id < 1) || 2809 (child_failover_id >= num_entry)) { 2810 2811 return BCM_E_PARAM; 2812 } 2813 2814 2815 _BCM_GET_FAILOVER_TYPE(attach_info.prot_group_1, child_failover_type_1); 2816 _BCM_GET_FAILOVER_TYPE(attach_info.prot_group_2, child_failover_type_2); 2817 2818 2819 if (child_failover_type_1 != child_failover_type_2) { 2820 return BCM_E_PARAM; 2821 } 2822 2823 if (child_failover_type_1 == _BCM_FAILOVER_ING_MC_PROTECTION_MODE) { 2824 2825 child_failover_id = attach_info.prot_group_1; 2826 _BCM_GET_FAILOVER_ID(child_failover_id); 2827 2828 /* Set Mode for level-2 protection group. */ 2829 BCM_IF_ERROR_RETURN (soc_mem_read(unit, TX_PROT_GROUP_1_TABLEm, 2830 MEM_BLOCK_ANY, child_failover_id, &tx_prot_group_entry)); 2831 2832 soc_mem_field32_set(unit, TX_PROT_GROUP_1_TABLEm, 2833 (uint32 *)&tx_prot_group_entry, PROT_MODEf, 1); 2834 2835 BCM_IF_ERROR_RETURN (soc_mem_write(unit, TX_PROT_GROUP_1_TABLEm, 2836 MEM_BLOCK_ALL, child_failover_id, &tx_prot_group_entry)); 2837 2838 /* Write for second level-2 group also. */ 2839 child_failover_id = attach_info.prot_group_2; 2840 _BCM_GET_FAILOVER_ID(child_failover_id); 2841 2842 BCM_IF_ERROR_RETURN (soc_mem_read(unit, TX_PROT_GROUP_1_TABLEm, 2843 MEM_BLOCK_ANY, child_failover_id, &tx_prot_group_entry)); 2844 2845 soc_mem_field32_set(unit, TX_PROT_GROUP_1_TABLEm, 2846 (uint32 *)&tx_prot_group_entry, PROT_MODEf, 1); 2847 2848 BCM_IF_ERROR_RETURN (soc_mem_write(unit, TX_PROT_GROUP_1_TABLEm, 2849 MEM_BLOCK_ALL, child_failover_id, &tx_prot_group_entry)); 2850 2851 } 2852 2853 2854 local_multi_level_state = (&(bcmi_multi_level_sw_state[unit][id])); 2855 2856 /* Program everything in the software state */ 2857 local_multi_level_state->parent_failover_id = attach_info.failover_id; 2858 local_multi_level_state->child_group_1 = attach_info.prot_group_1; 2859 local_multi_level_state->child_group_2 = attach_info.prot_group_2; 2860 2861 return BCM_E_NONE; 2862 } 2863 2864 /* 2865 * Function: 2866 * bcmi_failover_multi_level_prot_nhi_create 2867 * Purpose: 2868 * Creates/inializes an entry of multi level failover type. 2869 * Parameters: 2870 * unit - (IN) : BCM device number 2871 * nh_index - (IN) : nh index at which the entry is being created. 2872 * 2873 * Desc: 2874 * This function initializes entry for multi level double 2875 * wide initial protection nhi. 2876 * Returns: 2877 * BCM_E_XXX 2878 */ 2879 int 2880 bcmi_failover_multi_level_prot_nhi_create(int unit, int nh_index) 2881 { 2882 initial_prot_nhi_double_wide_table_entry_t prot_nhi_double_entry; 2883 int rv = BCM_E_UNAVAIL; 2884 2885 sal_memset(&prot_nhi_double_entry, 0, 2886 sizeof(initial_prot_nhi_double_wide_table_entry_t)); 2887 2888 /* now write at the half the index for this double wide 2889 * entry. As the ASIC reads two prot nhi entryies in 2890 * double mode. 2891 */ 2892 rv = soc_mem_write(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2893 MEM_BLOCK_ALL, (nh_index/2), &prot_nhi_double_entry); 2894 2895 return rv; 2896 } 2897 2898 /* 2899 * Function: 2900 * bcmi_failover_multi_level_prot_nhi_set 2901 * Purpose: 2902 * Set multi level protection nhi failover entry 2903 * Parameters: 2904 * unit - (IN) : BCM device number 2905 * nh_index - (IN) : next hop index to set failover entry 2906 * prot_nh_index - (IN) : protection next hop index 2907 * mc_group - (IN) : multicast group 2908 * failover_id - (IN) : failover group id 2909 * 2910 * Desc: 2911 * This function sets protection table entry at 2912 * index provided by nh index. 2913 * Returns: 2914 * BCM_E_XXX 2915 */ 2916 int 2917 bcmi_failover_multi_level_prot_nhi_set(int unit, int nh_index, 2918 uint32 prot_nh_index, bcm_multicast_t mc_group, 2919 bcm_failover_t failover_id) 2920 2921 { 2922 initial_prot_nhi_double_wide_table_entry_t prot_nhi_double_entry; 2923 int rv = BCM_E_UNAVAIL; 2924 bcmi_failover_multi_level_info_t *local_multi_level_state; 2925 int id; 2926 int l3mc_index; 2927 bcm_failover_t prot_group_1_id, prot_group_2_id, parent_failover_id; 2928 int prot_group_1, prot_group_2; 2929 int parent_failover_type, child_failover_type; 2930 int mc_protection = 0; 2931 void *null_entry = NULL; 2932 2933 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 2934 return BCM_E_UNAVAIL; 2935 } 2936 2937 null_entry = soc_mem_entry_null(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm); 2938 sal_memcpy(&prot_nhi_double_entry, null_entry, 2939 sizeof(initial_prot_nhi_double_wide_table_entry_t)); 2940 2941 id = failover_id; 2942 _BCM_GET_FAILOVER_ID(id); 2943 2944 local_multi_level_state = (&(bcmi_multi_level_sw_state[unit][id])); 2945 2946 /* Program everything in the software state */ 2947 parent_failover_id = local_multi_level_state->parent_failover_id; 2948 parent_failover_type= local_multi_level_state->parent_failover_type; 2949 prot_group_1 = local_multi_level_state->child_group_1; 2950 prot_group_2 = local_multi_level_state->child_group_2; 2951 2952 prot_group_1_id = prot_group_1; 2953 prot_group_2_id = prot_group_2; 2954 _BCM_GET_FAILOVER_ID(prot_group_1_id); 2955 _BCM_GET_FAILOVER_ID(prot_group_2_id); 2956 2957 /* 2958 * No need to check if both child protection type is same. 2959 * it is already checked when attach was done. 2960 */ 2961 _BCM_GET_FAILOVER_TYPE(prot_group_1, child_failover_type); 2962 2963 if ((parent_failover_type == _BCM_FAILOVER_1_1_MC_PROTECTION_MODE) || 2964 (child_failover_type == _BCM_FAILOVER_ING_MC_PROTECTION_MODE)) { 2965 mc_protection = TRUE; 2966 } 2967 2968 /* set the entry as double wide. */ 2969 soc_mem_field32_set(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2970 &prot_nhi_double_entry, DOUBLE_WIDE_MODEf, 1); 2971 2972 /* Write prot groups for second level group hierarchy.*/ 2973 soc_mem_field32_set(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2974 &prot_nhi_double_entry, PROT_GROUP_INDEX_0f, prot_group_1_id); 2975 2976 soc_mem_field32_set(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2977 &prot_nhi_double_entry, PROT_GROUP_INDEX_1f, prot_group_2_id); 2978 2979 /* we are using new priotection (hierarchy) technique. */ 2980 soc_mem_field32_set(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2981 &prot_nhi_double_entry, USE_NEW_PROTf, 1); 2982 2983 if (mc_protection) { 2984 2985 if (parent_failover_type == _BCM_FAILOVER_1_1_MC_PROTECTION_MODE) { 2986 soc_mem_field32_set(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2987 &prot_nhi_double_entry, PROT_MODEf, 1); 2988 } 2989 2990 l3mc_index = _BCM_MULTICAST_ID_GET(mc_group); 2991 /* validate the index */ 2992 if ((l3mc_index < 0) || (l3mc_index > 2993 soc_mem_index_count(unit, L3_IPMCm))) { 2994 return BCM_E_PARAM; 2995 } 2996 2997 soc_mem_field32_set(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 2998 &prot_nhi_double_entry, NEW_NHI_OR_MC_GROUPf, l3mc_index); 2999 } else { 3000 3001 /* if user makes base index of multi 3002 * level protection as primary, then he might 3003 * want to use the same NH as prot NH. 3004 * that way next 3 NHs are used as backup NHs. 3005 * other option is that he might be sending mc group, 3006 * but in that case we will not even use failover_if_id. 3007 */ 3008 if (bcmi_l3_nh_multi_count_get(unit, nh_index) == 4) { 3009 3010 soc_mem_field32_set(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3011 &prot_nhi_double_entry, NEW_NHI_OR_MC_GROUPf, nh_index); 3012 } else { 3013 soc_mem_field32_set(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3014 &prot_nhi_double_entry, NEW_NHI_OR_MC_GROUPf, prot_nh_index); 3015 } 3016 3017 /* 3018 * Just making sure to set it to zero in case someone 3019 * tries to change failover groups and then try to set prot nhi again 3020 */ 3021 soc_mem_field32_set(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3022 &prot_nhi_double_entry, PROT_MODEf, 0); 3023 } 3024 3025 /* set s/w state of failover id at this NH */ 3026 _BCM_FAILOVER_MULTI_LEVEL_FAILOVER_ID_SET(unit, nh_index, parent_failover_id); 3027 3028 /* now write at the half the index for this double wide 3029 * entry. As the ASIC reads two prot nhi entryies in 3030 * double mode. 3031 */ 3032 rv = soc_mem_write(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3033 MEM_BLOCK_ALL, (nh_index/2), &prot_nhi_double_entry); 3034 3035 return rv; 3036 } 3037 /* 3038 * Function: 3039 * bcmi_failover_multi_level_prot_nhi_cleanup 3040 * Purpose: 3041 * Clean failover entry at this next hop. 3042 * Parameters: 3043 * unit - (IN) : BCM device number 3044 * nh_index - (IN) : nh index where the failover entry is pointing. 3045 * 3046 * Returns: 3047 * BCM_E_XXX 3048 */ 3049 int 3050 bcmi_failover_multi_level_prot_nhi_cleanup (int unit, int nh_index) 3051 { 3052 initial_prot_nhi_double_wide_table_entry_t prot_nhi_double_entry; 3053 initial_prot_nhi_table_1_entry_t prot_nhi_1_entry; 3054 uint32 table_index = 0; 3055 uint32 bit_index = 0; 3056 uint32 buf[4]; 3057 int rv; 3058 3059 rv = soc_mem_read(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3060 MEM_BLOCK_ANY, nh_index/2, &prot_nhi_double_entry); 3061 3062 if (rv < 0){ 3063 return BCM_E_NOT_FOUND; 3064 } 3065 3066 sal_memset(&prot_nhi_double_entry, 0, 3067 sizeof(initial_prot_nhi_double_wide_table_entry_t)); 3068 3069 rv = soc_mem_write(unit, INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3070 MEM_BLOCK_ANY, nh_index/2, &prot_nhi_double_entry); 3071 3072 if (rv < 0){ 3073 return rv; 3074 } 3075 3076 table_index = ((nh_index >> 7) & 0x1FF); 3077 bit_index = (nh_index & 0x7F); 3078 3079 rv = soc_mem_read(unit, INITIAL_PROT_NHI_TABLE_1m, 3080 MEM_BLOCK_ANY, table_index, &prot_nhi_1_entry); 3081 if (rv < 0){ 3082 return BCM_E_NOT_FOUND; 3083 } 3084 sal_memcpy(buf, &prot_nhi_1_entry, sizeof(buf)); 3085 3086 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 3087 soc_mem_field_set(unit, INITIAL_PROT_NHI_TABLE_1m, 3088 (uint32 *)&prot_nhi_1_entry, REPLACE_ENABLE_BITMAPf, buf); 3089 3090 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLE_1m, 3091 MEM_BLOCK_ALL, table_index, &prot_nhi_1_entry); 3092 3093 return rv; 3094 } 3095 3096 /* 3097 * Function: 3098 * bcmi_failover_multi_level_prot_nhi_get 3099 * Purpose: 3100 * Get failover paramenters at this next hop. 3101 * Parameters: 3102 * unit - (IN) : BCM device number 3103 * nh_index - (IN) : nh index where the failover entry is pointing. 3104 * failover_id - (IN) : Failover group 3105 * prot_nh_index- (IN): protected next hop 3106 * mc_group (IN): multicast group 3107 * 3108 * Returns: 3109 * BCM_E_XXX 3110 */ 3111 int 3112 bcmi_failover_multi_level_prot_nhi_get(int unit, int nh_index, 3113 bcm_failover_t *failover_id, int *prot_nh_index, 3114 bcm_multicast_t *mc_group) 3115 { 3116 uint32 replacement_type; 3117 int l3mc_index = 0 , prot_group_idx = 0, prot_group_prot_mode = 0; 3118 initial_prot_nhi_double_wide_table_entry_t prot_nhi_double_entry; 3119 tx_prot_group_1_table_entry_t tx_prot_group_entry; 3120 3121 if (!(soc_feature(unit, soc_feature_hierarchical_protection))) { 3122 return BCM_E_UNAVAIL; 3123 } 3124 3125 3126 BCM_IF_ERROR_RETURN (soc_mem_read(unit, 3127 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3128 MEM_BLOCK_ANY, nh_index/2, &prot_nhi_double_entry)); 3129 3130 3131 _BCM_FAILOVER_MULTI_LEVEL_FAILOVER_ID_GET(unit, nh_index, *failover_id); 3132 3133 replacement_type = soc_mem_field32_get(unit, 3134 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3135 &prot_nhi_double_entry, PROT_MODEf); 3136 3137 prot_group_idx = soc_mem_field32_get(unit, 3138 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3139 &prot_nhi_double_entry, PROT_GROUP_INDEX_1f); 3140 3141 BCM_IF_ERROR_RETURN (soc_mem_read(unit, TX_PROT_GROUP_1_TABLEm, 3142 MEM_BLOCK_ANY, prot_group_idx, &tx_prot_group_entry)); 3143 3144 prot_group_prot_mode = soc_mem_field32_get(unit, 3145 TX_PROT_GROUP_1_TABLEm, (&tx_prot_group_entry), 3146 PROT_MODEf); 3147 3148 /* 3149 * If protection mode at level 1 3150 * or level 2 is 1 then we will have multicast group 3151 * set in the double wide protection tables. 3152 */ 3153 replacement_type |= prot_group_prot_mode; 3154 3155 if (!replacement_type) { 3156 *prot_nh_index = soc_mem_field32_get(unit, 3157 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3158 &prot_nhi_double_entry, NEW_NHI_OR_MC_GROUPf); 3159 /* In case of multi level swithing, we can have a primary port 3160 * pointing to a failover port but the primary port is the 3161 * starting point of all the backup links. 3162 * Backup links are created in the next 3 indexes of primary 3163 * nexthop. but to access all primary and backup links, 3164 * SDK will point primary to primary and then 3165 * backup links will be accessed from the offset generated 3166 * from failover tables. 3167 * If the primary port is pointing to its own NH, then it is sure 3168 * that failover link was on the next nh index of priamry. 3169 */ 3170 if (*prot_nh_index == nh_index) { 3171 *prot_nh_index += 1; 3172 } 3173 } else { 3174 l3mc_index = soc_mem_field32_get(unit, 3175 INITIAL_PROT_NHI_DOUBLE_WIDE_TABLEm, 3176 &prot_nhi_double_entry, NEW_NHI_OR_MC_GROUPf); 3177 3178 _BCM_MULTICAST_GROUP_SET(*mc_group, 3179 _BCM_MULTICAST_TYPE_EGRESS_OBJECT, 3180 l3mc_index); 3181 } 3182 3183 return BCM_E_NONE; 3184 } 3185 3186 3187 #endif /* defined(BCM_TRIDENT2PLUS_SUPPORT) && defined(INCLUDE_L3) */