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


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