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


      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 TH3 specific failover APIs
      9  *          with fixed next hop offset.
     10  */
     11 
     12 
     13 #include <shared/bsl.h>
     14 
     15 #include <soc/defs.h>
     16 #include <sal/core/libc.h>
     17 
     18 #if defined(INCLUDE_L3)
     19 #if defined(BCM_TOMAHAWK3_SUPPORT)
     20 
     21 #include <soc/drv.h>
     22 #include <soc/mem.h>
     23 #include <soc/util.h>
     24 #include <soc/debug.h>
     25 
     26 #include <bcm/types.h>
     27 #include <bcm/error.h>
     28 #include <bcm/module.h>
     29 #include <bcm/failover.h>
     30 
     31 #include <bcm_int/esw/tomahawk3.h>
     32 #include <bcm_int/esw/failover.h>
     33 
     34 #define REPLACE_ENABLE_BITMAP_SIZE 128
     35 
     36 #define FAILOVER_LOCK(u)   sal_mutex_take(FAILOVER_INFO(u)->failover_mutex, sal_sem_FOREVER)
     37 #define FAILOVER_UNLOCK(u) sal_mutex_give(FAILOVER_INFO(u)->failover_mutex)
     38 
     39 /*
     40  * Function:
     41  *      bcm_th3_failover_hw_clear
     42  * Purpose:
     43  *      Cleart Failover Hw memory
     44  * Parameters:
     45  *      unit     - Device Number
     46  * Returns:
     47  *      BCM_E_XXX
     48  */
     49 static int
     50 bcm_th3_failover_hw_clear(int unit)
     51 {
     52     uint8 *mbuf;
     53     int size, rv = BCM_E_NONE;
     54     soc_mem_t mem;
     55 
     56     mem = PROT_NHI_TABLE_1m;
     57     size = SOC_MEM_TABLE_BYTES(unit, mem);
     58     mbuf = soc_cm_salloc(unit, size, "failover_mem");
     59     if (mbuf != NULL) {
     60         sal_memset(mbuf, 0, size);
     61         FAILOVER_LOCK(unit);
     62         rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ANY,
     63                                  soc_mem_index_min(unit, mem),
     64                                  soc_mem_index_max(unit, mem), mbuf);
     65         FAILOVER_UNLOCK(unit);
     66         soc_cm_sfree(unit, mbuf);
     67 
     68     } else {
     69         rv = BCM_E_MEMORY;
     70         LOG_ERROR(BSL_LS_SOC_L3,
     71                   (BSL_META_U(unit, "FAILOVER HW mem %s clear failed.\n"),
     72                    SOC_MEM_NAME(unit, mem)));
     73     }
     74 
     75     return rv;
     76 }
     77 
     78 /*
     79  * Function:
     80  *      bcm_th3_failover_cleanup
     81  * Purpose:
     82  *      DeInit  the Failover software module
     83  * Parameters:
     84  *      unit     - Device Number
     85  * Returns:
     86  *      BCM_E_XXX
     87  */
     88 int
     89 bcm_th3_failover_cleanup(int unit)
     90 {
     91     _bcm_failover_bookkeeping_t *failover_info = FAILOVER_INFO(unit);
     92     int rv = BCM_E_UNAVAIL;
     93 
     94     if (!failover_info->initialized) {
     95         return (BCM_E_NONE);
     96     }
     97 
     98     if (!SOC_HW_ACCESS_DISABLE(unit)) {
     99         rv = bcm_th3_failover_hw_clear(unit);
    100     }
    101 
    102     /* Destroy protection mutex. */
    103     sal_mutex_destroy(failover_info->failover_mutex);
    104 
    105     /* Mark the state as uninitialized */
    106     failover_info->initialized = FALSE;
    107     failover_info->prot_offset = 0;
    108 
    109     return rv;
    110 }
    111 
    112 /*
    113  * Function:
    114  *      bcm_th3_failover_init
    115  * Purpose:
    116  *      Initialize the Failover software module
    117  * Parameters:
    118  *      unit     - (IN) Device Number
    119  * Returns:
    120  *      BCM_E_XXX
    121  */
    122 int
    123 bcm_th3_failover_init(int unit)
    124 {
    125     int rv = BCM_E_NONE;
    126     uint32 rval = 0;
    127     int prot_offset;
    128     _bcm_failover_bookkeeping_t *failover_info = FAILOVER_INFO(unit);
    129 
    130     if (failover_info->initialized) {
    131         BCM_IF_ERROR_RETURN(bcm_th3_failover_cleanup(unit));
    132     }
    133 
    134     /* Create Failover  protection mutex. */
    135     failover_info->failover_mutex = sal_mutex_create("failover_mutex");
    136     if (!failover_info->failover_mutex) {
    137         return BCM_E_MEMORY;
    138     }
    139 
    140     if (soc_property_get(unit, spn_FAILOVER_FIXED_NH_OFFSET_ENABLE, 0)) {
    141 
    142         /* Fixed protection NHI offset = half of egr_l3_next_hop size (16384) */
    143         prot_offset = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm) >> 1;
    144         if (prot_offset == 0) {
    145             return BCM_E_MEMORY;
    146         }
    147 
    148         /* Configure PROT_OFFSETf on PROT_NHI_CONFIGr */
    149         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, PROT_NHI_CONFIGr,
    150                                           REG_PORT_ANY, 0, &rval));
    151         soc_reg_field_set(unit, PROT_NHI_CONFIGr, &rval,
    152                           PROT_OFFSETf, prot_offset);
    153         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, PROT_NHI_CONFIGr,
    154                                           REG_PORT_ANY, 0, rval));
    155         
    156         /* Clear failover Hw mem: PROT_NHI_TABLE_1m */
    157         if (!SOC_WARM_BOOT(unit)) {
    158             rv = bcm_th3_failover_hw_clear(unit);
    159         }
    160         BCM_IF_ERROR_RETURN(rv);
    161 
    162         failover_info->prot_offset = prot_offset;
    163         cli_out("Failover enabled with fixed next hop offset %d\n",
    164                 prot_offset);
    165     } else {
    166         failover_info->prot_offset = 0;
    167     }
    168 
    169     failover_info->initialized = TRUE;
    170 
    171     return rv;
    172 }
    173 
    174 /*
    175  * Function:
    176  *      bcm_th3_failover_egress_set
    177  * Purpose:
    178  *      This function can be used to set the protected NH for
    179  *      the specified primary nexthop (intf)
    180  * Parameters:
    181  *      unit            - (IN) Device Number
    182  *      intf            - (IN) Primary NH interface
    183  *      failover_egr    - (IN/OUT) Egress object to be used as the
    184  *                        protection nexthop for primary NH.
    185  * Returns:
    186  *      BCM_E_XXX
    187  */
    188 int
    189 bcm_th3_failover_egress_set(int unit, bcm_if_t intf,
    190                             bcm_l3_egress_t *failover_egr)
    191 {
    192     int rv = BCM_E_NONE;
    193     uint32 flags;
    194     bcm_if_t prot_intf;
    195 
    196     if (!FAILOVER_INFO(unit)->initialized) {
    197         return BCM_E_INIT;
    198     }
    199 
    200     if (FAILOVER_INFO(unit)->prot_offset == 0) {
    201         return BCM_E_CONFIG;
    202     }
    203 
    204     if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf) &&
    205         !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) {
    206         return BCM_E_PARAM;
    207     }
    208 
    209     /* Set prot_intf with fixed offset from primary intf */
    210     prot_intf = intf + FAILOVER_INFO(unit)->prot_offset;
    211 
    212     /* Create protected egress nh BCM_L3_WITH_ID flags */
    213     flags = (BCM_L3_WITH_ID | BCM_L3_REPLACE);
    214 
    215     /* For TH3 failover_id shouldn't be used by user. It's used internally
    216        only to distinguish between primary_intf and prot_intf egress creation.
    217        This flag bit will be clear in bcm_xgs3_l3_egress_create. */
    218     failover_egr->failover_id |= _FAILOVER_FIXED_NH_OFFSET_ON;
    219     rv = bcm_esw_l3_egress_create(unit, flags, failover_egr, &prot_intf);
    220 
    221     return rv;
    222 }
    223 
    224 /*
    225  * Function:
    226  *      bcm_th3_failover_egress_get
    227  * Purpose:
    228  *      This function can be used to retrieve the protected NH for
    229  *      the specified primary nexthop (intf)
    230  * Parameters:
    231  *      unit            - (IN) Device Number
    232  *      intf            - (IN) Primary NH interface
    233  *      failover_egr    - (OUT) Egress object used as the
    234  *                        protection nexthop for primary NH.
    235  * Returns:
    236  *      BCM_E_XXX
    237  */
    238 int
    239 bcm_th3_failover_egress_get(int unit, bcm_if_t intf,
    240                             bcm_l3_egress_t *failover_egr)
    241 {
    242     int rv = BCM_E_NONE;
    243     bcm_if_t prot_intf;
    244 
    245     if (!FAILOVER_INFO(unit)->initialized) {
    246         return BCM_E_INIT;
    247     }
    248 
    249     if (FAILOVER_INFO(unit)->prot_offset == 0) {
    250         return BCM_E_CONFIG;
    251     }
    252 
    253     if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf) &&
    254         !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) {
    255         return BCM_E_PARAM;
    256     }
    257 
    258     /* Set prot_intf with fixed offset from primary intf */
    259     prot_intf = intf + FAILOVER_INFO(unit)->prot_offset;
    260 
    261     bcm_l3_egress_t_init(failover_egr);
    262 
    263     rv = bcm_esw_l3_egress_get(unit, prot_intf, failover_egr);
    264 
    265     return rv;
    266 }
    267 
    268 /*
    269  * Function:
    270  *      bcm_th3_failover_egress_clear
    271  * Purpose:
    272  *      This function can be used to clear the protected NH set earlier
    273  *      for the specified primary nexthop (intf)
    274  * Parameters:
    275  *      unit            - (IN) Device Number
    276  *      intf            - (IN) Primary NH interface
    277  * Returns:
    278  *      BCM_E_XXX
    279  */
    280 int
    281 bcm_th3_failover_egress_clear(int unit, bcm_if_t intf)
    282 {
    283     int rv = BCM_E_NONE;
    284     bcm_if_t prot_intf;
    285 
    286     if (!FAILOVER_INFO(unit)->initialized) {
    287         return BCM_E_INIT;
    288     }
    289 
    290     if (FAILOVER_INFO(unit)->prot_offset == 0) {
    291         return BCM_E_CONFIG;
    292     }
    293 
    294     if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf) &&
    295         !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) {
    296         return BCM_E_PARAM;
    297     }
    298 
    299     /* Set prot_intf with fixed offset from primary intf */
    300     prot_intf = intf + FAILOVER_INFO(unit)->prot_offset;
    301 
    302     /* First disable egress status for prot_intf (i.e., use primary intf) */
    303     rv = bcm_th3_failover_egress_status_set(unit, intf, FALSE);
    304 
    305     if (BCM_SUCCESS(rv)) {
    306         rv = bcm_esw_l3_egress_destroy(unit, prot_intf);
    307     }
    308 
    309     return rv;
    310 }
    311 
    312 /*
    313  * Function:
    314  *      bcm_th3_failover_egress_status_set
    315  * Purpose:
    316  *      This function controls (set/clear) the active state of use of
    317  *      primary NH or protected NH
    318  * Parameters:
    319  *      unit            - (IN) Device Number
    320  *      intf            - (IN) Primary NH interface
    321  *      enable          - (IN) Enable=True for use of protected NH,
    322  *                        Enable=False for use of Primary NH (intf).
    323  * Returns:
    324  *      BCM_E_XXX
    325  */
    326 int
    327 bcm_th3_failover_egress_status_set(int unit, bcm_if_t intf, int enable)
    328 {
    329     int rv = BCM_E_NONE;
    330     int nh_idx, index, bit_pos;
    331     uint32 entry[5], data[5];
    332     soc_mem_t mem = PROT_NHI_TABLE_1m;
    333 
    334     /*  Make sure module was initialized. */
    335     if (!BCM_XGS3_L3_INITIALIZED(unit) ||
    336         !FAILOVER_INFO(unit)->initialized) {
    337         return (BCM_E_INIT);
    338     }
    339 
    340     if (FAILOVER_INFO(unit)->prot_offset == 0) {
    341         return (BCM_E_CONFIG);
    342     }
    343 
    344     /* Check l3 switching mode. */
    345     if (!(BCM_XGS3_L3_EGRESS_MODE_ISSET(unit))) {
    346         return (BCM_E_DISABLED);
    347     }
    348 
    349     /* Input parameters check. */
    350     if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf) &&
    351         !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) {
    352         return (BCM_E_PARAM);
    353     }
    354 
    355     /* Calculate next hop index. */
    356     if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf)) {
    357         nh_idx = intf - BCM_XGS3_EGRESS_IDX_MIN(unit);
    358     } else {
    359         nh_idx = intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
    360     }
    361 
    362     /* Validate primary nh_idx */
    363     if (nh_idx >= FAILOVER_INFO(unit)->prot_offset) {
    364         return BCM_E_PARAM;
    365     }
    366 
    367     /* Calculate PROT_NHI_TABLE_1: index, and REPLACE_ENABLE_BITMAP: bit position */
    368     index = nh_idx / REPLACE_ENABLE_BITMAP_SIZE;
    369     bit_pos = nh_idx % REPLACE_ENABLE_BITMAP_SIZE;
    370 
    371     FAILOVER_LOCK(unit);
    372     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry);
    373     if (BCM_SUCCESS(rv)) {
    374         soc_mem_field_get(unit, mem, entry, REPLACE_ENABLE_BITMAPf, data);
    375         SHR_BITWRITE(data, bit_pos, enable);
    376         soc_mem_field_set(unit, mem, entry, REPLACE_ENABLE_BITMAPf, data);
    377         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry);
    378     }
    379     FAILOVER_UNLOCK(unit);
    380 
    381     return rv;
    382 }
    383 
    384 /*
    385  * Function:
    386  *      bcm_th3_failover_egress_status_get
    387  * Purpose:
    388  *      This function retrieves the current status of use of
    389   *      primary NH or protected NH
    390  * Parameters:
    391  *      unit            - (IN) Device Number
    392  *      intf            - (IN) Primary NH interface
    393  *      enable          - (OUT) Enable=True for use of protected NH,
    394  *                        Enable=False for use of Primary NH (intf).
    395  * Returns:
    396  *      BCM_E_XXX
    397  */
    398 int
    399 bcm_th3_failover_egress_status_get(int unit, bcm_if_t intf, int *enable)
    400 {
    401     int rv = BCM_E_NONE;
    402     int nh_idx, index, bit_pos;
    403     uint32 entry[5], data[5];
    404     soc_mem_t mem = PROT_NHI_TABLE_1m;
    405 
    406     /*  Make sure module was initialized. */
    407     if (!BCM_XGS3_L3_INITIALIZED(unit) ||
    408         !FAILOVER_INFO(unit)->initialized) {
    409         return (BCM_E_INIT);
    410     }
    411 
    412     if (FAILOVER_INFO(unit)->prot_offset == 0) {
    413         return (BCM_E_CONFIG);
    414     }
    415 
    416     /* Check l3 switching mode. */
    417     if (!(BCM_XGS3_L3_EGRESS_MODE_ISSET(unit))) {
    418         return (BCM_E_DISABLED);
    419     }
    420 
    421     /* Input parameters check. */
    422     if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf) &&
    423         !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) {
    424         return (BCM_E_PARAM);
    425     }
    426 
    427     /* Calculate next hop index. */
    428     if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, intf)) {
    429         nh_idx = intf - BCM_XGS3_EGRESS_IDX_MIN(unit);
    430     } else {
    431         nh_idx = intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
    432     }
    433 
    434     /* Validate primary nh_idx */
    435     if ((nh_idx >= FAILOVER_INFO(unit)->prot_offset) || (enable == NULL)) {
    436         return BCM_E_PARAM;
    437     }
    438 
    439     /* Calculate PROT_NHI_TABLE_1: index, and REPLACE_ENABLE_BITMAP: bit position */
    440     index = nh_idx / REPLACE_ENABLE_BITMAP_SIZE;
    441     bit_pos = nh_idx % REPLACE_ENABLE_BITMAP_SIZE;
    442 
    443     FAILOVER_LOCK(unit);
    444     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry);
    445     if (BCM_SUCCESS(rv)) {
    446         soc_mem_field_get(unit, mem, entry, REPLACE_ENABLE_BITMAPf, data);
    447         *enable = (SHR_BITGET(data, bit_pos) ? 1 : 0);
    448     }
    449     FAILOVER_UNLOCK(unit);
    450 
    451     return rv;
    452 }
    453 
    454 #endif /* defined(BCM_TOMAHAWK3_SUPPORT) */
    455 #endif /* defined(INCLUDE_L3) */