openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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) */