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 (56138B)


      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  * TR2 failover API
      8  */
      9 
     10 #include <soc/defs.h>
     11 #include <sal/core/libc.h>
     12 #include <shared/bsl.h>
     13 #if defined(BCM_TRIUMPH2_SUPPORT) &&  defined(INCLUDE_L3)
     14 
     15 #include <soc/drv.h>
     16 #include <soc/mem.h>
     17 #include <soc/util.h>
     18 #include <soc/debug.h>
     19 #include <bcm/types.h>
     20 #include <bcm/error.h>
     21 #include <bcm_int/esw/mbcm.h>
     22 #include <bcm_int/esw_dispatch.h>
     23 #include <bcm_int/esw/field.h>
     24 #include <bcm_int/esw/firebolt.h>
     25 #include <bcm_int/esw/triumph2.h>
     26 #include <bcm_int/esw/failover.h>
     27 #include <bcm/failover.h>
     28 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
     29 #include <bcm_int/esw/trident2plus.h>
     30 #endif
     31 #if defined(BCM_SABER2_SUPPORT)
     32 #include <bcm_int/esw/saber2.h>
     33 #endif
     34 #if defined(BCM_TOMAHAWK2_SUPPORT)
     35 #include <bcm_int/esw/tomahawk2.h>
     36 #endif
     37 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
     38 #include <soc/esw/ecmp.h>
     39 #endif /*  SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
     40 #ifdef BCM_WARM_BOOT_SUPPORT
     41 #include <bcm_int/esw/switch.h>
     42 #include <soc/scache.h>
     43 #endif /* BCM_WARM_BOOT_SUPPORT */
     44 
     45 /*
     46  * Function:
     47  *      _bcm_failover_check_init
     48  * Purpose:
     49  *      Check if Failover is initialized
     50  * Parameters:
     51  *      unit     - Device Number
     52  * Returns:
     53  *      BCM_E_XXX
     54  */
     55 
     56 
     57 STATIC int 
     58 _bcm_failover_check_init (int unit)
     59 {
     60         if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) {
     61             return BCM_E_UNIT;
     62         }
     63 
     64         if (!_bcm_failover_bk_info[unit].initialized) { 
     65             return BCM_E_INIT;
     66         } else {
     67              return BCM_E_NONE;
     68         }
     69 }
     70 
     71 
     72 
     73 /*
     74  * Function:
     75  *      bcm_failover_lock
     76  * Purpose:
     77  *      Take the Failover Lock Sempahore
     78  * Parameters:
     79  *      unit     - Device Number
     80  * Returns:
     81  *      BCM_E_XXX
     82  */
     83 
     84 
     85  int 
     86  bcm_tr2_failover_lock (int unit)
     87 {
     88    int rv;
     89 
     90    rv = _bcm_failover_check_init (unit);
     91    
     92    if ( rv == BCM_E_NONE ) {
     93            sal_mutex_take(FAILOVER_INFO((unit))->failover_mutex, sal_mutex_FOREVER);
     94    }
     95    return rv; 
     96 }
     97 
     98 
     99 
    100 /*
    101  * Function:
    102  *      bcm_failover_unlock
    103  * Purpose:
    104  *      Release  the Failover Lock Semaphore
    105  * Parameters:
    106  *      unit     - Device Number
    107  * Returns:
    108  *      BCM_E_XXX
    109  */
    110 
    111 
    112 void
    113 bcm_tr2_failover_unlock(int unit)
    114 {
    115     int rv;
    116 
    117     rv = _bcm_failover_check_init (unit);
    118 
    119     if ( rv == BCM_E_NONE ) {
    120         sal_mutex_give(FAILOVER_INFO((unit))->failover_mutex);
    121     }
    122 }
    123 
    124 
    125 
    126 /*
    127  * Function:
    128  *      _bcm_tr2_failover_free_resource
    129  * Purpose:
    130  *      Free all allocated software resources 
    131  * Parameters:
    132  *      unit - SOC unit number
    133  * Returns:
    134  *      Nothing
    135  */
    136 
    137 
    138 STATIC void
    139 _bcm_tr2_failover_free_resource(int unit, _bcm_failover_bookkeeping_t *failover_info)
    140 {
    141 
    142     if (!failover_info) {
    143          return;
    144     }
    145 
    146     if (failover_info->prot_group_bitmap) {
    147         sal_free(failover_info->prot_group_bitmap);
    148         failover_info->prot_group_bitmap = NULL;
    149     }
    150 
    151     if (failover_info->prot_nhi_bitmap) {
    152         sal_free(failover_info->prot_nhi_bitmap);
    153         failover_info->prot_nhi_bitmap = NULL;
    154     }
    155 
    156     if (failover_info->mmu_prot_group_bitmap) {
    157         sal_free(failover_info->mmu_prot_group_bitmap);
    158         failover_info->mmu_prot_group_bitmap = NULL;
    159     }
    160 
    161 }
    162 
    163 #ifdef BCM_WARM_BOOT_SUPPORT
    164 
    165 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    166 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
    167 
    168 
    169 /*
    170  * Function:
    171  *     _bcm_tr2_failover_alloc
    172  * Purpose:
    173  *     Alloc scache for warm boot.
    174  * Parameters:
    175  *      unit    : (IN) Device Unit Number
    176  * Returns:
    177  *      BCM_E_XXX
    178  */
    179 STATIC int
    180 _bcm_tr2_failover_alloc(int unit)
    181 {
    182     soc_scache_handle_t scache_handle;
    183     uint8 *scache_ptr;
    184     int rv, alloc_size, prot_grp_idx_count;
    185 
    186     prot_grp_idx_count = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
    187     alloc_size = SHR_BITALLOCSIZE(prot_grp_idx_count);
    188     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0);
    189     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
    190                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
    191     if (rv == BCM_E_NOT_FOUND) {
    192         rv = BCM_E_NONE;
    193     }
    194 
    195     return rv;
    196 }
    197 
    198 
    199 /*
    200  * Function:
    201  *     bcm_tr2_failover_sync
    202  * Purpose:
    203  *     Sync scache for warm boot.
    204  * Parameters:
    205  *      unit    : (IN) Device Unit Number
    206  * Returns:
    207  *      BCM_E_XXX
    208  */
    209 int
    210 bcm_tr2_failover_sync(int unit)
    211 {
    212     soc_scache_handle_t scache_handle;
    213     uint8 *scache_ptr, *ptr;
    214     int prot_grp_idx_count;
    215     int rv;
    216 
    217     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0);
    218     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
    219                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
    220     if (BCM_FAILURE(rv)) {
    221         if (rv == BCM_E_NOT_FOUND) {
    222             return BCM_E_NONE;
    223         }
    224         return rv;
    225     }
    226 
    227     ptr = scache_ptr;
    228     prot_grp_idx_count = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
    229 
    230     /* Sync PROT_GROUP_MAP */
    231     sal_memcpy(ptr, BCM_FAILOVER_PROT_GROUP_MAP(unit),
    232                SHR_BITALLOCSIZE(prot_grp_idx_count));
    233     ptr += SHR_BITALLOCSIZE(prot_grp_idx_count);
    234 
    235     return BCM_E_NONE;
    236 }
    237 
    238 
    239 /*
    240  * Function:
    241  *     _bcm_tr2_failover_prot_nhi_recover
    242  * Purpose:
    243  *     PROT_NHI_MAP recover for warm boot.
    244  * Parameters:
    245  *      unit    : (IN) Device Unit Number
    246  * Returns:
    247  *      BCM_E_XXX
    248  */
    249 STATIC int
    250 _bcm_tr2_failover_prot_nhi_recover(int unit)
    251 {
    252     int idx, index_min, index_max, prot_grp_idx, grp_idx_max;
    253     initial_prot_nhi_table_entry_t prot_nhi_entry;
    254     soc_field_t fld;
    255     soc_field_t fld_grp;
    256 
    257     grp_idx_max = soc_mem_index_max(unit, INITIAL_PROT_GROUP_TABLEm);
    258 
    259     index_min = soc_mem_index_min(unit, INITIAL_PROT_NHI_TABLEm);
    260     index_max = soc_mem_index_max(unit, INITIAL_PROT_NHI_TABLEm);
    261     if (SOC_IS_KATANA2(unit) || SOC_IS_TRIUMPH3(unit)) {
    262         fld = REPLACEMENT_DATAf;
    263     } else {
    264         fld = PROT_NEXT_HOP_INDEXf;
    265     }
    266     fld_grp = PROT_GROUPf;
    267 
    268     for (idx = index_min; idx <= index_max; idx++) {
    269         SOC_IF_ERROR_RETURN(soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, MEM_BLOCK_ANY,
    270                                           idx, &prot_nhi_entry));
    271         prot_grp_idx = soc_INITIAL_PROT_NHI_TABLEm_field32_get(unit, &prot_nhi_entry, fld_grp);
    272         if ( (prot_grp_idx >= 1) && (prot_grp_idx <= grp_idx_max) &&
    273              (soc_INITIAL_PROT_NHI_TABLEm_field32_get(unit, &prot_nhi_entry,
    274                                                       fld) != 0) ) {
    275             _BCM_FAILOVER_PROT_NHI_MAP_USED_SET(unit, idx);
    276         }
    277     }
    278 
    279     return BCM_E_NONE;
    280 }
    281 
    282 
    283 /*
    284  * Function:
    285  *     _bcm_tr2_failover_recovery
    286  * Purpose:
    287  *     Scache recovery for warm boot.
    288  * Parameters:
    289  *      unit    : (IN) Device Unit Number
    290  * Returns:
    291  *      BCM_E_XXX
    292  */
    293 STATIC int
    294 _bcm_tr2_failover_recovery(int unit)
    295 {
    296     soc_scache_handle_t scache_handle;
    297     uint8 *scache_ptr, *ptr;
    298     int rv, prot_grp_idx_count;
    299     uint16 recovered_ver;
    300 
    301     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FAILOVER, 0);
    302     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
    303                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, &recovered_ver);
    304 
    305     if (BCM_E_NOT_FOUND == rv) {
    306         /* Upgrading from SDK release that does not have warmboot state,
    307            Alloc scache for now on */
    308         rv = _bcm_tr2_failover_alloc(unit);
    309         if (BCM_FAILURE(rv)) {
    310             return rv;
    311         }
    312         return BCM_E_NOT_FOUND;
    313     } else if (BCM_FAILURE(rv)) {
    314         return rv;
    315     }
    316 
    317     /* SCACHE Hande found, recover from SCAHE */
    318     prot_grp_idx_count = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
    319     ptr = scache_ptr;
    320 
    321     /* Recover PROT_GROUP_MAP */
    322     sal_memcpy(BCM_FAILOVER_PROT_GROUP_MAP(unit), ptr,
    323                SHR_BITALLOCSIZE(prot_grp_idx_count));
    324     ptr += SHR_BITALLOCSIZE(prot_grp_idx_count);
    325 
    326     /* Recover PROT_NHI_MAP */
    327     BCM_IF_ERROR_RETURN(_bcm_tr2_failover_prot_nhi_recover(unit));
    328 
    329     return BCM_E_NONE;
    330 }
    331 
    332 
    333 /* 
    334  * Function:
    335  *     _bcm_tr2_failover_reinit
    336  * Purpose:
    337  *     Reinit for warm boot.
    338  * Parameters:
    339  *      unit    : (IN) Device Unit Number
    340  * Returns:
    341  *      BCM_E_XXX
    342  */
    343 STATIC int
    344 _bcm_tr2_failover_reinit(int unit)
    345 {
    346     int idx, index_min, index_max, prot_grp_idx, grp_idx_max;
    347     initial_prot_nhi_table_entry_t prot_nhi_entry;
    348     soc_field_t fld;
    349     soc_field_t fld_grp;
    350     int rv;
    351 
    352     if (SOC_IS_TRIUMPH3(unit)) {
    353         /* Try SCACHE Recovery first */
    354         rv = _bcm_tr2_failover_recovery(unit);
    355 
    356         if BCM_SUCCESS(rv) {
    357             /* WB recovery successfull, return */
    358             return (rv);
    359         }
    360 
    361         if ( (BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) {
    362             /* Something failed in WB recovery, return error code */
    363             return (rv);
    364         }
    365 
    366         /* If we are here => (rv == BCM_E_NOT_FOUND), Resort to H/w recovery */
    367     }
    368 
    369     grp_idx_max = soc_mem_index_max(unit, INITIAL_PROT_GROUP_TABLEm);
    370 
    371     index_min = soc_mem_index_min(unit, INITIAL_PROT_NHI_TABLEm);
    372     index_max = soc_mem_index_max(unit, INITIAL_PROT_NHI_TABLEm);
    373     if (SOC_IS_KATANA2(unit) || SOC_IS_TRIUMPH3(unit)) {
    374         fld = REPLACEMENT_DATAf;
    375     } else {
    376         fld = PROT_NEXT_HOP_INDEXf; 
    377     }
    378     fld_grp = PROT_GROUPf;
    379      
    380     for (idx = index_min; idx <= index_max; idx++) {
    381         SOC_IF_ERROR_RETURN(soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, MEM_BLOCK_ANY,
    382                                           idx, &prot_nhi_entry));
    383         prot_grp_idx = soc_INITIAL_PROT_NHI_TABLEm_field32_get(unit, &prot_nhi_entry, fld_grp);
    384         if ( (prot_grp_idx >= 1) && (prot_grp_idx <= grp_idx_max) &&
    385              (soc_INITIAL_PROT_NHI_TABLEm_field32_get(unit, &prot_nhi_entry,
    386                                                       fld) != 0) ) {
    387             _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, prot_grp_idx);
    388             _BCM_FAILOVER_PROT_NHI_MAP_USED_SET(unit, idx);
    389         }
    390     }
    391     return BCM_E_NONE;
    392 }
    393 #endif /* BCM_WARM_BOOT_SUPPORT */
    394 
    395 
    396 /*
    397  * Function:
    398  *      bcm_tr2_failover_init
    399  * Purpose:
    400  *      Initialize the Failover software module
    401  * Parameters:
    402  *      unit     - Device Number
    403  * Returns:
    404  *      BCM_E_XXX
    405  */
    406 
    407 
    408 int
    409 bcm_tr2_failover_init(int unit)
    410 {
    411     int rv = BCM_E_NONE;
    412     int num_prot_group, num_prot_nhi;
    413 #if defined(BCM_SABER2_SUPPORT)
    414     int mmu_num_prot_group;
    415 #endif
    416     _bcm_failover_bookkeeping_t *failover_info = FAILOVER_INFO(unit);
    417 
    418      /*
    419       * allocate resources
    420       */
    421      if (failover_info->initialized) {
    422           BCM_IF_ERROR_RETURN(bcm_tr2_failover_cleanup(unit));
    423      }
    424 
    425      num_prot_group = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
    426      num_prot_nhi = soc_mem_index_count(unit, INITIAL_PROT_NHI_TABLEm);
    427 
    428      failover_info->prot_group_bitmap =
    429      sal_alloc(SHR_BITALLOCSIZE(num_prot_group), "prot_group_bitmap");
    430      if (failover_info->prot_group_bitmap == NULL) {
    431           _bcm_tr2_failover_free_resource(unit, failover_info);
    432           return BCM_E_MEMORY;
    433      }
    434 
    435      failover_info->prot_nhi_bitmap =
    436      sal_alloc(SHR_BITALLOCSIZE(num_prot_nhi), "prot_nhi_bitmap");
    437      if (failover_info->prot_nhi_bitmap == NULL) {
    438           _bcm_tr2_failover_free_resource(unit, failover_info);
    439           return BCM_E_MEMORY;
    440      }
    441 
    442      sal_memset(failover_info->prot_group_bitmap, 0, SHR_BITALLOCSIZE(num_prot_group));
    443      sal_memset(failover_info->prot_nhi_bitmap, 0, SHR_BITALLOCSIZE(num_prot_nhi));
    444 
    445      /* Create Failover  protection mutex. */
    446      failover_info->failover_mutex = sal_mutex_create("failover_mutex");
    447      if (!failover_info->failover_mutex) {
    448           _bcm_tr2_failover_free_resource(unit, failover_info);
    449           return BCM_E_MEMORY;
    450      }
    451 
    452 #if defined(BCM_SABER2_SUPPORT)
    453      if (SOC_IS_SABER2(unit)) {
    454          /* Since each entry represent 32 group, multiplexing with 32 */
    455          mmu_num_prot_group = 2 * soc_mem_index_count(unit, MMU_INITIAL_NHOP_TBLm);
    456 
    457          failover_info->mmu_prot_group_bitmap =
    458              sal_alloc(SHR_BITALLOCSIZE(mmu_num_prot_group), "mmu_prot_group_bitmap");
    459          if (failover_info->mmu_prot_group_bitmap == NULL) {
    460              _bcm_tr2_failover_free_resource(unit, failover_info);
    461              return BCM_E_MEMORY;
    462          }
    463 
    464          sal_memset(failover_info->mmu_prot_group_bitmap, 0, SHR_BITALLOCSIZE(mmu_num_prot_group));
    465      }
    466 #endif
    467 
    468 #ifdef BCM_WARM_BOOT_SUPPORT
    469     if(SOC_WARM_BOOT(unit)) {
    470         rv = _bcm_tr2_failover_reinit(unit);
    471         if (BCM_FAILURE(rv)){
    472             _bcm_tr2_failover_free_resource(unit, failover_info);
    473             return rv;
    474         }
    475     } else {
    476         /* Cold boot, Allocate scache */
    477         if (SOC_IS_TRIUMPH3(unit)) {
    478             rv = _bcm_tr2_failover_alloc(unit);
    479             if (BCM_FAILURE(rv)) {
    480                 _bcm_tr2_failover_free_resource(unit, failover_info);
    481                 return rv;
    482             }
    483         }
    484     }
    485 #endif /* BCM_WARM_BOOT_SUPPORT */
    486 
    487     /* Mark the state as initialized */
    488     failover_info->initialized = TRUE;
    489 
    490     return rv;
    491 }
    492 
    493 /*
    494  * Function:
    495  *      _bcm_tr2_failover_hw_clear
    496  * Purpose:
    497  *     Perform hw tables clean up for failover module. 
    498  * Parameters:
    499  *      unit     - Device Number
    500  * Returns:
    501  *      BCM_E_XXX
    502  */
    503  
    504 STATIC int
    505 _bcm_tr2_failover_hw_clear(int unit)
    506 {
    507     int i, rv, rv_error = BCM_E_NONE;
    508     int num_entry;
    509 
    510     num_entry = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
    511 
    512     /* Index-0 is reserved */      
    513     for (i = 1; i < num_entry; i++) {
    514         if (_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, i)) {
    515             rv = bcm_tr2_failover_destroy(unit, i);
    516             if (rv < 0) {
    517                 rv_error = rv;
    518             }
    519         }
    520     }
    521 
    522 #if defined(BCM_SABER2_SUPPORT)
    523     if (SOC_IS_SABER2(unit)) {
    524         num_entry = 2 * soc_mem_index_count(unit, MMU_INITIAL_NHOP_TBLm) ;
    525 
    526         /* Index-0 is reserved */      
    527         for (i = 1; i < num_entry; i++) {
    528             if (_BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_GET(unit, i)) {
    529                 rv = bcm_tr2_mmu_failover_destroy(unit, i);
    530                 if (rv < 0) {
    531                     rv_error = rv;
    532                 }
    533             }
    534         }
    535     }
    536 #endif
    537     return rv_error;
    538 }
    539 
    540 /*
    541  * Function:
    542  *      bcm_tr2_failover_cleanup
    543  * Purpose:
    544  *      DeInit  the Failover software module
    545  * Parameters:
    546  *      unit     - Device Number
    547  * Returns:
    548  *      BCM_E_XXX
    549  */
    550 
    551 int
    552 bcm_tr2_failover_cleanup(int unit)
    553 {
    554     _bcm_failover_bookkeeping_t *failover_info = FAILOVER_INFO(unit);
    555     int rv = BCM_E_UNAVAIL;
    556 
    557     if (FALSE == failover_info->initialized) {
    558         return (BCM_E_NONE);
    559     } 
    560 
    561     rv = bcm_tr2_failover_lock (unit);
    562     if (BCM_FAILURE(rv)) {
    563         return rv;
    564     }
    565 
    566     if (0 == SOC_HW_ACCESS_DISABLE(unit)) { 
    567         rv = _bcm_tr2_failover_hw_clear(unit);
    568     }
    569 
    570     /* Free software resources */
    571     (void) _bcm_tr2_failover_free_resource(unit, failover_info);
    572 
    573     bcm_tr2_failover_unlock (unit);
    574 
    575     /* Destroy protection mutex. */
    576     sal_mutex_destroy(failover_info->failover_mutex);
    577 
    578     /* Mark the state as uninitialized */
    579     failover_info->initialized = FALSE;
    580 
    581     return rv;
    582 }
    583 
    584 #if defined(BCM_SABER2_SUPPORT)
    585 /*
    586  * Function:
    587  *		_bcm_tr2_failover_get_prot_group_table_index
    588  * Purpose:
    589  *		Obtain Index into  INITIAL_PROT_GROUP_TABLE
    590  * Parameters:
    591  *		IN :  Unit
    592  *           OUT : prot_index
    593  * Returns:
    594  *		BCM_E_XXX
    595  */
    596 
    597 
    598 STATIC int
    599 _bcm_tr2_failover_get_mmu_prot_group_table_index (int unit, int  *prot_index)
    600 {
    601     int  i;
    602     int  num_entry;
    603 
    604     num_entry = 2 * soc_mem_index_count(unit, MMU_INITIAL_NHOP_TBLm);
    605 
    606     /* Index-0 is reserved */      
    607     for (i = 1; i < num_entry; i++) {
    608          if (!_BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_GET(unit, i)) {
    609               break;
    610          }
    611     }
    612 
    613     if (i == num_entry) {
    614          return  BCM_E_RESOURCE;
    615     }
    616     _BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_SET(unit, i);
    617     *prot_index = i;	 
    618 
    619     return BCM_E_NONE;
    620 }
    621 #endif /* BCM_SABER2_SUPPORT */
    622 
    623 
    624 /*
    625  * Function:
    626  *		_bcm_tr2_failover_clear_prot_group_table_entry
    627  * Purpose:
    628  *		Clear INITIAL_PROT_GROUP_TABLE entry pointed by Index
    629  * Parameters:
    630  *		IN :  Unit
    631  *           IN : prot_index
    632  * Returns:
    633  *		BCM_E_XXX
    634  */
    635 
    636 
    637 STATIC void
    638 _bcm_tr2_failover_clear_mmu_prot_group_table_entry (int unit, bcm_failover_t  prot_index)
    639 {
    640    _BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_CLR(unit, prot_index);
    641 }
    642 
    643 
    644 /*
    645  * Function:
    646  *		_bcm_tr2_failover_id_validate
    647  * Purpose:
    648  *		Validate the failover ID
    649  * Parameters:
    650  *           IN : failover_id
    651  * Returns:
    652  *		BCM_E_XXX
    653  */
    654 
    655 int
    656 bcm_tr2_failover_mmu_id_validate (int unit, bcm_failover_t failover_id)
    657 {
    658     int num_entry;
    659 
    660     num_entry = 2 * soc_mem_index_count(unit,  MMU_INITIAL_NHOP_TBLm);
    661 
    662     if ( ( failover_id < 1 ) || (failover_id > num_entry ) ) {
    663          return BCM_E_PARAM;
    664     } else if (failover_id == num_entry) {
    665          return  BCM_E_RESOURCE;
    666     }
    667     if (!_BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_GET(unit, failover_id)) {
    668         return BCM_E_NOT_FOUND;
    669     }
    670 
    671     return BCM_E_NONE;
    672 }
    673 /*
    674  * Function:
    675  *		_bcm_tr2_failover_get_prot_group_table_index
    676  * Purpose:
    677  *		Obtain Index into  INITIAL_PROT_GROUP_TABLE
    678  * Parameters:
    679  *		IN :  Unit
    680  *           OUT : prot_index
    681  * Returns:
    682  *		BCM_E_XXX
    683  */
    684 
    685 
    686 STATIC int
    687 _bcm_tr2_failover_get_prot_group_table_index (int unit, int  *prot_index)
    688 {
    689     int  i;
    690     int  num_entry;
    691 
    692     num_entry = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
    693 
    694     /* Index-0 is reserved */      
    695     for (i = 1; i < num_entry; i++) {
    696          if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, i)) {
    697               break;
    698          }
    699     }
    700 
    701     if (i == num_entry) {
    702          return  BCM_E_RESOURCE;
    703     }
    704     _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, i);
    705     *prot_index = i;	 
    706 
    707     return BCM_E_NONE;
    708 }
    709 
    710 
    711 
    712 /*
    713  * Function:
    714  *		_bcm_tr2_failover_clear_prot_group_table_entry
    715  * Purpose:
    716  *		Clear INITIAL_PROT_GROUP_TABLE entry pointed by Index
    717  * Parameters:
    718  *		IN :  Unit
    719  *           IN : prot_index
    720  * Returns:
    721  *		BCM_E_XXX
    722  */
    723 
    724 
    725 STATIC void
    726 _bcm_tr2_failover_clear_prot_group_table_entry (int unit, bcm_failover_t  prot_index)
    727 {
    728    _BCM_FAILOVER_PROT_GROUP_MAP_USED_CLR(unit, prot_index);
    729 }
    730 
    731 
    732 
    733 /*
    734  * Function:
    735  *		_bcm_tr2_failover_set_prot_group_table_entry
    736  * Purpose:
    737  *		Set INITIAL_PROT_GROUP_TABLE entry pointed by Index
    738  * Parameters:
    739  *		IN :  Unit
    740  *           IN : prot_index
    741  * Returns:
    742  *		BCM_E_XXX
    743  */
    744 
    745 
    746 STATIC void
    747 _bcm_tr2_failover_set_prot_group_table_entry (int unit, bcm_failover_t  prot_index)
    748 {
    749    _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, prot_index);
    750 }
    751 
    752 /*
    753  * Function:
    754  *		_bcm_tr2_failover_id_validate
    755  * Purpose:
    756  *		Validate the failover ID
    757  * Parameters:
    758  *           IN : failover_id
    759  * Returns:
    760  *		BCM_E_XXX
    761  */
    762 
    763 int
    764 bcm_tr2_failover_id_validate (int unit, bcm_failover_t failover_id)
    765 {
    766     int num_entry;
    767 
    768     num_entry = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
    769 
    770     if ( ( failover_id < 1 ) || (failover_id > num_entry ) ) {
    771          return BCM_E_PARAM;
    772     } else if (failover_id == num_entry) {
    773          return  BCM_E_RESOURCE;
    774     }
    775      if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, failover_id)) {
    776           return BCM_E_NOT_FOUND;
    777      }
    778 
    779     return BCM_E_NONE;
    780 }
    781 
    782 /*
    783  * Function:
    784  *		bcm_tr2_failover_create
    785  * Purpose:
    786  *		Create a failover object
    787  * Parameters:
    788  *		IN :  unit
    789  *           IN :  flags
    790  *           OUT :  failover_id
    791  * Returns:
    792  *		BCM_E_XXX
    793  */
    794 
    795 int 
    796 bcm_tr2_failover_create(int unit, uint32 flags, bcm_failover_t *failover_id)
    797 {
    798     int rv = BCM_E_UNAVAIL;
    799     initial_prot_group_table_entry_t  prot_group_entry;
    800 #if defined(BCM_TRIUMPH3_SUPPORT)
    801     rx_prot_group_table_entry_t  rx_prot_group_entry;
    802 #endif /* BCM_TRIUMPH3_SUPPORT */
    803     int  num_entry;
    804 
    805     if (failover_id == NULL) {
    806         return BCM_E_PARAM;
    807     }
    808 
    809     /* Check for unsupported Flag */
    810     if (flags & (~(BCM_FAILOVER_REPLACE |
    811                    BCM_FAILOVER_WITH_ID |
    812                    BCM_FAILOVER_ENCAP))) {
    813         return BCM_E_PARAM;
    814     }
    815 
    816     if ((flags & BCM_FAILOVER_WITH_ID) || (flags & BCM_FAILOVER_REPLACE )) {
    817 
    818 #if defined(BCM_SABER2_SUPPORT)
    819         if ((SOC_IS_SABER2(unit)) && (flags & BCM_FAILOVER_ENCAP)) {
    820             /* make sure the given id is valid */
    821             num_entry = 2 * soc_mem_index_count(unit, MMU_INITIAL_NHOP_TBLm) ;
    822             if ((*failover_id < 1) || (*failover_id >= num_entry)) {
    823                 return BCM_E_PARAM;
    824             }
    825             if (flags & BCM_FAILOVER_WITH_ID) {
    826                 if (_BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_GET(unit, *failover_id)) {
    827                     return BCM_E_EXISTS;
    828                 } else {
    829                     _BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_SET(unit, *failover_id);
    830                 }
    831             }
    832             if (flags & BCM_FAILOVER_REPLACE) {
    833                 if (!_BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_GET(unit, *failover_id)) {
    834                     return BCM_E_NOT_FOUND;
    835                 }
    836             }
    837             _BCM_ENCAP_TYPE_IN_FAILOVER_ID(*failover_id, _BCM_FAILOVER_1_1_MC_PROTECTION_MODE); 
    838             return BCM_E_NONE;
    839 
    840         } else
    841 #endif
    842         {
    843             /* make sure the given id is valid */
    844             num_entry = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
    845             if ((*failover_id < 1) || (*failover_id >= num_entry)) {
    846                 return BCM_E_PARAM;
    847             }
    848             if (flags & BCM_FAILOVER_WITH_ID) {
    849                 if (_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, *failover_id)) {
    850                     return BCM_E_EXISTS;
    851                 } else {
    852                     _BCM_FAILOVER_PROT_GROUP_MAP_USED_SET(unit, *failover_id);
    853                 }
    854             }
    855             if (flags & BCM_FAILOVER_REPLACE) {
    856                 if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, *failover_id)) {
    857                     return BCM_E_NOT_FOUND;
    858                 }
    859             }
    860         }
    861          rv = BCM_E_NONE;
    862          _BCM_ENCAP_TYPE_IN_FAILOVER_ID(*failover_id, _BCM_FAILOVER_DEFAULT_MODE); 
    863     } else  if (!flags) {
    864          /* Get Index */
    865          rv = _bcm_tr2_failover_get_prot_group_table_index (unit, failover_id);
    866          _BCM_ENCAP_TYPE_IN_FAILOVER_ID(*failover_id, _BCM_FAILOVER_DEFAULT_MODE); 
    867     }
    868 #if defined(BCM_SABER2_SUPPORT)
    869     else if ((SOC_IS_SABER2(unit)) && (flags & BCM_FAILOVER_ENCAP)) {
    870 	 /* Get Index */
    871 	    rv = _bcm_tr2_failover_get_mmu_prot_group_table_index (unit, failover_id);
    872 	    BCM_IF_ERROR_RETURN(rv);
    873 	    _BCM_ENCAP_TYPE_IN_FAILOVER_ID(*failover_id, _BCM_FAILOVER_1_1_MC_PROTECTION_MODE);
    874 	     return BCM_E_NONE;
    875     }
    876 #endif
    877     
    878     if (BCM_SUCCESS(rv)) {
    879         /* Init table entry */
    880         sal_memset(&prot_group_entry, 0, sizeof(initial_prot_group_table_entry_t));
    881         rv = soc_mem_write(unit, INITIAL_PROT_GROUP_TABLEm,
    882                 MEM_BLOCK_ALL, *failover_id,
    883                 &prot_group_entry);
    884         if (rv < 0) {
    885             _bcm_tr2_failover_clear_prot_group_table_entry(unit, *failover_id);
    886             return BCM_E_RESOURCE;
    887         }
    888     }
    889 
    890 #if defined(BCM_TRIUMPH3_SUPPORT)
    891     if (SOC_IS_TRIUMPH3(unit)) {
    892          /* Init table entry */
    893          sal_memset(&rx_prot_group_entry, 0, sizeof(rx_prot_group_table_entry_t));
    894          rv = soc_mem_write(unit, RX_PROT_GROUP_TABLEm,
    895                                   MEM_BLOCK_ALL, *failover_id,
    896                                   &rx_prot_group_entry);
    897          if (rv < 0) {
    898               _bcm_tr2_failover_clear_prot_group_table_entry(unit, *failover_id);
    899               return BCM_E_RESOURCE;
    900          }
    901     }
    902 #endif /* BCM_TRIUMPH3_SUPPORT */
    903 
    904     return rv;
    905 }
    906 
    907 /*
    908  * Function:
    909  *		bcm_tr2_failover_destroy
    910  * Purpose:
    911  *		Destroy a failover object
    912  * Parameters:
    913  *		IN :  unit
    914  *           IN :  failover_id
    915  * Returns:
    916  *		BCM_E_XXX
    917  */
    918 
    919 int 
    920 bcm_tr2_failover_destroy(int unit, bcm_failover_t  failover_id)
    921 {
    922     int rv = BCM_E_UNAVAIL;
    923     initial_prot_group_table_entry_t  prot_group_entry;
    924 #if defined(BCM_TRIUMPH3_SUPPORT)
    925     rx_prot_group_table_entry_t  rx_prot_group_entry;
    926 #endif /* BCM_TRIUMPH3_SUPPORT */
    927 
    928     rv = bcm_tr2_failover_id_validate ( unit, failover_id );
    929     BCM_IF_ERROR_RETURN(rv);
    930 
    931     if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, failover_id)) {
    932          return BCM_E_NOT_FOUND;
    933     }
    934 
    935     /* Release index */
    936     _bcm_tr2_failover_clear_prot_group_table_entry (unit, failover_id);
    937 
    938    /* Clear entry */
    939     BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_GROUP_TABLEm, 
    940                              MEM_BLOCK_ANY, failover_id, &prot_group_entry));
    941     sal_memset(&prot_group_entry, 0, 
    942                              sizeof(initial_prot_group_table_entry_t));
    943     rv = soc_mem_write(unit, INITIAL_PROT_GROUP_TABLEm,
    944                              MEM_BLOCK_ALL, failover_id,
    945                              &prot_group_entry);
    946     if (rv < 0) {
    947          _bcm_tr2_failover_set_prot_group_table_entry(unit, failover_id);
    948          return BCM_E_RESOURCE;
    949     }
    950 
    951 #if defined(BCM_TRIUMPH3_SUPPORT)
    952     if (SOC_IS_TRIUMPH3(unit)) {
    953          /* Init table entry */
    954          sal_memset(&rx_prot_group_entry, 0, sizeof(rx_prot_group_table_entry_t));
    955 
    956          rv = soc_mem_write(unit, RX_PROT_GROUP_TABLEm,
    957                                   MEM_BLOCK_ALL, failover_id,
    958                                   &rx_prot_group_entry);
    959          if (rv < 0) {
    960               _bcm_tr2_failover_set_prot_group_table_entry(unit, failover_id);
    961               return BCM_E_RESOURCE;
    962          }
    963     }
    964 #endif /* BCM_TRIUMPH3_SUPPORT */
    965 
    966     return rv;
    967 }
    968 
    969 int 
    970 bcm_tr2_mmu_failover_destroy(int unit, bcm_failover_t  failover_id)
    971 {
    972     _BCM_GET_FAILOVER_ID(failover_id);
    973     if (!_BCM_FAILOVER_MMU_PROT_GROUP_MAP_USED_GET(unit, failover_id)) {
    974          return BCM_E_NOT_FOUND;
    975     }
    976 
    977     /* Release index */
    978     _bcm_tr2_failover_clear_mmu_prot_group_table_entry (unit, failover_id);
    979 #if defined(BCM_SABER2_SUPPORT)
    980     if (SOC_IS_SABER2(unit)) {
    981         bcm_sb2_failover_destroy(unit, failover_id);
    982     }
    983 #endif
    984     return BCM_E_NONE;
    985 }
    986 /*
    987  * Function:
    988  *		bcm_tr2_failover_set
    989  * Purpose:
    990  *		Set the parameters for  a failover object
    991  * Parameters:
    992  *		IN :  unit
    993  *           IN :  failover_id
    994  *           IN :  value
    995  * Returns:
    996  *		BCM_E_XXX
    997  */
    998 
    999 int
   1000 bcm_tr2_failover_set(int unit, bcm_failover_t failover_id, int value)
   1001 {
   1002     int rv = BCM_E_UNAVAIL;
   1003     initial_prot_group_table_entry_t  prot_group_entry;
   1004 
   1005     BCM_IF_ERROR_RETURN( bcm_tr2_failover_id_validate ( unit, failover_id ));
   1006     if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, failover_id)) {
   1007          return BCM_E_NOT_FOUND;
   1008     }
   1009     if ((value < 0) || (value > 1)) {
   1010        return BCM_E_PARAM;
   1011     }
   1012 
   1013     BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_GROUP_TABLEm, 
   1014                    MEM_BLOCK_ANY, failover_id, &prot_group_entry));
   1015 
   1016     soc_mem_field32_set(unit, INITIAL_PROT_GROUP_TABLEm, 
   1017                    &prot_group_entry, STATUSf, 
   1018                    value);
   1019 
   1020     rv =  soc_mem_write(unit, INITIAL_PROT_GROUP_TABLEm,
   1021                    MEM_BLOCK_ALL, failover_id,
   1022                    &prot_group_entry);
   1023 
   1024     return rv;
   1025 
   1026 }
   1027 
   1028 
   1029 /*
   1030  * Function:
   1031  *		bcm_tr2_failover_get
   1032  * Purpose:
   1033  *		Get the parameters for  a failover object
   1034  * Parameters:
   1035  *		IN :  unit
   1036  *           IN :  failover_id
   1037  *           OUT :  value
   1038  * Returns:
   1039  *		BCM_E_XXX
   1040  */
   1041 
   1042 int
   1043 bcm_tr2_failover_get(int unit, bcm_failover_t failover_id, int  *value)
   1044 {
   1045     initial_prot_group_table_entry_t  prot_group_entry;
   1046 
   1047     BCM_IF_ERROR_RETURN( bcm_tr2_failover_id_validate ( unit, failover_id ));
   1048     if (!_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, failover_id)) {
   1049          return BCM_E_NOT_FOUND;
   1050     }
   1051 
   1052     BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_GROUP_TABLEm, 
   1053                    MEM_BLOCK_ANY, failover_id, &prot_group_entry));
   1054 
   1055     *value =   soc_mem_field32_get(unit, INITIAL_PROT_GROUP_TABLEm,
   1056                    &prot_group_entry, STATUSf);
   1057 
   1058     return BCM_E_NONE;
   1059 }
   1060 
   1061 
   1062 /*
   1063  * Function:
   1064  *		bcm_tr2_failover_prot_nhi_create
   1065  * Purpose:
   1066  *		Create  the  entry for  PROT_NHI
   1067  * Parameters:
   1068  *		IN :  unit
   1069  *           IN :  Primary Next Hop Index
   1070  * Returns:
   1071  *		BCM_E_XXX
   1072  */
   1073 
   1074 
   1075 int
   1076 bcm_tr2_failover_prot_nhi_create (int unit, int nh_index)
   1077 {
   1078     initial_prot_nhi_table_entry_t  prot_nhi_entry;
   1079     int rv = BCM_E_UNAVAIL;
   1080 
   1081     sal_memset(&prot_nhi_entry, 0, sizeof(initial_prot_nhi_table_entry_t));
   1082 
   1083     rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm,
   1084                        MEM_BLOCK_ALL, nh_index, &prot_nhi_entry);
   1085 
   1086     return rv;
   1087 
   1088 }
   1089 
   1090 
   1091 /*
   1092  * Function:
   1093  *		bcm_tr2_failover_prot_nhi_set
   1094  * Purpose:
   1095  *		Set the parameters for PROT_NHI
   1096  * Parameters:
   1097  *		IN :  unit
   1098  *           IN :  Primary Next Hop Index
   1099  *           IN :  Protection Next Hop Index
   1100  *           IN :  Failover Group Index
   1101  * Returns:
   1102  *		BCM_E_XXX
   1103  */
   1104 
   1105 int
   1106 bcm_tr2_failover_prot_nhi_set(int unit, int nh_index, uint32 prot_nh_index, bcm_failover_t failover_id)
   1107 {
   1108     initial_prot_nhi_table_entry_t   prot_nhi_entry;
   1109     int rv = BCM_E_UNAVAIL;
   1110 
   1111     BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 
   1112                              MEM_BLOCK_ANY, nh_index, &prot_nhi_entry));
   1113 
   1114     soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 
   1115                                        &prot_nhi_entry, PROT_NEXT_HOP_INDEXf, 
   1116                                        prot_nh_index);
   1117 
   1118     soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm, 
   1119                                        &prot_nhi_entry, PROT_GROUPf, 
   1120                                        (uint32) failover_id);
   1121 
   1122     rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm,
   1123                        MEM_BLOCK_ALL, nh_index, &prot_nhi_entry);
   1124 
   1125     return rv;
   1126 
   1127 }
   1128 
   1129 
   1130 /*
   1131  * Function:
   1132  *		bcm_tr2_failover_prot_nhi_get
   1133  * Purpose:
   1134  *		Get the parameters for PROT_NHI
   1135  * Parameters:
   1136  *		IN :  unit
   1137  *           IN :  primary Next Hop Index
   1138  *           OUT :  Failover Group Index
   1139  *           OUT : Protection Next Hop Index
   1140  * Returns:
   1141  *		BCM_E_XXX
   1142  */
   1143 
   1144 
   1145 int
   1146 bcm_tr2_failover_prot_nhi_get(int unit, int nh_index, bcm_failover_t  *failover_id, int  *prot_nh_index)
   1147 {
   1148     initial_prot_nhi_table_entry_t   prot_nhi_entry;
   1149 
   1150     BCM_IF_ERROR_RETURN (soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 
   1151                              MEM_BLOCK_ANY, nh_index, &prot_nhi_entry));
   1152 
   1153     *failover_id =   soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm,
   1154                               &prot_nhi_entry, PROT_GROUPf);
   1155 
   1156     *prot_nh_index =   soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm,
   1157                               &prot_nhi_entry, PROT_NEXT_HOP_INDEXf);
   1158 
   1159     return BCM_E_NONE;
   1160 
   1161 }
   1162 
   1163 /*
   1164  * Function:
   1165  *		bcm_tr2_failover_prot_nhi_cleanup
   1166  * Purpose:
   1167  *		Create  the  entry for  PROT_NHI
   1168  * Parameters:
   1169  *		IN :  unit
   1170  *           IN :  Primary Next Hop Index
   1171  * Returns:
   1172  *		BCM_E_XXX
   1173  */
   1174 
   1175 
   1176 int
   1177 bcm_tr2_failover_prot_nhi_cleanup  (int unit, int nh_index)
   1178 {
   1179     initial_prot_nhi_table_entry_t  prot_nhi_entry;
   1180     int rv = BCM_E_UNAVAIL;
   1181 
   1182     rv = soc_mem_read(unit, INITIAL_PROT_NHI_TABLEm, 
   1183                              MEM_BLOCK_ANY, nh_index, &prot_nhi_entry);
   1184 
   1185    if (rv < 0){
   1186          return BCM_E_NOT_FOUND;
   1187     }
   1188 
   1189     sal_memset(&prot_nhi_entry, 0, sizeof(initial_prot_nhi_table_entry_t));
   1190 
   1191     rv = soc_mem_write(unit, INITIAL_PROT_NHI_TABLEm,
   1192                        MEM_BLOCK_ALL, nh_index, &prot_nhi_entry);
   1193 
   1194     return rv;
   1195 
   1196 }
   1197 
   1198 /*
   1199  * Function:
   1200  *    bcm_tr2_failover_prot_nhi_update
   1201  * Purpose:
   1202  *    Update the next_hop  entry for failover
   1203  * Parameters:
   1204  *    IN :  unit
   1205  *    IN :  Old Failover next hop index
   1206  *    IN :  New Failover next hop index
   1207  * Returns:
   1208  *    BCM_E_XXX
   1209  */
   1210 
   1211 
   1212 int
   1213 bcm_tr2_failover_prot_nhi_update  (int unit, int old_nh_index, int new_nh_index)
   1214 {
   1215     int rv=BCM_E_NONE;
   1216     int num_entry, index;
   1217     int prot_nh_index;
   1218     uint32 *pprot_nhi = NULL;
   1219     uint32 *pprot_nhi_entry = NULL; 
   1220     int entry_size; 
   1221 
   1222     num_entry = soc_mem_index_count(unit, INITIAL_PROT_NHI_TABLEm);
   1223     entry_size = soc_mem_entry_words(unit, INITIAL_PROT_NHI_TABLEm); 
   1224     pprot_nhi = soc_cm_salloc(unit, num_entry * entry_size * 4, "temp_buf");
   1225     if (pprot_nhi == NULL) 
   1226         return BCM_E_MEMORY; 
   1227     rv = soc_mem_read_range(unit, INITIAL_PROT_NHI_TABLEm, MEM_BLOCK_ANY, 0, 
   1228                             num_entry-1, pprot_nhi);
   1229     if (rv == SOC_E_NONE) {
   1230         for (index=0, pprot_nhi_entry = pprot_nhi; index < num_entry; index++) {        
   1231             prot_nh_index = soc_mem_field32_get(unit, INITIAL_PROT_NHI_TABLEm,
   1232                                                 pprot_nhi_entry, 
   1233                                                 PROT_NEXT_HOP_INDEXf);
   1234         
   1235             if (prot_nh_index == old_nh_index) {
   1236                 soc_mem_field32_set(unit, INITIAL_PROT_NHI_TABLEm,
   1237                                     pprot_nhi_entry, PROT_NEXT_HOP_INDEXf,
   1238                                     new_nh_index);
   1239             }    
   1240             pprot_nhi_entry += entry_size;   
   1241         }
   1242         rv = soc_mem_write_range(unit, INITIAL_PROT_NHI_TABLEm, MEM_BLOCK_ANY, 
   1243                                  0, num_entry-1, pprot_nhi);
   1244     }
   1245     if (pprot_nhi)
   1246         soc_cm_sfree(unit, pprot_nhi);
   1247     return rv;
   1248 }
   1249 
   1250 /*
   1251  * Function:
   1252  *    bcm_tr2_failover_ecmp_prot_nhi_set
   1253  * Purpose:
   1254  *    Set the parameters for PROT_NHI
   1255  * Parameters:
   1256  *    IN :  unit
   1257  *    IN :  ecmp index /dvp group pointer
   1258  *    IN :  member offset from base ptr
   1259  *    IN :  Primary Next Hop Index
   1260  *    IN :  Protection Next Hop Index
   1261  *    IN :  Failover Group Index
   1262  * Returns:
   1263  *    BCM_E_XXX
   1264  */
   1265 
   1266 int
   1267 bcm_tr2_failover_ecmp_prot_nhi_set(int unit, int ecmp, int index, 
   1268                                    int nh_index, 
   1269                                    bcm_failover_t failover_id, 
   1270                                    int prot_nh_index)
   1271 {
   1272     int i, base_ptr = 0, count = 0, nhi, idx_max;
   1273     uint32 hw_buf[SOC_MAX_MEM_WORDS]; /* Buffer to read hw entry. */
   1274 
   1275 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1276 #if defined(BCM_TRIDENT3_SUPPORT)
   1277     uint8 protected_ecmp = 0;
   1278     int ecmp_max_paths = 0, rv = BCM_E_NONE;
   1279     uint32 alloc_sz = 0;
   1280     soc_esw_ecmp_group_info_t grp_info = {0};
   1281     soc_esw_ecmp_member_info_t *mem_array = NULL;
   1282 #endif /* BCM_TRIDENT3_SUPPORT */
   1283 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1284 
   1285 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_APACHE_SUPPORT)
   1286     if (soc_feature(unit, soc_feature_hierarchical_protection)) {
   1287         idx_max = (soc_mem_index_count(unit, TX_PROT_GROUP_1_1_TABLEm) *
   1288                 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY);
   1289     } else if (soc_feature(unit, soc_feature_td2p_mpls_linear_protection)) {
   1290         idx_max = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) *
   1291                 BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY);
   1292     } else
   1293 #endif
   1294 #if defined(BCM_TOMAHAWK2_SUPPORT)
   1295     if (SOC_IS_TOMAHAWK2(unit)) {
   1296         idx_max = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) *
   1297                    BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY);
   1298     } else
   1299 #endif
   1300     {
   1301         idx_max = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
   1302     }
   1303 
   1304     if (ecmp < 0) {
   1305         base_ptr = soc_mem_index_min(unit, INITIAL_L3_ECMPm);
   1306         count    = soc_mem_index_count(unit, INITIAL_L3_ECMPm);
   1307     } else {
   1308         BCM_IF_ERROR_RETURN(
   1309             _bcm_xgs3_l3_ecmp_grp_info_get(unit, ecmp, &count, &base_ptr));
   1310     }
   1311 
   1312 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1313 #if defined(BCM_TRIDENT3_SUPPORT)
   1314     if (soc_esw_ecmp_protected_enabled(unit)) {
   1315         protected_ecmp = 1;
   1316         rv = _bcm_xgs3_ecmp_max_grp_size_get(unit, ecmp, &ecmp_max_paths);
   1317         if (rv != BCM_E_NONE) {
   1318             return rv;
   1319         }
   1320 
   1321         alloc_sz = (ecmp_max_paths * sizeof(soc_esw_ecmp_member_info_t));
   1322         mem_array = sal_alloc(alloc_sz, "NH array");
   1323         if (NULL == mem_array) {
   1324             return BCM_E_MEMORY;
   1325         }
   1326 
   1327         SOC_ESW_ECMP_LOCK(unit);
   1328         sal_memset(mem_array, 0, alloc_sz);
   1329         /* Calculate Base_ptr table index. */
   1330         grp_info.ecmp_grp = ecmp;
   1331         rv = soc_esw_ecmp_protected_grp_get(unit, &grp_info, mem_array);
   1332         if (rv != BCM_E_NONE) {
   1333             sal_free(mem_array);
   1334             SOC_ESW_ECMP_UNLOCK(unit);
   1335             return rv;
   1336         }
   1337     }
   1338 #endif /* BCM_TRIDENT3_SUPPORT */
   1339 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1340 
   1341     for (i = 0; i < count; i++) {
   1342         if (index >= 0 && index < count && index != i) {
   1343             continue;
   1344         }
   1345 
   1346 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1347 #if defined(BCM_TRIDENT3_SUPPORT)
   1348         if (protected_ecmp == 1) {
   1349             nhi = mem_array[i].nh;
   1350             if (nhi == nh_index) {
   1351                 mem_array[i].prot_nh = prot_nh_index;
   1352                 if (failover_id > 0 &&
   1353                     failover_id < idx_max) {
   1354                     mem_array[i].prot_grp = failover_id;
   1355                 }
   1356             } else { /* Mismatch between offset and nh_index */
   1357                 if (index == i) {
   1358                     sal_free(mem_array);
   1359                     SOC_ESW_ECMP_UNLOCK(unit);
   1360                     return BCM_E_PARAM;
   1361                 }
   1362             }
   1363         } else
   1364 #endif /* BCM_TRIDENT3_SUPPORT */
   1365 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1366         {
   1367             BCM_IF_ERROR_RETURN(
   1368                 soc_mem_read(unit, INITIAL_L3_ECMPm,
   1369                              MEM_BLOCK_ANY, base_ptr + i, hw_buf));
   1370 
   1371             nhi = soc_mem_field32_get(unit, INITIAL_L3_ECMPm, hw_buf,
   1372                                       NEXT_HOP_INDEXf);
   1373             if (nhi == nh_index) {
   1374                 soc_mem_field32_set(unit, INITIAL_L3_ECMPm, hw_buf,
   1375                                     PROT_NEXT_HOP_INDEXf, (uint32)prot_nh_index);
   1376                 if (failover_id > 0 &&
   1377                     failover_id < idx_max) {
   1378                     soc_mem_field32_set(unit, INITIAL_L3_ECMPm, hw_buf,
   1379                                         PROT_GROUPf, (uint32)failover_id);
   1380                 }
   1381                 BCM_IF_ERROR_RETURN(
   1382                     soc_mem_write(unit, INITIAL_L3_ECMPm,
   1383                                   MEM_BLOCK_ANY, base_ptr + i, hw_buf));
   1384             } else { /* Mismatch between offset and nh_index */
   1385                 if (index == i) {
   1386                     return BCM_E_PARAM;
   1387                 }
   1388             }
   1389         }
   1390     }
   1391 
   1392 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1393 #if defined(BCM_TRIDENT3_SUPPORT)
   1394     if (protected_ecmp == 1) {
   1395         soc_esw_ecmp_group_info_t_init(&grp_info);
   1396         grp_info.ecmp_grp = ecmp;
   1397         grp_info.ecmp_member_base = base_ptr;
   1398         grp_info.max_paths = ecmp_max_paths;
   1399         rv = soc_esw_ecmp_protected_grp_add(unit, &grp_info, mem_array);
   1400         if (rv != BCM_E_NONE) {
   1401             sal_free(mem_array);
   1402             SOC_ESW_ECMP_UNLOCK(unit);
   1403             return rv;
   1404         }
   1405         sal_free(mem_array);
   1406         SOC_ESW_ECMP_UNLOCK(unit);
   1407 
   1408         if (base_ptr != grp_info.ecmp_member_base) {
   1409             ecmp_count_entry_t l3_ecmp_count_entry;
   1410             initial_l3_ecmp_group_entry_t initial_l3_ecmp_group_entry;
   1411     
   1412             BCM_XGS3_L3_ENT_REF_CNT_DEC(BCM_XGS3_L3_TBL_PTR(unit, ecmp),
   1413                                         base_ptr, ecmp_max_paths);
   1414             base_ptr = grp_info.ecmp_member_base;
   1415             BCM_XGS3_L3_ENT_REF_CNT_INC(BCM_XGS3_L3_TBL_PTR(unit, ecmp),
   1416                                         base_ptr, ecmp_max_paths);
   1417     
   1418             sal_memset(&l3_ecmp_count_entry, 0, sizeof(l3_ecmp_count_entry));
   1419             sal_memset(&initial_l3_ecmp_group_entry, 0, sizeof(initial_l3_ecmp_group_entry));
   1420     
   1421             SOC_IF_ERROR_RETURN(
   1422                 READ_INITIAL_L3_ECMP_GROUPm(unit, MEM_BLOCK_ANY,
   1423                                             ecmp, &initial_l3_ecmp_group_entry));
   1424             soc_INITIAL_L3_ECMP_GROUPm_field32_set(unit, &initial_l3_ecmp_group_entry,
   1425                                                    BASE_PTRf, base_ptr);
   1426             SOC_IF_ERROR_RETURN(
   1427                 WRITE_INITIAL_L3_ECMP_GROUPm(unit, MEM_BLOCK_ALL,
   1428                                              ecmp, &initial_l3_ecmp_group_entry));
   1429             SOC_IF_ERROR_RETURN(
   1430                 READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY,
   1431                                     ecmp, &l3_ecmp_count_entry));
   1432             soc_L3_ECMP_COUNTm_field32_set(unit, &l3_ecmp_count_entry,
   1433                                            BASE_PTRf, base_ptr);
   1434             SOC_IF_ERROR_RETURN(
   1435                 WRITE_L3_ECMP_COUNTm(unit, MEM_BLOCK_ALL,
   1436                                      ecmp, &l3_ecmp_count_entry));
   1437     
   1438         }
   1439 
   1440     }
   1441 #endif /* BCM_TRIDENT3_SUPPORT */
   1442 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1443 
   1444     return BCM_E_NONE;
   1445 }
   1446 
   1447 
   1448 /*
   1449  * Function:
   1450  *    bcm_tr2_failover_ecmp_prot_nhi_get
   1451  * Purpose:
   1452  *    Get the parameters for ecmp PROT_NHI
   1453  * Parameters:
   1454  *    IN :  unit
   1455  *    IN :  ecmp index /dvp group pointer
   1456  *    IN :  member offset from base ptr
   1457  *    IN :  primary Next Hop Index
   1458  *    OUT : Failover Group Index
   1459  *    OUT : Protection Next Hop Index
   1460  * Returns:
   1461  *    BCM_E_XXX
   1462  */
   1463 
   1464 int
   1465 bcm_tr2_failover_ecmp_prot_nhi_get(int unit, int ecmp, int index, 
   1466                                    int nh_index, 
   1467                                    bcm_failover_t *failover_id,
   1468                                    int *prot_nh_index)
   1469 {
   1470     int i, base_ptr = 0, count = 0, nhi;
   1471     uint32 hw_buf[SOC_MAX_MEM_WORDS]; /* Buffer to read hw entry. */
   1472 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1473 #if defined(BCM_TRIDENT3_SUPPORT)
   1474     uint8 protected_ecmp = 0;
   1475     int ecmp_max_paths = 0, rv = BCM_E_NONE;
   1476     uint32 alloc_sz = 0;
   1477     soc_esw_ecmp_group_info_t grp_info = {0};
   1478     soc_esw_ecmp_member_info_t *mem_array = NULL;
   1479 #endif /* BCM_TRIDENT3_SUPPORT */
   1480 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1481 
   1482 
   1483     if (ecmp < 0) {
   1484         base_ptr = soc_mem_index_min(unit, INITIAL_L3_ECMPm);
   1485         count    = soc_mem_index_count(unit, INITIAL_L3_ECMPm);
   1486     } else {
   1487         BCM_IF_ERROR_RETURN(
   1488             _bcm_xgs3_l3_ecmp_grp_info_get(unit, ecmp, &count, &base_ptr));
   1489     }
   1490 
   1491 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1492 #if defined(BCM_TRIDENT3_SUPPORT)
   1493     if (soc_esw_ecmp_protected_enabled(unit)) {
   1494         protected_ecmp = 1;
   1495         rv = _bcm_xgs3_ecmp_max_grp_size_get(unit, ecmp, &ecmp_max_paths);
   1496         if (rv != BCM_E_NONE) {
   1497             return rv;
   1498         }
   1499 
   1500         alloc_sz = (ecmp_max_paths * sizeof(soc_esw_ecmp_member_info_t));
   1501         mem_array = sal_alloc(alloc_sz, "NH array");
   1502         if (NULL == mem_array) {
   1503             return BCM_E_MEMORY;
   1504         }
   1505 
   1506         SOC_ESW_ECMP_LOCK(unit);
   1507         sal_memset(mem_array, 0, alloc_sz);
   1508         grp_info.ecmp_grp = ecmp;
   1509         rv = soc_esw_ecmp_protected_grp_get(unit, &grp_info, mem_array);
   1510         if (BCM_FAILURE(rv)) {
   1511             sal_free(mem_array);
   1512             SOC_ESW_ECMP_UNLOCK(unit);
   1513             return rv;
   1514         }
   1515         SOC_ESW_ECMP_UNLOCK(unit);
   1516     }
   1517 #endif /* BCM_TRIDENT3_SUPPORT */
   1518 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1519 
   1520     for (i = 0; i < count; i++) {
   1521         if (index >= 0 && index < count && index != i) {
   1522             continue;
   1523         }
   1524 
   1525 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1526 #if defined(BCM_TRIDENT3_SUPPORT)
   1527         if (protected_ecmp == 1) {
   1528             nhi = mem_array[i].nh;
   1529             if (nhi == nh_index) {
   1530                 *failover_id   = mem_array[i].prot_grp;
   1531                 *prot_nh_index = mem_array[i].prot_nh;
   1532                 if (*failover_id == 0 && *prot_nh_index == 0) {
   1533                     sal_free(mem_array);
   1534                     return BCM_E_NOT_FOUND;
   1535                 }
   1536                 break;
   1537             } else { /* Mismatch between offset and nh_index */
   1538                 if (index == i) {
   1539                     sal_free(mem_array);
   1540                     return BCM_E_PARAM;
   1541                 }
   1542             }
   1543         } else
   1544 #endif /* BCM_TRIDENT3_SUPPORT */
   1545 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1546         {
   1547 
   1548             BCM_IF_ERROR_RETURN(
   1549                 soc_mem_read(unit, INITIAL_L3_ECMPm,
   1550                              MEM_BLOCK_ANY, base_ptr + i, hw_buf));
   1551 
   1552             nhi = soc_mem_field32_get(unit, INITIAL_L3_ECMPm, hw_buf,
   1553                                       NEXT_HOP_INDEXf);
   1554             if (nhi == nh_index) {
   1555                 *failover_id   = soc_mem_field32_get(unit, INITIAL_L3_ECMPm, hw_buf,
   1556                                                      PROT_GROUPf);
   1557                 *prot_nh_index = soc_mem_field32_get(unit, INITIAL_L3_ECMPm, hw_buf,
   1558                                                      PROT_NEXT_HOP_INDEXf);
   1559                 if (*failover_id == 0 && *prot_nh_index == 0) {
   1560                     return BCM_E_NOT_FOUND;
   1561                 }
   1562                 break;
   1563             } else { /* Mismatch between offset and nh_index */
   1564                 if (index == i) {
   1565                     return BCM_E_PARAM;
   1566                 }
   1567             }
   1568         }
   1569     }
   1570 
   1571 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1572 #if defined(BCM_TRIDENT3_SUPPORT)
   1573     sal_free(mem_array);
   1574 #endif /* BCM_TRIDENT3_SUPPORT */
   1575 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1576 
   1577     return BCM_E_NONE;
   1578 }
   1579 
   1580 /*
   1581  * Function:
   1582  *    bcm_tr2_failover_prot_nhi_cleanup
   1583  * Purpose:
   1584  *    Create  the  entry for  PROT_NHI
   1585  * Parameters:
   1586  *    IN :  unit
   1587  *    IN :  ecmp index /dvp group pointer
   1588  *    IN :  member offset from base ptr
   1589  *    IN :  Primary Next Hop Index
   1590  * Returns:
   1591  *    BCM_E_XXX
   1592  */
   1593 
   1594 
   1595 int
   1596 bcm_tr2_failover_ecmp_prot_nhi_cleanup(int unit, int ecmp, int index,
   1597                                        int nh_index)
   1598 {
   1599     int i, base_ptr = 0, count = 0, nhi;
   1600     uint32 hw_buf[SOC_MAX_MEM_WORDS]; /* Buffer to read hw entry. */
   1601 
   1602 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1603 #if defined(BCM_TRIDENT3_SUPPORT)
   1604     uint8 protected_ecmp = 0;
   1605     int ecmp_max_paths = 0, rv = BCM_E_NONE;
   1606     uint32 alloc_sz = 0;
   1607     soc_esw_ecmp_group_info_t grp_info = {0};
   1608     soc_esw_ecmp_member_info_t *mem_array = NULL;
   1609 #endif /* BCM_TRIDENT3_SUPPORT */
   1610 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1611 
   1612     if (ecmp < 0) {
   1613         base_ptr = soc_mem_index_min(unit, INITIAL_L3_ECMPm);
   1614         count    = soc_mem_index_count(unit, INITIAL_L3_ECMPm);
   1615     } else {
   1616         BCM_IF_ERROR_RETURN(
   1617             _bcm_xgs3_l3_ecmp_grp_info_get(unit, ecmp, &count, &base_ptr));
   1618     }
   1619 
   1620 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1621 #if defined(BCM_TRIDENT3_SUPPORT)
   1622     if (soc_esw_ecmp_protected_enabled(unit)) {
   1623         protected_ecmp = 1;
   1624         rv = _bcm_xgs3_ecmp_max_grp_size_get(unit, ecmp, &ecmp_max_paths);
   1625         if (rv != BCM_E_NONE) {
   1626             return rv;
   1627         }
   1628 
   1629         alloc_sz = (ecmp_max_paths * sizeof(soc_esw_ecmp_member_info_t));
   1630         mem_array = sal_alloc(alloc_sz, "NH array");
   1631         if (NULL == mem_array) {
   1632             return BCM_E_MEMORY;
   1633         }
   1634 
   1635         SOC_ESW_ECMP_LOCK(unit);
   1636         sal_memset(mem_array, 0, alloc_sz);
   1637         /* Calculate Base_ptr table index. */
   1638         grp_info.ecmp_grp = ecmp;
   1639         rv = soc_esw_ecmp_protected_grp_get(unit, &grp_info, mem_array);
   1640         if (rv != BCM_E_NONE) {
   1641             sal_free(mem_array);
   1642             SOC_ESW_ECMP_UNLOCK(unit);
   1643             return rv;
   1644         }
   1645     }
   1646 #endif /* BCM_TRIDENT3_SUPPORT */
   1647 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1648 
   1649     for (i = 0; i < count; i++) {
   1650         if (index >= 0 && index < count && index != i) {
   1651             continue;
   1652         }
   1653 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1654 #if defined(BCM_TRIDENT3_SUPPORT)
   1655         if (protected_ecmp == 1) {
   1656             nhi = mem_array[i].nh;
   1657             if (nhi == nh_index) {
   1658                 mem_array[i].prot_nh = 0;
   1659                 mem_array[i].prot_grp = 0;
   1660             } else { /* Mismatch between offset and nh_index */
   1661                 if (index == i) {
   1662                     sal_free(mem_array);
   1663                     SOC_ESW_ECMP_UNLOCK(unit);
   1664                     return BCM_E_PARAM;
   1665                 }
   1666             }
   1667         } else
   1668 #endif /* BCM_TRIDENT3_SUPPORT */
   1669 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1670 
   1671         {
   1672             BCM_IF_ERROR_RETURN(
   1673                 soc_mem_read(unit, INITIAL_L3_ECMPm,
   1674                              MEM_BLOCK_ANY, base_ptr + i, hw_buf));
   1675 
   1676             nhi = soc_mem_field32_get(unit, INITIAL_L3_ECMPm, hw_buf,
   1677                                       NEXT_HOP_INDEXf);
   1678             if (nhi == nh_index) {
   1679                 soc_mem_field32_set(unit, INITIAL_L3_ECMPm, hw_buf,
   1680                                     PROT_NEXT_HOP_INDEXf, 0);
   1681                 soc_mem_field32_set(unit, INITIAL_L3_ECMPm, hw_buf,
   1682                                     PROT_GROUPf, 0);
   1683                 BCM_IF_ERROR_RETURN(
   1684                     soc_mem_write(unit, INITIAL_L3_ECMPm,
   1685                                   MEM_BLOCK_ANY, base_ptr + i, hw_buf));
   1686             } else { /* Mismatch between offset and nh_index */
   1687                 if (index == i) {
   1688                     return BCM_E_PARAM;
   1689                 }
   1690             }
   1691         }
   1692     }
   1693 
   1694 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
   1695 #if defined(BCM_TRIDENT3_SUPPORT)
   1696     if (protected_ecmp == 1) {
   1697         soc_esw_ecmp_group_info_t_init(&grp_info);
   1698         grp_info.ecmp_grp = ecmp;
   1699         grp_info.ecmp_member_base = base_ptr;
   1700         grp_info.max_paths = ecmp_max_paths;
   1701         rv = soc_esw_ecmp_protected_grp_add(unit, &grp_info, mem_array);
   1702         if (rv != BCM_E_NONE) {
   1703             sal_free(mem_array);
   1704             SOC_ESW_ECMP_UNLOCK(unit);
   1705             return rv;
   1706         }
   1707         sal_free(mem_array);
   1708         SOC_ESW_ECMP_UNLOCK(unit);
   1709 
   1710         if (base_ptr != grp_info.ecmp_member_base) {
   1711             ecmp_count_entry_t l3_ecmp_count_entry;
   1712             initial_l3_ecmp_group_entry_t initial_l3_ecmp_group_entry;
   1713 
   1714             BCM_XGS3_L3_ENT_REF_CNT_DEC(BCM_XGS3_L3_TBL_PTR(unit, ecmp),
   1715                                         base_ptr, ecmp_max_paths);
   1716             base_ptr = grp_info.ecmp_member_base;
   1717             BCM_XGS3_L3_ENT_REF_CNT_INC(BCM_XGS3_L3_TBL_PTR(unit, ecmp),
   1718                                         base_ptr, ecmp_max_paths);
   1719 
   1720             sal_memset(&l3_ecmp_count_entry, 0, sizeof(l3_ecmp_count_entry));
   1721             sal_memset(&initial_l3_ecmp_group_entry, 0, sizeof(initial_l3_ecmp_group_entry));
   1722 
   1723             SOC_IF_ERROR_RETURN(
   1724                 READ_INITIAL_L3_ECMP_GROUPm(unit, MEM_BLOCK_ANY,
   1725                                             ecmp, &initial_l3_ecmp_group_entry));
   1726             soc_INITIAL_L3_ECMP_GROUPm_field32_set(unit, &initial_l3_ecmp_group_entry,
   1727                                                    BASE_PTRf, base_ptr);
   1728             SOC_IF_ERROR_RETURN(
   1729                 WRITE_INITIAL_L3_ECMP_GROUPm(unit, MEM_BLOCK_ALL,
   1730                                              ecmp, &initial_l3_ecmp_group_entry));
   1731             SOC_IF_ERROR_RETURN(
   1732                 READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY,
   1733                                     ecmp, &l3_ecmp_count_entry));
   1734             soc_L3_ECMP_COUNTm_field32_set(unit, &l3_ecmp_count_entry,
   1735                                            BASE_PTRf, base_ptr);
   1736             SOC_IF_ERROR_RETURN(
   1737                 WRITE_L3_ECMP_COUNTm(unit, MEM_BLOCK_ALL,
   1738                                      ecmp, &l3_ecmp_count_entry));
   1739         }
   1740     }
   1741 #endif /* BCM_TRIDENT3_SUPPORT */
   1742 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
   1743 
   1744     return BCM_E_NONE;
   1745 }
   1746 
   1747 /*
   1748  * Function:
   1749  *    bcm_tr2_failover_id_check
   1750  * Purpose:
   1751  *    Check Failover identifier
   1752  * Parameters:
   1753  *    IN :  unit
   1754  *    IN :  failover_id
   1755  * Returns:
   1756  *    BCM_E_XXX
   1757  */
   1758 int
   1759 bcm_tr2_failover_id_check(int unit, bcm_failover_t failover_id)
   1760 {
   1761     int num_count;
   1762 #if defined(BCM_SABER2_SUPPORT)
   1763     int type;
   1764     _BCM_GET_FAILOVER_TYPE(failover_id, type);
   1765     if (type & _BCM_FAILOVER_1_1_MC_PROTECTION_MODE) {
   1766         _BCM_GET_FAILOVER_ID(failover_id);
   1767         num_count = 2 * soc_mem_index_count(unit, MMU_INITIAL_NHOP_TBLm);
   1768         if (failover_id > 0 && failover_id < num_count) {
   1769             return (BCM_E_NONE);
   1770         }
   1771     } else 
   1772 #endif
   1773     {
   1774 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_APACHE_SUPPORT)
   1775        if (soc_feature(unit, soc_feature_hierarchical_protection)) {
   1776             num_count = soc_mem_index_count(unit, TX_PROT_GROUP_1_1_TABLEm);
   1777         } else if (soc_feature(unit, soc_feature_td2p_mpls_linear_protection)) {
   1778             num_count = soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm);
   1779         } else
   1780 #endif
   1781 #if defined(BCM_TOMAHAWK2_SUPPORT)
   1782         if (SOC_IS_TOMAHAWK2(unit)) {
   1783             num_count = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) *
   1784                          BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY);
   1785         } else
   1786 #endif
   1787         {
   1788             num_count = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
   1789         }
   1790         if (failover_id > 0 && failover_id < num_count) {
   1791             return (BCM_E_NONE);
   1792         }
   1793     }
   1794     return (BCM_E_PARAM);
   1795 }
   1796 
   1797 /*
   1798  * Function:
   1799  *    bcm_tr2_failover_egr_check
   1800  * Purpose:
   1801  *    Check Failover for Egress Object
   1802  * Parameters:
   1803  *    IN :  unit
   1804  *    IN :  Egress Object
   1805  * Returns:
   1806  *    BCM_E_XXX
   1807  */
   1808 
   1809 
   1810 int
   1811 bcm_tr2_failover_egr_check (int unit, bcm_l3_egress_t  *egr)
   1812 {
   1813     if (egr->failover_id > 0 && egr->failover_id < 1024) {
   1814         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egr->failover_if_id) || 
   1815             BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, egr->failover_if_id)) {
   1816              return (BCM_E_NONE);
   1817         }
   1818     }
   1819     return (BCM_E_PARAM);
   1820 }
   1821 
   1822 /*
   1823  * Function:
   1824  *    bcm_tr2_failover_mpls_check
   1825  * Purpose:
   1826  *    Check for failover enable - MPLS port
   1827  * Parameters:
   1828  *    IN :  unit
   1829  *    IN :  Egress Object
   1830  * Returns:
   1831  *    BCM_E_XXX
   1832  */
   1833 
   1834 
   1835 int
   1836 bcm_tr2_failover_mpls_check (int unit, bcm_mpls_port_t  *mpls_port)
   1837 {
   1838     int failover_vp = -1;
   1839 
   1840     if ( ( (mpls_port->failover_id) > 0)  &&  ( (mpls_port->failover_id) < 1024) ) {
   1841          /* Get egress next-hop index from Failover MPLS gport */
   1842          failover_vp = BCM_GPORT_MPLS_PORT_ID_GET(mpls_port->failover_port_id);
   1843          if (failover_vp == -1) {
   1844              return BCM_E_PARAM;
   1845          }
   1846          if ( (failover_vp >= 1)  && (failover_vp < soc_mem_index_count(unit, SOURCE_VPm)) ) {
   1847              return BCM_E_NONE;
   1848          }
   1849     }
   1850     return BCM_E_PARAM;
   1851 }
   1852 
   1853 #ifndef BCM_SW_STATE_DUMP_DISABLE
   1854 /*
   1855  * Function:
   1856  *     _bcm_tr2_failover_sw_dump
   1857  * Purpose:
   1858  *     Displays State information maintained by software
   1859  *     for 'Failover' module.
   1860  * Parameters:
   1861  *     unit - Device unit number
   1862  * Returns:
   1863  *     Void
   1864  */
   1865 void
   1866 _bcm_tr2_failover_sw_dump(int unit)
   1867 {
   1868     int  i;
   1869     int  num_entry = 0;
   1870 
   1871 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_APACHE_SUPPORT)
   1872     if (soc_feature(unit, soc_feature_hierarchical_protection)) {
   1873         num_entry = (soc_mem_index_count(unit, TX_PROT_GROUP_1_1_TABLEm) *
   1874                      BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY);
   1875     } else if (soc_feature(unit, soc_feature_td2p_mpls_linear_protection)) {
   1876         num_entry = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) *
   1877                      BCM_TD2P_MPLS_PS_NUM_GROUPS_PER_ENTRY);
   1878     } else
   1879 #endif
   1880 #if defined (BCM_TOMAHAWK2_SUPPORT)
   1881     if (SOC_IS_TOMAHAWK2(unit)) {
   1882         num_entry = (soc_mem_index_count(unit, TX_INITIAL_PROT_GROUP_TABLEm) *
   1883                      BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY);
   1884     } else
   1885 #endif /* BCM_TOMAHAWK2_SUPPORT */
   1886     {
   1887         num_entry = soc_mem_index_count(unit, INITIAL_PROT_GROUP_TABLEm);
   1888     }
   1889 
   1890     LOG_CLI((BSL_META_U(unit,
   1891                         "Protection Group usage bitmap:\n")));
   1892 
   1893     for (i = 0; i < num_entry; i++) {
   1894          if (_BCM_FAILOVER_PROT_GROUP_MAP_USED_GET(unit, i)) {
   1895              LOG_CLI((BSL_META_U(unit,
   1896                                  "%d "), i));     
   1897          }
   1898     }
   1899     LOG_CLI((BSL_META_U(unit,
   1900                         "\n")));
   1901 #if defined (BCM_TOMAHAWK2_SUPPORT)
   1902     if (SOC_IS_TOMAHAWK2(unit)) {
   1903         num_entry = (soc_mem_index_count(unit, RX_PROT_GROUP_TABLEm) *
   1904                      BCM_TH2_FAILOVER_PROT_GROUPS_PER_ENTRY);
   1905         LOG_CLI((BSL_META_U(unit,
   1906                             "Ingress Protection Group usage bitmap:\n")));
   1907     
   1908         for (i = 0; i < num_entry; i++) {
   1909              if (_BCM_FAILOVER_INGRESS_PROT_GROUP_MAP_USED_GET(unit, i)) {
   1910                  LOG_CLI((BSL_META_U(unit,
   1911                                      "%d "), i));     
   1912              }
   1913         }
   1914         LOG_CLI((BSL_META_U(unit,
   1915                             "\n")));    
   1916     }
   1917 #endif /* BCM_TOMAHAWK2_SUPPORT */
   1918     return;
   1919 }
   1920 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   1921 
   1922 #endif /* BCM_TRIUMPH2_SUPPORT && INCLUDE_L3 */
   1923