failover.c (36628B)
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 TH2 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(INCLUDE_L3) 18 #if defined(BCM_TOMAHAWK2_SUPPORT) 19 20 #include <soc/drv.h> 21 #include <soc/mem.h> 22 #include <soc/util.h> 23 #include <soc/debug.h> 24 25 #include <bcm/types.h> 26 #include <bcm/error.h> 27 #include <bcm/module.h> 28 #include <soc/scache.h> 29 #include <bcm/failover.h> 30 #include <bcm/extender.h> 31 32 #include <bcm_int/esw/switch.h> 33 #include <bcm_int/esw/firebolt.h> 34 #include <bcm_int/esw/tomahawk2.h> 35 #include <bcm_int/common/multicast.h> 36 #include <bcm_int/esw/failover.h> 37 #include <bcm_int/esw/triumph2.h> 38 39 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 40 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_0 41 42 43 #define _bcm_th2_failover_bk_info _bcm_failover_bk_info 44 typedef _bcm_failover_bookkeeping_t _bcm_th2_failover_bookkeeping_t; 45 46 /* 47 * Function: 48 * _bcm_th2_failover_check_init 49 * Purpose: 50 * Check if Failover is initialized 51 * Parameters: 52 * unit - Device Number 53 * Returns: 54 * BCM_E_XXX 55 */ 56 STATIC int 57 _bcm_th2_failover_check_init (int unit) 58 { 59 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { 60 return BCM_E_UNIT; 61 } 62 63 if (!_bcm_th2_failover_bk_info[unit].initialized) { 64 return BCM_E_INIT; 65 } else { 66 return BCM_E_NONE; 67 } 68 } 69 70 /* 71 * Function: 72 * bcm_failover_lock 73 * Purpose: 74 * Take the Failover Lock Sempahore 75 * Parameters: 76 * unit - Device Number 77 * Returns: 78 * BCM_E_XXX 79 */ 80 int 81 bcm_th2_failover_lock (int unit) 82 { 83 int rv; 84 85 rv = _bcm_th2_failover_check_init(unit); 86 87 if ( rv == BCM_E_NONE ) { 88 sal_mutex_take(FAILOVER_INFO((unit))->failover_mutex, 89 sal_mutex_FOREVER); 90 } 91 return rv; 92 } 93 94 /* 95 * Function: 96 * bcm_failover_unlock 97 * Purpose: 98 * Release the Failover Lock Semaphore 99 * Parameters: 100 * unit - Device Number 101 * Returns: 102 * BCM_E_XXX 103 */ 104 void 105 bcm_th2_failover_unlock (int unit) 106 { 107 int rv; 108 109 rv = _bcm_th2_failover_check_init(unit); 110 111 if ( rv == BCM_E_NONE ) { 112 sal_mutex_give(FAILOVER_INFO((unit))->failover_mutex); 113 } 114 } 115 116 /* 117 * Function: 118 * _bcm_th2_failover_free_resource 119 * Purpose: 120 * Free all allocated software resources 121 * Parameters: 122 * unit - SOC unit number 123 * Returns: 124 * Nothing 125 */ 126 STATIC void 127 _bcm_th2_failover_free_resource(int unit, 128 _bcm_th2_failover_bookkeeping_t *failover_info) 129 { 130 if (!failover_info) { 131 return; 132 } 133 134 if (failover_info->prot_group_bitmap) { 135 sal_free(failover_info->prot_group_bitmap); 136 failover_info->prot_group_bitmap = NULL; 137 } 138 139 if (failover_info->ingress_prot_group_bitmap) { 140 sal_free(failover_info->ingress_prot_group_bitmap); 141 failover_info->ingress_prot_group_bitmap = NULL; 142 } 143 return; 144 } 145 146 #ifdef BCM_WARM_BOOT_SUPPORT 147 /* 148 * Function: 149 * _bcm_th2_failover_wb_alloc 150 * Purpose: 151 * Allocate space for failover 152 * Parameters: 153 * unit - Device Number 154 * Returns: 155 * BCM_E_XXX 156 */ 157 STATIC int 158 _bcm_th2_failover_wb_alloc(int unit) 159 { 160 soc_scache_handle_t scache_handle; 161 uint8 *scache_ptr; 162 int rv, stable_size, alloc_size = 0; 163 int num_prot_group, rx_num_prot_group; 164 num_prot_group = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) 165 * BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 166 alloc_size += SHR_BITALLOCSIZE(num_prot_group); 167 168 rx_num_prot_group = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) 169 * BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 170 alloc_size += SHR_BITALLOCSIZE(rx_num_prot_group); 171 172 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 173 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 174 return BCM_E_NONE; 175 } 176 177 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0); 178 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 179 &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL); 180 181 if (rv == BCM_E_NOT_FOUND) { 182 rv = BCM_E_NONE; 183 } 184 185 return rv; 186 } 187 188 /* 189 * Function: 190 * _bcm_th2_failover_sync 191 * Purpose: 192 * Sync level-2 state in scache 193 * Parameters: 194 * unit - Device Number 195 * Returns: 196 * BCM_E_XXX 197 */ 198 199 int 200 _bcm_th2_failover_sync(int unit) 201 { 202 soc_scache_handle_t scache_handle; 203 uint8 *scache_ptr, *ptr; 204 int num_prot_group, rx_num_prot_group, stable_size; 205 206 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 207 /* Requires extended scache support level-2 warmboot */ 208 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 209 return BCM_E_NONE; 210 } 211 num_prot_group = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) * 212 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 213 rx_num_prot_group = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 214 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 215 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0); 216 BCM_IF_ERROR_RETURN 217 (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 218 BCM_WB_DEFAULT_VERSION, NULL)); 219 220 ptr = scache_ptr; 221 222 sal_memcpy(ptr, BCM_FAILOVER_PROT_GROUP_MAP(unit), 223 SHR_BITALLOCSIZE(num_prot_group)); 224 ptr += SHR_BITALLOCSIZE(num_prot_group); 225 226 sal_memcpy(ptr, BCM_FAILOVER_INGRESS_PROT_GROUP_MAP(unit), 227 SHR_BITALLOCSIZE(rx_num_prot_group)); 228 ptr += SHR_BITALLOCSIZE(rx_num_prot_group); 229 230 231 return BCM_E_NONE; 232 } 233 234 235 /* 236 * Function: 237 * _bcm_th2_failover_reinit 238 * Purpose: 239 * Reinit for warm boot. 240 * Parameters: 241 * unit : (IN) Device Unit Number 242 * Returns: 243 * BCM_E_XXX 244 */ 245 STATIC int 246 _bcm_th2_failover_reinit(int unit) 247 { 248 soc_scache_handle_t scache_handle; 249 uint8 *scache_ptr, *ptr; 250 int stable_size, rv; 251 uint16 recovered_ver; 252 int num_prot_group, rx_num_prot_group; 253 254 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 255 if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 256 return BCM_E_NONE; 257 } 258 259 num_prot_group = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) * 260 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 261 rx_num_prot_group = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 262 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 263 264 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0); 265 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr, 266 BCM_WB_DEFAULT_VERSION, &recovered_ver); 267 if (BCM_E_NOT_FOUND == rv) { 268 /* Upgrading from SDK release that does not have warmboot state */ 269 BCM_IF_ERROR_RETURN(_bcm_th2_failover_wb_alloc(unit)); 270 return BCM_E_NONE; 271 } else if (BCM_FAILURE(rv)) { 272 return rv; 273 } 274 275 ptr = scache_ptr; 276 277 sal_memcpy(BCM_FAILOVER_PROT_GROUP_MAP(unit), ptr, 278 SHR_BITALLOCSIZE(num_prot_group)); 279 ptr += SHR_BITALLOCSIZE(num_prot_group); 280 281 sal_memcpy(BCM_FAILOVER_INGRESS_PROT_GROUP_MAP(unit), ptr, 282 SHR_BITALLOCSIZE(rx_num_prot_group)); 283 ptr += SHR_BITALLOCSIZE(rx_num_prot_group); 284 285 return BCM_E_NONE; 286 } 287 288 289 #endif /* BCM_WARM_BOOT_SUPPORT */ 290 291 /* 292 * Function: 293 * bcm_th2_failover_init 294 * Purpose: 295 * Initialize the Failover software module 296 * Parameters: 297 * unit - Device Number 298 * Returns: 299 * BCM_E_XXX 300 */ 301 int 302 bcm_th2_failover_init (int unit) 303 { 304 int rv = BCM_E_NONE; 305 int num_prot_group, rx_num_prot_group; 306 _bcm_th2_failover_bookkeeping_t *failover_info = FAILOVER_INFO(unit); 307 308 /* 309 * allocate resources 310 */ 311 if (failover_info->initialized) { 312 BCM_IF_ERROR_RETURN(bcm_th2_failover_cleanup(unit)); 313 } 314 315 num_prot_group = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) 316 * BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 317 318 failover_info->prot_group_bitmap = 319 sal_alloc(SHR_BITALLOCSIZE(num_prot_group), "prot_group_bitmap"); 320 if (failover_info->prot_group_bitmap == NULL) { 321 _bcm_th2_failover_free_resource(unit, failover_info); 322 return BCM_E_MEMORY; 323 } 324 325 sal_memset(failover_info->prot_group_bitmap, 0, 326 SHR_BITALLOCSIZE(num_prot_group)); 327 328 329 rx_num_prot_group = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) 330 * BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 331 332 failover_info->ingress_prot_group_bitmap = 333 sal_alloc(SHR_BITALLOCSIZE(rx_num_prot_group), "ingress_prot_group_bitmap"); 334 if (failover_info->ingress_prot_group_bitmap == NULL) { 335 _bcm_th2_failover_free_resource(unit, failover_info); 336 return BCM_E_MEMORY; 337 } 338 339 sal_memset(failover_info->ingress_prot_group_bitmap, 0, 340 SHR_BITALLOCSIZE(rx_num_prot_group)); 341 342 /* Create Failover protection mutex. */ 343 failover_info->failover_mutex = sal_mutex_create("failover_mutex"); 344 if (!failover_info->failover_mutex) { 345 _bcm_th2_failover_free_resource(unit, failover_info); 346 return BCM_E_MEMORY; 347 } 348 349 #ifdef BCM_WARM_BOOT_SUPPORT 350 if(SOC_WARM_BOOT(unit)) { 351 rv = _bcm_th2_failover_reinit(unit); 352 if (BCM_FAILURE(rv)){ 353 _bcm_th2_failover_free_resource(unit, failover_info); 354 return rv; 355 } 356 } else { 357 rv = _bcm_th2_failover_wb_alloc(unit); 358 if (BCM_FAILURE(rv)) { 359 _bcm_th2_failover_free_resource(unit, failover_info); 360 return rv; 361 } 362 } 363 #endif /* BCM_WARM_BOOT_SUPPORT */ 364 /* Mark the state as initialized */ 365 failover_info->initialized = TRUE; 366 367 return rv; 368 } 369 370 /* 371 * Function: 372 * _bcm_th2_failover_hw_clear 373 * Purpose: 374 * Perform hw tables clean up for failover module. 375 * Parameters: 376 * unit - Device Number 377 * Returns: 378 * BCM_E_XXX 379 */ 380 STATIC int 381 _bcm_th2_failover_hw_clear (int unit) 382 { 383 int i, rv, rv_error = BCM_E_NONE; 384 int num_entry; 385 386 num_entry = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) * 387 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 388 389 /* Index-0 is reserved */ 390 for (i = 1; i < num_entry; i++) { 391 if (_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, i)) { 392 rv = bcm_th2_failover_destroy(unit, i); 393 if (rv < 0) { 394 rv_error = rv; 395 } 396 } 397 } 398 399 num_entry = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 400 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 401 402 /* Index-0 is reserved */ 403 for (i = 1; i < num_entry; i++) { 404 if (_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET(unit, i)) { 405 _BCM_ENCAP_TYPE_IN_FAILOVER_ID(i, _BCM_FAILOVER_INGRESS); 406 rv = bcm_th2_failover_destroy(unit, i); 407 if (rv < 0) { 408 rv_error = rv; 409 } 410 } 411 } 412 413 return rv_error; 414 } 415 416 /* 417 * Function: 418 * bcm_th2_failover_cleanup 419 * Purpose: 420 * DeInit the Failover software module 421 * Parameters: 422 * unit - Device Number 423 * Returns: 424 * BCM_E_XXX 425 */ 426 int 427 bcm_th2_failover_cleanup (int unit) 428 { 429 _bcm_th2_failover_bookkeeping_t *failover_info = FAILOVER_INFO(unit); 430 int rv = BCM_E_UNAVAIL; 431 432 if (FALSE == failover_info->initialized) { 433 return (BCM_E_NONE); 434 } 435 436 rv = bcm_th2_failover_lock(unit); 437 if (BCM_FAILURE(rv)) { 438 return rv; 439 } 440 441 if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 442 rv = _bcm_th2_failover_hw_clear(unit); 443 } 444 445 /* Free software resources */ 446 (void) _bcm_th2_failover_free_resource(unit, failover_info); 447 448 bcm_th2_failover_unlock(unit); 449 450 /* Destroy protection mutex. */ 451 sal_mutex_destroy(failover_info->failover_mutex); 452 453 /* Mark the state as uninitialized */ 454 failover_info->initialized = FALSE; 455 456 return rv; 457 } 458 459 460 /* 461 * Function: 462 * _bcm_th2_failover_get_prot_group_table_index 463 * Purpose: 464 * Obtain Index into INITIAL_PROT_GROUP_TABLE 465 * Parameters: 466 * IN : Unit 467 * OUT : prot_index 468 * Returns: 469 * BCM_E_XXX 470 */ 471 STATIC int 472 _bcm_th2_failover_get_prot_group_table_index (int unit, int *prot_index) 473 { 474 int i; 475 int num_entry; 476 477 num_entry = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) * 478 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 479 480 /* Index-0 is reserved */ 481 for (i = 1; i < num_entry; i++) { 482 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, i)) { 483 break; 484 } 485 } 486 487 if (i == num_entry) { 488 return BCM_E_RESOURCE; 489 } 490 _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, i); 491 *prot_index = i; 492 493 return BCM_E_NONE; 494 } 495 496 /* 497 * Function: 498 * _bcm_th2_failover_clear_prot_group_table_entry 499 * Purpose: 500 * Clear INITIAL_PROT_GROUP_TABLE entry pointed by Index 501 * Parameters: 502 * IN : Unit 503 * IN : prot_index 504 * Returns: 505 * BCM_E_XXX 506 */ 507 STATIC void 508 _bcm_th2_failover_clear_prot_group_table_entry (int unit, 509 bcm_failover_t prot_index) 510 { 511 _BCM_FAILOVER_PROT_GROUP_MAP_USED_CLR(unit, prot_index); 512 } 513 514 /* 515 * Function: 516 * _bcm_th2_failover_set_prot_group_table_entry 517 * Purpose: 518 * Set INITIAL_PROT_GROUP_TABLE entry pointed by Index 519 * Parameters: 520 * IN : Unit 521 * IN : prot_index 522 * Returns: 523 * BCM_E_XXX 524 */ 525 STATIC void 526 _bcm_th2_failover_set_prot_group_table_entry (int unit, 527 bcm_failover_t prot_index) 528 { 529 _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, prot_index); 530 } 531 532 /* 533 * Function: 534 * _bcm_th2_failover_id_validate 535 * Purpose: 536 * Validate the failover ID 537 * Parameters: 538 * IN : failover_id 539 * Returns: 540 * BCM_E_XXX 541 */ 542 STATIC int 543 _bcm_th2_failover_id_validate (int unit, bcm_failover_t failover_id) 544 { 545 int num_entry; 546 547 num_entry = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) * 548 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 549 550 if ((failover_id < 1) || (failover_id > num_entry)) { 551 return BCM_E_PARAM; 552 } else if (failover_id == num_entry) { 553 return BCM_E_RESOURCE; 554 } 555 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, failover_id)) { 556 return BCM_E_NOT_FOUND; 557 } 558 559 return BCM_E_NONE; 560 } 561 562 /* 563 * Function: 564 * _bcm_th2_failover_clear_ingress_prot_group_table_index 565 * Purpose: 566 * Clear RX_PROT_GROUP_TABLE entry pointed by Index 567 * Parameters: 568 * unit : (IN) Device Unit Number 569 * prot_index : (IN) RX_PROT_GROUP_TABLE bit index 570 * Returns: 571 * BCM_E_XXX 572 */ 573 STATIC void 574 _bcm_th2_failover_clear_ingress_prot_group_table_index( 575 int unit, bcm_failover_t prot_index) 576 { 577 _BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_CLR(unit, prot_index); 578 } 579 580 /* 581 * Function: 582 * _bcm_th2_failover_ingress_id_validate 583 * Purpose: 584 * Validate the ingress failover ID 585 * Parameters: 586 * unit : (IN) Device Unit Number 587 * failover_id : (IN) Ingress failover ID 588 * Returns: 589 * BCM_E_XXX 590 */ 591 int 592 _bcm_th2_failover_ingress_id_validate(int unit, 593 bcm_failover_t failover_id) 594 { 595 int num_entry; 596 597 num_entry = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 598 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 599 600 if ((failover_id < 1) || (failover_id >= num_entry)) { 601 return BCM_E_PARAM; 602 } 603 604 if (!_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET(unit, failover_id)) { 605 return BCM_E_NOT_FOUND; 606 } 607 608 return BCM_E_NONE; 609 } 610 611 /* 612 * Function: 613 * _bcm_th2_failover_get_ingress_prot_group_table_index 614 * Purpose: 615 * Obtain Index into RX_PROT_GROUP_TABLE 616 * Parameters: 617 * unit : (IN) Device Unit Number 618 * prot_index : (OUT) RX_PROT_GROUP_TABLE bit index 619 * Returns: 620 * BCM_E_XXX 621 */ 622 STATIC int 623 _bcm_th2_failover_get_ingress_prot_group_table_index(int unit, 624 int *prot_index) 625 { 626 int i; 627 int num_entry; 628 629 num_entry = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 630 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 631 632 /* Index-0 is reserved */ 633 for (i = 1; i < num_entry; i++) { 634 if (!_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET(unit, i)) { 635 break; 636 } 637 } 638 639 if (i == num_entry) { 640 return BCM_E_RESOURCE; 641 } 642 643 *prot_index = i; 644 return BCM_E_NONE; 645 } 646 647 648 /* 649 * Function: 650 * _bcm_th2_failover_set_ingress_prot_group_table_index 651 * Purpose: 652 * Set RX_PROT_GROUP_TABLE entry pointed by Index 653 * Parameters: 654 * unit : (IN) Device Unit Number 655 * prot_index : (IN) RX_PROT_GROUP_TABLE bit index 656 * Returns: 657 * BCM_E_XXX 658 */ 659 STATIC void 660 _bcm_th2_failover_set_ingress_prot_group_table_index(int unit, 661 bcm_failover_t prot_index) 662 { 663 _BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_SET(unit, prot_index); 664 } 665 666 667 /* 668 * Function: 669 * bcm_th2_failover_create 670 * Purpose: 671 * Create a failover object 672 * Parameters: 673 * IN : unit 674 * IN : flags 675 * OUT : failover_id 676 * Returns: 677 * BCM_E_XXX 678 */ 679 int 680 bcm_th2_failover_create (int unit, uint32 flags, bcm_failover_t *failover_id) 681 { 682 int rv = BCM_E_UNAVAIL; 683 tx_initial_prot_group_table_entry_t tx_init_prot_group_entry; 684 rx_prot_group_table_entry_t rx_prot_group_entry; 685 int num_entry,local_failover_id; 686 int failover_type; 687 uint32 table_index; 688 uint32 bit_index; 689 uint32 buf[4]; 690 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 691 uint32 replace_enable_field = REPLACE_ENABLE_BITMAPf; 692 void *prot_group_entry = &tx_init_prot_group_entry; 693 694 if (failover_id == NULL) { 695 return BCM_E_PARAM; 696 } 697 698 /* Check for unsupported Flag */ 699 if (flags & (~(BCM_FAILOVER_REPLACE | 700 BCM_FAILOVER_WITH_ID | 701 BCM_FAILOVER_INGRESS))) { 702 return BCM_E_PARAM; 703 } 704 705 if ((flags & BCM_FAILOVER_WITH_ID) || (flags & BCM_FAILOVER_REPLACE)) { 706 707 if (flags & BCM_FAILOVER_INGRESS) { 708 local_failover_id = *failover_id; 709 710 /* Allow failoverIds of type _BCM_FAILOVER_INGRESS */ 711 _BCM_GET_FAILOVER_TYPE(local_failover_id, failover_type); 712 if (!(failover_type & _BCM_FAILOVER_INGRESS)) { 713 return BCM_E_PARAM; 714 } 715 716 _BCM_GET_FAILOVER_ID(local_failover_id); 717 /* make sure the given id is valid */ 718 num_entry = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) * 719 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 720 if ((local_failover_id < 1) || (local_failover_id >= num_entry)) { 721 return BCM_E_PARAM; 722 } 723 724 if (flags & BCM_FAILOVER_WITH_ID) { 725 if (_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET( 726 unit, local_failover_id)) { 727 return BCM_E_EXISTS; 728 } else { 729 _BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_SET( 730 unit, local_failover_id); 731 } 732 } 733 734 if (flags & BCM_FAILOVER_REPLACE) { 735 if (!_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET( 736 unit, local_failover_id)) { 737 return BCM_E_NOT_FOUND; 738 } 739 } 740 } else { 741 /* make sure the given id is valid */ 742 num_entry = (soc_mem_index_count(unit, prot_group_mem) * 743 BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY); 744 if ((*failover_id < 1) || (*failover_id >= num_entry)) { 745 return BCM_E_PARAM; 746 } 747 if (flags & BCM_FAILOVER_WITH_ID) { 748 if (_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, *failover_id)) { 749 return BCM_E_EXISTS; 750 } else { 751 _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, *failover_id); 752 } 753 } 754 if (flags & BCM_FAILOVER_REPLACE) { 755 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, *failover_id)) { 756 return BCM_E_NOT_FOUND; 757 } 758 } 759 } 760 rv = BCM_E_NONE; 761 } else if (!flags) { 762 /* Get Index */ 763 rv = _bcm_th2_failover_get_prot_group_table_index(unit, failover_id); 764 } else if (flags & BCM_FAILOVER_INGRESS) { 765 rv = _bcm_th2_failover_get_ingress_prot_group_table_index(unit, 766 failover_id); 767 _BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_SET(unit, *failover_id); 768 _BCM_ENCAP_TYPE_IN_FAILOVER_ID(*failover_id, _BCM_FAILOVER_INGRESS); 769 } 770 if (BCM_SUCCESS(rv)) { 771 if (flags & BCM_FAILOVER_INGRESS) { 772 local_failover_id = *failover_id; 773 _BCM_GET_FAILOVER_ID(local_failover_id); 774 table_index = ((local_failover_id >> 7) & 775 (soc_mem_index_count(unit,RX_PROT_GROUP_TABLEm) - 1)); 776 bit_index = (local_failover_id & 0x7F); 777 BCM_IF_ERROR_RETURN ( 778 soc_mem_read(unit, RX_PROT_GROUP_TABLEm, MEM_BLOCK_ANY, 779 table_index, &rx_prot_group_entry)); 780 sal_memcpy(buf, &rx_prot_group_entry, sizeof(buf)); 781 782 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 783 784 soc_mem_field_set(unit, RX_PROT_GROUP_TABLEm, 785 (uint32 *)&rx_prot_group_entry, 786 DROP_DATA_ENABLE_BITMAPf, buf); 787 788 rv = soc_mem_write(unit, RX_PROT_GROUP_TABLEm, MEM_BLOCK_ALL, 789 table_index, &rx_prot_group_entry); 790 if (rv < 0) { 791 _bcm_th2_failover_clear_ingress_prot_group_table_index( 792 unit, local_failover_id); 793 return rv; 794 } 795 } else { 796 local_failover_id = *failover_id; 797 _BCM_GET_FAILOVER_ID(*failover_id); 798 /* Init table entry */ 799 table_index = ((*failover_id >> 7) & 800 (soc_mem_index_count(unit,prot_group_mem) - 1)); 801 bit_index = (*failover_id & 0x7F); 802 BCM_IF_ERROR_RETURN (soc_mem_read(unit, prot_group_mem, 803 MEM_BLOCK_ANY, table_index, prot_group_entry)); 804 sal_memcpy(buf, prot_group_entry, sizeof(buf)); 805 806 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 807 808 soc_mem_field_set(unit, prot_group_mem, 809 (uint32 *)prot_group_entry, replace_enable_field, buf); 810 811 rv = soc_mem_write(unit, prot_group_mem, 812 MEM_BLOCK_ALL, table_index, prot_group_entry); 813 if (rv < 0) { 814 _bcm_th2_failover_clear_prot_group_table_entry(unit, *failover_id); 815 return BCM_E_RESOURCE; 816 } 817 *failover_id = local_failover_id; 818 } 819 } 820 821 return rv; 822 } 823 824 825 /* 826 * Function: 827 * bcm_th2_failover_destroy 828 * Purpose: 829 * Destroy a failover object 830 * Parameters: 831 * IN : unit 832 * IN : failover_id 833 * Returns: 834 * BCM_E_XXX 835 */ 836 int 837 bcm_th2_failover_destroy (int unit, bcm_failover_t failover_id) 838 { 839 int rv = BCM_E_UNAVAIL; 840 int type = _BCM_FAILOVER_DEFAULT_MODE; 841 int local_failover_id=0; 842 tx_initial_prot_group_table_entry_t tx_init_prot_group_entry; 843 rx_prot_group_table_entry_t rx_prot_group_entry; 844 uint32 table_index; 845 uint32 bit_index; 846 uint32 buf[4]; 847 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 848 uint32 replace_enable_field = REPLACE_ENABLE_BITMAPf; 849 void *prot_group_entry = &tx_init_prot_group_entry; 850 851 /*Check failover id type Ingress or Egress Encap*/ 852 _BCM_GET_FAILOVER_TYPE(failover_id, type); 853 if (type & _BCM_FAILOVER_INGRESS) { 854 local_failover_id = failover_id; 855 _BCM_GET_FAILOVER_ID(local_failover_id); 856 857 rv = _bcm_th2_failover_ingress_id_validate(unit, local_failover_id); 858 BCM_IF_ERROR_RETURN(rv); 859 860 /*Release software index*/ 861 _bcm_th2_failover_clear_ingress_prot_group_table_index( 862 unit, local_failover_id); 863 /*clear hw entry*/ 864 table_index = ((local_failover_id >> 7) & 865 (soc_mem_index_count(unit,RX_PROT_GROUP_TABLEm) - 1)); 866 bit_index = (local_failover_id & 0x7F); 867 BCM_IF_ERROR_RETURN ( 868 soc_mem_read(unit, RX_PROT_GROUP_TABLEm, 869 MEM_BLOCK_ANY, table_index, &rx_prot_group_entry)); 870 871 sal_memcpy(buf, &rx_prot_group_entry, sizeof(buf)); 872 873 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 874 soc_mem_field_set(unit, RX_PROT_GROUP_TABLEm, 875 (uint32 *)&rx_prot_group_entry, 876 DROP_DATA_ENABLE_BITMAPf, buf); 877 878 rv = soc_mem_write(unit, RX_PROT_GROUP_TABLEm, MEM_BLOCK_ALL, 879 table_index, &rx_prot_group_entry); 880 if (rv < 0) { 881 _bcm_th2_failover_set_ingress_prot_group_table_index( 882 unit, local_failover_id); 883 return rv; 884 } 885 } else { 886 rv = _bcm_th2_failover_id_validate(unit, failover_id); 887 BCM_IF_ERROR_RETURN(rv); 888 889 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, failover_id)) { 890 return BCM_E_NOT_FOUND; 891 } 892 893 /*Release index*/ 894 _bcm_th2_failover_clear_prot_group_table_entry(unit, failover_id); 895 896 /* Clear entry */ 897 table_index = ((failover_id >> 7) & 898 (soc_mem_index_count(unit,prot_group_mem) - 1)); 899 bit_index = (failover_id & 0x7F); 900 BCM_IF_ERROR_RETURN (soc_mem_read(unit, prot_group_mem, 901 MEM_BLOCK_ANY, table_index, prot_group_entry)); 902 903 sal_memcpy(buf, prot_group_entry, sizeof(buf)); 904 905 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 906 soc_mem_field_set(unit, prot_group_mem, 907 (uint32 *)prot_group_entry, replace_enable_field, buf); 908 909 rv = soc_mem_write(unit, prot_group_mem, MEM_BLOCK_ALL, 910 table_index, prot_group_entry); 911 if (rv < 0) { 912 _bcm_th2_failover_set_prot_group_table_entry(unit, failover_id); 913 return BCM_E_RESOURCE; 914 } 915 } 916 917 return rv; 918 } 919 920 921 STATIC int 922 _bcm_th2_failover_nhi_get(int unit, bcm_gport_t port, int *nh_index) 923 { 924 int vp=0xFFFF; 925 ing_dvp_table_entry_t dvp; 926 927 if (!BCM_GPORT_IS_MPLS_PORT(port) && 928 !BCM_GPORT_IS_MIM_PORT(port) ) { 929 return BCM_E_PARAM; 930 } 931 932 if ( BCM_GPORT_IS_MPLS_PORT(port)) { 933 vp = BCM_GPORT_MPLS_PORT_ID_GET(port); 934 } else if ( BCM_GPORT_IS_MIM_PORT(port)) { 935 vp = BCM_GPORT_MIM_PORT_ID_GET(port); 936 } 937 938 if (vp >= soc_mem_index_count(unit, SOURCE_VPm)) { 939 return BCM_E_PARAM; 940 } 941 BCM_IF_ERROR_RETURN (READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp)); 942 943 /* Next-hop index is used for multicast replication */ 944 *nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, NEXT_HOP_INDEXf); 945 return BCM_E_NONE; 946 } 947 948 /* 949 * Function: 950 * bcm_th2_failover_status_set 951 * Purpose: 952 * Set the parameters for a failover object 953 * Parameters: 954 * IN : unit 955 * IN : failover_id 956 * IN : value 957 * Returns: 958 * BCM_E_XXX 959 */ 960 int 961 bcm_th2_failover_status_set (int unit, 962 bcm_failover_element_t *failover, 963 int value) 964 { 965 int rv = BCM_E_UNAVAIL; 966 int nh_index; 967 int local_failover_id=0; 968 uint32 table_index = 0; 969 uint32 bit_index = 0; 970 uint32 buf[4]; 971 tx_initial_prot_group_table_entry_t tx_init_prot_group_entry; 972 rx_prot_group_table_entry_t rx_prot_group_entry; 973 initial_prot_nhi_table_1_entry_t prot_nhi_1_entry; 974 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 975 uint32 replace_enable_field = REPLACE_ENABLE_BITMAPf; 976 void *prot_group_entry = &tx_init_prot_group_entry; 977 978 if ((value < 0) || (value > 1)) { 979 return BCM_E_PARAM; 980 } 981 982 if (failover->failover_id != BCM_FAILOVER_INVALID) { 983 if (failover->flags == BCM_FAILOVER_INGRESS) { 984 /* RX prot group table*/ 985 local_failover_id = failover->failover_id; 986 _BCM_GET_FAILOVER_ID(local_failover_id); 987 BCM_IF_ERROR_RETURN( 988 _bcm_th2_failover_ingress_id_validate(unit, local_failover_id)); 989 990 table_index = ((local_failover_id >> 7) & 991 (soc_mem_index_count(unit,RX_PROT_GROUP_TABLEm) - 1)); 992 bit_index = (local_failover_id & 0x7F); 993 994 BCM_IF_ERROR_RETURN( 995 soc_mem_read(unit, RX_PROT_GROUP_TABLEm, 996 MEM_BLOCK_ANY, table_index, &rx_prot_group_entry)); 997 998 sal_memcpy(buf, &rx_prot_group_entry, sizeof(buf)); 999 if (value == 0) { 1000 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1001 } else { 1002 buf[bit_index / 32] |= (0x1 << (bit_index % 32)); 1003 } 1004 1005 soc_mem_field_set(unit, RX_PROT_GROUP_TABLEm, 1006 (uint32 *)&rx_prot_group_entry, 1007 DROP_DATA_ENABLE_BITMAPf, buf); 1008 1009 rv = soc_mem_write(unit, RX_PROT_GROUP_TABLEm, MEM_BLOCK_ALL, 1010 table_index, &rx_prot_group_entry); 1011 } else { 1012 local_failover_id = failover->failover_id; 1013 _BCM_GET_FAILOVER_ID(local_failover_id); 1014 1015 /* Group protection for Port and Tunnel: Egress and Ingress */ 1016 table_index = ((local_failover_id >> 7) & 1017 (soc_mem_index_count(unit,prot_group_mem) - 1)); 1018 bit_index = (local_failover_id & 0x7F); 1019 1020 BCM_IF_ERROR_RETURN( 1021 _bcm_th2_failover_id_validate(unit, local_failover_id)); 1022 1023 BCM_IF_ERROR_RETURN (soc_mem_read(unit, prot_group_mem, 1024 MEM_BLOCK_ANY, table_index, prot_group_entry)); 1025 1026 sal_memcpy(buf, prot_group_entry, sizeof(buf)); 1027 if (value == 0) { 1028 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1029 } else { 1030 buf[bit_index / 32] |= (0x1 << (bit_index % 32)); 1031 } 1032 1033 soc_mem_field_set(unit, prot_group_mem, 1034 (uint32 *)prot_group_entry, replace_enable_field, buf); 1035 1036 rv = soc_mem_write(unit, prot_group_mem, 1037 MEM_BLOCK_ALL, table_index, prot_group_entry); 1038 } 1039 1040 } else if (failover->intf != BCM_IF_INVALID) { 1041 /* Only Egress is applicable */ 1042 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, failover->intf)) { 1043 nh_index = failover->intf - BCM_XGS3_EGRESS_IDX_MIN(unit); 1044 } else { 1045 nh_index = failover->intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 1046 } 1047 1048 table_index = ((nh_index >> 7) & 0x1FF); 1049 bit_index = (nh_index & 0x7F); 1050 1051 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLE_1m, 1052 MEM_BLOCK_ANY, table_index, &prot_nhi_1_entry)); 1053 1054 sal_memcpy(buf, &prot_nhi_1_entry, sizeof(buf)); 1055 if (value == 0) { 1056 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1057 } else { 1058 buf[bit_index / 32] |= (0x1 << (bit_index % 32)); 1059 } 1060 1061 soc_mem_field_set(unit, INITIAL_PROT_NHI_TABLE_1m, 1062 (uint32 *)&prot_nhi_1_entry, REPLACE_ENABLE_BITMAPf, buf); 1063 1064 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLE_1m, 1065 MEM_BLOCK_ALL, table_index, &prot_nhi_1_entry); 1066 if (rv < 0) { 1067 return rv; 1068 } 1069 } else if (failover->port != BCM_GPORT_INVALID) { 1070 /* Individual protection for Pseudo-wire: Egress and Ingress */ 1071 BCM_IF_ERROR_RETURN ( 1072 _bcm_th2_failover_nhi_get(unit, failover->port , &nh_index)); 1073 1074 table_index = ((nh_index >> 7) & 0x1FF); 1075 bit_index = (nh_index & 0x7F); 1076 1077 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLE_1m, 1078 MEM_BLOCK_ANY, table_index, &prot_nhi_1_entry)); 1079 1080 sal_memcpy(buf, &prot_nhi_1_entry, sizeof(buf)); 1081 if (value == 0) { 1082 buf[bit_index / 32] &= ~(0x1 << (bit_index % 32)); 1083 } else { 1084 buf[bit_index / 32] |= (0x1 << (bit_index % 32)); 1085 } 1086 1087 soc_mem_field_set(unit, INITIAL_PROT_NHI_TABLE_1m, 1088 (uint32 *)&prot_nhi_1_entry, REPLACE_ENABLE_BITMAPf, buf); 1089 1090 rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLE_1m, 1091 MEM_BLOCK_ALL, table_index, &prot_nhi_1_entry); 1092 1093 } 1094 return rv; 1095 } 1096 1097 1098 1099 /* 1100 * Function: 1101 * bcm_th2_failover_status_get 1102 * Purpose: 1103 * Get the parameters for a failover object 1104 * Parameters: 1105 * IN : unit 1106 * IN : failover_id 1107 * OUT : value 1108 * Returns: 1109 * BCM_E_XXX 1110 */ 1111 int 1112 bcm_th2_failover_status_get (int unit, 1113 bcm_failover_element_t *failover, 1114 int *value) 1115 { 1116 tx_initial_prot_group_table_entry_t tx_init_prot_group_entry; 1117 rx_prot_group_table_entry_t rx_prot_group_entry; 1118 initial_prot_nhi_table_1_entry_t prot_nhi_1_entry; 1119 int nh_index; 1120 int local_failover_id=0; 1121 uint32 table_index = 0; 1122 uint32 bit_index = 0; 1123 uint32 buf[4]; 1124 uint32 prot_group_mem = TX_INITIAL_PROT_GROUP_TABLEm; 1125 uint32 replace_enable_field = REPLACE_ENABLE_BITMAPf; 1126 void *prot_group_entry = &tx_init_prot_group_entry; 1127 1128 if (failover->failover_id != BCM_FAILOVER_INVALID) { 1129 if (failover->flags == BCM_FAILOVER_INGRESS) { 1130 local_failover_id = failover->failover_id; 1131 _BCM_GET_FAILOVER_ID(local_failover_id); 1132 BCM_IF_ERROR_RETURN( 1133 _bcm_th2_failover_ingress_id_validate(unit, local_failover_id)); 1134 1135 table_index = ((local_failover_id >> 7) & 1136 (soc_mem_index_count(unit,RX_PROT_GROUP_TABLEm) - 1)); 1137 bit_index = (local_failover_id & 0x7F); 1138 1139 BCM_IF_ERROR_RETURN ( 1140 soc_mem_read(unit, RX_PROT_GROUP_TABLEm, 1141 MEM_BLOCK_ANY, table_index, &rx_prot_group_entry)); 1142 1143 soc_mem_field_get(unit, RX_PROT_GROUP_TABLEm, 1144 (uint32 *)&rx_prot_group_entry, 1145 DROP_DATA_ENABLE_BITMAPf, buf); 1146 *value = ((buf[bit_index / 32] >> (bit_index % 32)) & 0x1); 1147 } else { 1148 local_failover_id = failover->failover_id; 1149 _BCM_GET_FAILOVER_ID(local_failover_id); 1150 1151 BCM_IF_ERROR_RETURN( 1152 _bcm_th2_failover_id_validate(unit, local_failover_id)); 1153 1154 table_index = ((local_failover_id >> 7) & 1155 (soc_mem_index_count(unit,prot_group_mem) - 1)); 1156 bit_index = (local_failover_id & 0x7F); 1157 1158 BCM_IF_ERROR_RETURN (soc_mem_read(unit, prot_group_mem, 1159 MEM_BLOCK_ANY, table_index, prot_group_entry)); 1160 1161 soc_mem_field_get(unit, prot_group_mem, 1162 (uint32 *)prot_group_entry, replace_enable_field, buf); 1163 *value = ((buf[bit_index / 32] >> (bit_index % 32)) & 0x1); 1164 1165 } 1166 } else if (failover->intf != BCM_IF_INVALID) { 1167 1168 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, failover->intf)) { 1169 nh_index = failover->intf - BCM_XGS3_EGRESS_IDX_MIN(unit); 1170 } else { 1171 nh_index = failover->intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 1172 } 1173 1174 table_index = ((nh_index >> 7) & 0x1FF); 1175 bit_index = (nh_index & 0x7F); 1176 1177 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLE_1m, 1178 MEM_BLOCK_ANY, table_index, &prot_nhi_1_entry)); 1179 1180 soc_mem_field_get(unit, INITIAL_PROT_NHI_TABLE_1m, 1181 (uint32 *)&prot_nhi_1_entry, REPLACE_ENABLE_BITMAPf, buf); 1182 1183 *value = ((buf[bit_index / 32] >> (bit_index % 32)) & 0x1); 1184 1185 } else if (failover->port != BCM_GPORT_INVALID) { 1186 1187 BCM_IF_ERROR_RETURN ( 1188 _bcm_th2_failover_nhi_get(unit, failover->port , &nh_index)); 1189 1190 table_index = ((nh_index >> 7) & 0x1FF); 1191 bit_index = (nh_index & 0x7F); 1192 1193 BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLE_1m, 1194 MEM_BLOCK_ANY, table_index, &prot_nhi_1_entry)); 1195 1196 soc_mem_field_get(unit, INITIAL_PROT_NHI_TABLE_1m, 1197 (uint32 *)&prot_nhi_1_entry, REPLACE_ENABLE_BITMAPf, buf); 1198 1199 *value = ((buf[bit_index / 32] >> (bit_index % 32)) & 0x1); 1200 } 1201 return BCM_E_NONE; 1202 } 1203 1204 1205 #endif /* defined(BCM_TOMAHAWK2_SUPPORT) */ 1206 #endif /* defined(INCLUDE_L3) */