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

range.c (70754B)


      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:    range.c
      8  * Purpose: Manages RANGE_CHECKER (IFP_RANGE_CHECK)
      9  */
     10 
     11 #include <shared/bsl.h>
     12 #include <soc/drv.h>
     13 #include <soc/scache.h>
     14 
     15 #include <bcm/range.h>
     16 #include <bcm/error.h>
     17 #include <bcm/module.h>
     18 #include <bcm_int/esw/range.h>
     19 #include <bcm_int/esw/switch.h>
     20 #include <bcm_int/esw/xgs4.h>
     21 #include <bcm_int/esw_dispatch.h>
     22 
     23 #define RANGE_MALLOC(_p_, _t_, _sz_, _desc_)                \
     24     do {                                                    \
     25         if (!_p_) {                                         \
     26             (_p_) = (_t_ *) sal_alloc((_sz_), (_desc_));    \
     27         }                                                   \
     28         if (_p_) {                                          \
     29             sal_memset((_p_), 0, (_sz_));                   \
     30         }                                                   \
     31     } while(0)
     32 
     33 #define BCM_IF_NULL_RETURN_PARAM(_p_) \
     34     do {                                                    \
     35         if ((_p_) == NULL) {                                \
     36             return BCM_E_PARAM;                             \
     37         }                                                   \
     38     } while(0)
     39 
     40 /* Global Range control structure pointers */
     41 bcmi_xgs5_range_ctrl_t *range_control[BCM_MAX_NUM_UNITS];
     42 
     43 /* STATIC function declarations */
     44 STATIC int bcmi_xgs5_range_ctrl_init(int unit);
     45 
     46 STATIC int bcmi_xgs5_range_hw_init(int unit);
     47 
     48 STATIC int bcmi_xgs5_range_ctrl_free(int unit, bcmi_xgs5_range_ctrl_t *rangec);
     49 
     50 soc_field_t range_group_fields[] =
     51            {
     52                 IFP_RANGE_CHECK_MASK_0f,
     53                 IFP_RANGE_CHECK_MASK_1f,
     54                 IFP_RANGE_CHECK_MASK_2f,
     55                 IFP_RANGE_CHECK_MASK_3f,
     56                 IFP_RANGE_CHECK_MASK_4f,
     57                 IFP_RANGE_CHECK_MASK_5f,
     58                 IFP_RANGE_CHECK_MASK_6f,
     59                 IFP_RANGE_CHECK_MASK_7f,
     60                 IFP_RANGE_CHECK_MASK_8f,
     61                 IFP_RANGE_CHECK_MASK_9f,
     62                 IFP_RANGE_CHECK_MASK_10f,
     63                 IFP_RANGE_CHECK_MASK_11f,
     64                 IFP_RANGE_CHECK_MASK_12f,
     65                 IFP_RANGE_CHECK_MASK_13f,
     66                 IFP_RANGE_CHECK_MASK_14f,
     67                 IFP_RANGE_CHECK_MASK_15f
     68            };
     69 
     70 
     71 /*  Function    :   bcmi_xgs5_range_ctrl_free
     72  *  Purpose     :   Free Range control structure
     73  *  Parameters  :   unit - (IN) BCM device number
     74  *                  rangec  - (IN)  Range control structure.
     75  *  Returns     :   BCM_E_XXX
     76  */
     77 
     78 STATIC int
     79 bcmi_xgs5_range_ctrl_free(int unit, bcmi_xgs5_range_ctrl_t *rangec)
     80 {
     81     LOG_DEBUG(BSL_LS_BCM_RANGE,
     82                 (BSL_META_U(unit,
     83                             "bcmi_xgs5_range_ctrl_free\n")));
     84     if (NULL == rangec) {
     85         /* Already freed */
     86         return BCM_E_NONE;
     87     }
     88 
     89     /* Free mutex */
     90     if (NULL != rangec->range_mutex) {
     91         sal_mutex_destroy(rangec->range_mutex);
     92         rangec->range_mutex = NULL;
     93     }
     94 
     95     /* Free the range control structure */
     96     sal_free(rangec);
     97 
     98     range_control[unit] = NULL;
     99 
    100     return BCM_E_NONE;
    101 }
    102 
    103 /*  Function    :   bcmi_xgs5_range_ctrl_init
    104  *  Purpose     :   Allocate and Initialise range control structure.
    105  *  Parameters  :   unit     - (IN)     BCM unit
    106  *  Returns     :   BCM_E_XXX
    107  */
    108 STATIC int
    109 bcmi_xgs5_range_ctrl_init(int unit)
    110 {
    111     int                     alloc_sz = 0;           /* Allocation size */
    112     soc_mem_t               range_mem = INVALIDm;   /* Range Checker Memory ID */
    113     bcmi_xgs5_range_ctrl_t  *range_ctrl = NULL;     /* Range Control Structure */
    114 
    115     range_mem = IFP_RANGE_CHECKm;
    116 
    117     if (range_control[unit] != NULL) {
    118         bcmi_xgs5_range_detach(unit);
    119     }
    120 
    121     if (range_control[unit] != NULL) {
    122         (void)bcmi_xgs5_range_ctrl_free(unit, range_control[unit]);
    123     }
    124 
    125     /* Allocating memory of Range control Structure */
    126     alloc_sz = sizeof(bcmi_xgs5_range_ctrl_t);
    127     RANGE_MALLOC(range_ctrl, bcmi_xgs5_range_ctrl_t, alloc_sz, "range control");
    128     if(range_ctrl == NULL) {
    129         LOG_ERROR(BSL_LS_BCM_RANGE,
    130                 (BSL_META_U(unit,
    131                             "Range Module(unit %d) Error: Module alloc failed.\n"),
    132                  unit));
    133         return BCM_E_MEMORY;
    134     }
    135 
    136     range_control[unit] = range_ctrl;
    137 
    138     /* Create Range Mutex*/
    139     if(range_ctrl->range_mutex == NULL) {
    140         range_ctrl->range_mutex = sal_mutex_create("range_mutex");
    141         if (range_ctrl->range_mutex == NULL) {
    142             /*Free range ctrl structure. */
    143             (void)bcmi_xgs5_range_ctrl_free(unit, range_ctrl);
    144             LOG_ERROR(BSL_LS_BCM_RANGE,
    145                     (BSL_META_U(unit,
    146                                 "Range Module(unit %d) Error: Mutex alloc failed.\n"),
    147                      unit));
    148             return BCM_E_MEMORY;
    149         }
    150     }
    151 
    152     range_ctrl->range_mem = range_mem;
    153 
    154     range_ctrl->max_ranges = _RANGE_ID_MAX(unit);
    155 
    156     range_ctrl->max_groups = _RANGE_GROUP_MAX(unit);
    157 
    158     range_ctrl->range_used_by_module = RANGE_USED_BY_FIELD_MODULE;
    159 
    160     if (soc_feature(unit, soc_feature_range_check_group_support)) {
    161         range_ctrl->range_used_by_module = RANGE_USED_BY_RANGE_MODULE;
    162     }
    163 
    164     sal_memset(range_ctrl->range_group_used_bitmap, 0,
    165                (sizeof(SHR_BITDCL) * SOC_MAX_NUM_PIPES));
    166 
    167     return BCM_E_NONE;
    168 }
    169 
    170 /*  Function    :   bcmi_xgs5_range_hw_init
    171  *  Purpose     :   Clear hardware Range Checker memory
    172  *  Parameters  :   unit - (IN) BCM device number.
    173  *  Returns     :   BCM_E_XXX
    174  */
    175 STATIC int
    176 bcmi_xgs5_range_hw_init(int unit)
    177 {
    178     int rv;         /* Operation return status. */
    179 
    180     /* Clear RANGE_CHECK mem*/
    181     rv = soc_mem_clear(unit, RANGE_CTRL(unit)->range_mem, MEM_BLOCK_ALL, TRUE);
    182     SOC_IF_ERROR_RETURN(rv);
    183 
    184     return BCM_E_NONE;
    185 }
    186 
    187 #if defined (BCM_WARM_BOOT_SUPPORT)
    188 #define BCM_WB_VERSION_1_0     SOC_SCACHE_VERSION(1, 0)
    189 #define BCM_WB_VERSION_1_1     SOC_SCACHE_VERSION(1, 1)
    190 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_1
    191 
    192 /*  Function    :   bcmi_xgs5_range_wb_scache_size_get_1_0
    193  *  Purpose     :   Returns required scache size in bytes for version = 1_0
    194  *  Parameters  :   unit      - (IN) BCM device number.
    195  *                  req_scache_size -(OUT) Required scache size
    196  *  Returns     :   BCM_E_XXX
    197  */
    198 STATIC int
    199 bcmi_xgs5_range_wb_scache_size_get_1_0(int unit, int *req_scache_size)
    200 {
    201     int         alloc_size = 0;     /* Allocation size */
    202     _range_t    range;              /* Range structure */
    203 
    204     bcmi_xgs5_range_ctrl_t *range_ctrl;
    205 
    206     range_ctrl = RANGE_CTRL(unit);
    207 
    208     /* The following fields from the Range Control Structure needs to
    209      be synced for recovery after Warmboot:
    210      1. range_oper_mode - to know whether the module was operating in
    211                           Per Pipe/ Global Mode to read appropriate
    212                           Memory.
    213      2. num_ranges      - Number of Ranges existing in the System.
    214      3. range_used_by_module - Whether Range resource is being used by
    215                           Field Module or Range Module.*/
    216     alloc_size += sizeof(range_ctrl->range_oper_mode);
    217     alloc_size += sizeof(range_ctrl->num_ranges);
    218     alloc_size += sizeof(range_ctrl->range_used_by_module);
    219 
    220     /* The following fields from the Range Structure needs to
    221        be synced for recovery :
    222      1. Range Id,
    223      2. Range Offset,
    224      3. Range Width,
    225      4. UDF id mapped with the Range,
    226      5. pipe_instance to which this range is mapped to.
    227      Rest all fields in the range structure can be recovered from the Hardware.
    228      */
    229 
    230     alloc_size += RANGE_CTRL(unit)->max_ranges * sizeof(range.rid);
    231     alloc_size += RANGE_CTRL(unit)->max_ranges * sizeof(range.offset);
    232     alloc_size += RANGE_CTRL(unit)->max_ranges * sizeof(range.width);
    233     alloc_size += RANGE_CTRL(unit)->max_ranges * sizeof(range.udf_id);
    234     alloc_size += RANGE_CTRL(unit)->max_ranges * sizeof(range.pipe_instance);
    235 
    236     *req_scache_size = alloc_size;
    237 
    238     return BCM_E_NONE;
    239 }
    240 
    241 /*  Function    :   bcmi_xgs5_range_wb_scache_size_get_1_1
    242  *  Purpose     :   Returns required scache size in bytes for version = 1_1
    243  *  Parameters  :   unit      - (IN) BCM device number.
    244  *                  req_scache_size -(OUT) Required scache size
    245  *  Returns     :   BCM_E_XXX
    246  */
    247 STATIC int
    248 bcmi_xgs5_range_wb_scache_size_get_1_1(int unit, int *req_scache_size)
    249 {
    250 
    251     bcmi_xgs5_range_ctrl_t *range_ctrl;
    252 
    253     range_ctrl = RANGE_CTRL(unit);
    254 
    255     /* The following fields from the Range Control Structure needs to
    256      be synced for recovery after Warmboot:
    257      range_group_used_bitmap - Used HW masks of the range group */
    258 
    259     *req_scache_size += sizeof(range_ctrl->range_group_used_bitmap);
    260 
    261     return BCM_E_NONE;
    262 }
    263 
    264 /*  Function    :   bcmi_xgs5_range_wb_scache_size_get
    265  *  Purpose     :   Returns required scache size
    266  *  Parameters  :   unit      - (IN) BCM device number.
    267  *                  req_scache_size -(OUT) Required scache size
    268  *  Returns     :   BCM_E_XXX
    269  */
    270 STATIC int
    271 bcmi_xgs5_range_wb_scache_size_get(int unit, int *req_scache_size)
    272 {
    273     BCM_IF_ERROR_RETURN(
    274             bcmi_xgs5_range_wb_scache_size_get_1_0(unit, req_scache_size));
    275     BCM_IF_ERROR_RETURN(
    276             bcmi_xgs5_range_wb_scache_size_get_1_1(unit, req_scache_size));
    277 
    278     return BCM_E_NONE;
    279 }
    280 
    281 /*  Function    :   bcmi_xgs5_range_wb_alloc
    282  *  Purpose     :   Allocates required scache size for the Range module recovery
    283  *  Paramters   :   unit      - (IN) BCM device number.
    284  *  Returns     :   BCM_E_XXX
    285  */
    286 STATIC int bcmi_xgs5_range_wb_alloc(int unit)
    287 {
    288     int         rv = BCM_E_NONE;    /* Operation return status. */
    289     int         req_scache_size;    /* Required Scache Size.    */
    290     uint8       *scache_ptr;        /* Scache ptr.              */
    291     soc_scache_handle_t scache_handle;  /* Scache handle.       */
    292 
    293     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_RANGE, 0);
    294 
    295     /*Obtain the required size for scache sync*/
    296     rv = bcmi_xgs5_range_wb_scache_size_get(unit, &req_scache_size);
    297     BCM_IF_ERROR_RETURN(rv);
    298 
    299     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
    300             req_scache_size, &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
    301 
    302     if (BCM_E_NOT_FOUND == rv) {
    303         /* Proceed with Level 1 Warm Boot */
    304         rv = BCM_E_NONE;
    305     }
    306 
    307     return rv;
    308 }
    309 
    310 /*  Function    :   bcmi_xgs5_range_wb_reinit_1_0
    311  *  Purpose     :   Recovers Range warmboot state from scache
    312  *  Parameters  :   unit            - (IN)  Unit number.
    313  *                  scache_ptr      - (IN)  Pointer to scache
    314  *  Returns     :   BCM_E_XXX
    315  */
    316 STATIC int
    317 bcmi_xgs5_range_wb_reinit_1_0(int unit, uint8 **scache_ptr)
    318 {
    319     uint8           *scache_p;          /* Pointer to scache */
    320     soc_mem_t       mem = RANGE_CTRL(unit)->range_mem;  /* Range Checker Memory ID */
    321     int             idx;                /* Range iteration index */
    322     int             index_min;          /* Range memory minimum index */
    323     int             index_max;          /* Range memory maximum index */
    324     uint32          enable;             /* Whether the entry is valid or not.*/
    325     uint32          type;               /* Range checker type. */
    326     uint32          tbl_entry[SOC_MAX_MEM_FIELD_WORDS];  /* Range checker entry buffer. */
    327     _range_t        *range_p;           /* Pointer to a range. */
    328     _range_t        **last_range_p;     /* Pointer to the last range reinit. */
    329     bcm_port_config_t   pc;             /* Port configuration.      */
    330     int             rv;                 /* Operation return value */
    331 
    332     /* Initialize port configuration structure. */
    333     bcm_port_config_t_init(&pc);
    334 
    335     /* Get device port configuration. */
    336     rv = bcm_esw_port_config_get(unit, &pc);
    337     if (BCM_FAILURE(rv)) {
    338         return rv;
    339     }
    340 
    341     scache_p = (uint8 *)(*scache_ptr);
    342 
    343     /* Range module oper mode */
    344     RANGE_CTRL(unit)->range_oper_mode = *scache_p;
    345     scache_p++;
    346 
    347     /* Number of Ranges created */
    348     RANGE_CTRL(unit)->num_ranges = *scache_p;
    349     scache_p++;
    350 
    351     /* Range resource is being used by which module */
    352     RANGE_CTRL(unit)->range_used_by_module = *scache_p;
    353     scache_p++;
    354 
    355     last_range_p = &(RANGE_CTRL(unit)->ranges);
    356     index_min = soc_mem_index_min(unit, mem);
    357     index_max = soc_mem_index_max(unit, mem);
    358 
    359     for (idx = index_min; idx <= index_max; idx ++) {
    360         sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
    361 
    362         /* Create a new range entry for the list */
    363         if ((range_p = sal_alloc(sizeof (*range_p), "range")) == NULL) {
    364             return (BCM_E_MEMORY);
    365         }
    366         sal_memset(range_p, 0, sizeof(_range_t));
    367 
    368         /* Copy Pipe instance */
    369         range_p->pipe_instance = *scache_p;
    370         scache_p++;
    371 
    372         /* Copy the ports bitmap used by the range. */
    373         range_p->ports = pc.all;
    374 
    375         if(RANGE_CTRL(unit)->range_oper_mode == bcmRangeOperModePipeLocal) {
    376             /*Fetch the memory based on the pipe instance. */
    377             if (range_p->pipe_instance < SOC_MAX_NUM_PIPES) {
    378                 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
    379                                     IFP_RANGE_CHECKm,
    380                                     range_p->pipe_instance,
    381                                     &mem));
    382             } else {
    383                 sal_free(range_p);
    384                 return BCM_E_INTERNAL;
    385             }
    386 
    387             /*In Perpipe mode, only that particular pipe's PBMP will be used*/
    388             range_p->ports = pc.per_pipe[range_p->pipe_instance];
    389         }
    390 
    391         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tbl_entry);
    392         if (BCM_FAILURE(rv)) {
    393             sal_free(range_p);
    394             return rv;
    395         }
    396 
    397         soc_mem_field_get(unit, mem, tbl_entry, ENABLEf, &enable);
    398         if (enable == 0) {
    399             sal_free(range_p);
    400             continue;
    401         }
    402         /* Populate the structure */
    403         /* Get the Range Id */
    404         sal_memcpy(&(range_p->rid), scache_p, sizeof(uint32));
    405         scache_p += sizeof(uint32);
    406 
    407         /* Get the UDF Id mapped to the range */
    408         sal_memcpy(&(range_p->udf_id), scache_p, sizeof(bcm_udf_id_t));
    409         scache_p += sizeof(bcm_udf_id_t);
    410 
    411         /* Get the UDF offset */
    412         range_p->offset = *scache_p;
    413         scache_p++;
    414 
    415         /* Get the UDF width */
    416         range_p->width = *scache_p;
    417         scache_p++;
    418 
    419         /* Get the hw_index the range maps to */
    420         range_p->hw_index = idx;
    421 
    422         /* Read the min value from the hw */
    423         soc_mem_field_get(unit, mem, tbl_entry, LOWER_BOUNDSf,
    424                 (uint32 *)&(range_p->min));
    425 
    426         /* Read the max value from the hw */
    427         soc_mem_field_get(unit, mem, tbl_entry, UPPER_BOUNDSf,
    428                 (uint32 *)&(range_p->max));
    429 
    430         /* Read the Range Checker Type from the hw*/
    431         if ((SOC_MEM_FIELD_VALID(unit, mem, FIELD_SELECTf))) {
    432             soc_mem_field_get(unit, mem, tbl_entry, FIELD_SELECTf, (uint32 *)&(range_p->rtype));
    433         } else {
    434             soc_mem_field_get(unit, mem, tbl_entry,
    435                     SOURCE_DESTINATION_SELECTf, &type);
    436             if (type == 0) {
    437                 range_p->rtype = bcmRangeTypeL4SrcPort;
    438             } else if (type == 1) {
    439                 range_p->rtype = bcmRangeTypeL4DstPort;
    440             }
    441         }
    442 
    443         *last_range_p = range_p;
    444         last_range_p = &range_p->next;
    445     }
    446 
    447     return BCM_E_NONE;
    448 }
    449 
    450 /*  Function    :   bcmi_xgs5_range_wb_reinit_1_1
    451  *  Purpose     :   Recovers Range warmboot state from scache
    452  *  Parameters  :   unit            - (IN)  Unit number.
    453  *                  scache_ptr      - (IN)  Pointer to scache
    454  *  Returns     :   BCM_E_XXX
    455  */
    456 STATIC int
    457 bcmi_xgs5_range_wb_reinit_1_1(int unit, uint8 **scache_ptr)
    458 {
    459     uint8       *scache_p;  /* Scache pointer */
    460 
    461     scache_p = (uint8 *)(*scache_ptr);
    462     sal_memcpy(&(RANGE_CTRL(unit)->range_group_used_bitmap),
    463                scache_p,
    464                (sizeof(SHR_BITDCL) * SOC_MAX_NUM_PIPES));
    465     scache_p++;
    466 
    467     return BCM_E_NONE;
    468 
    469 }
    470 
    471 /*  Function    :   bcmi_xgs5_range_wb_sync_1_0
    472  *  Purpose     :   Sync Range module info into scache for version = 1_0
    473  *  Parameters  :   unit            - (IN)  Unit number
    474  *                  scache_ptr      - (IN)  Pointer to scache
    475  *  Returns     :   BCM_E_XXX
    476  */
    477 STATIC int
    478 bcmi_xgs5_range_wb_sync_1_0(int unit, uint8 **scache_ptr)
    479 {
    480     uint8       *scache_p;  /* Scache pointer */
    481     _range_t    *range_p;   /* Pointer to a range */
    482 
    483     scache_p = (uint8 *)(*scache_ptr);
    484 
    485     /* Sync the Range Module Oper Mode */
    486     *scache_p = RANGE_CTRL(unit)->range_oper_mode;
    487     scache_p++;
    488 
    489     /* Sync the number of Ranges in the system */
    490     *scache_p = RANGE_CTRL(unit)->num_ranges;
    491     scache_p++;
    492 
    493     /* Sync the information on which module uses the Range resources */
    494     *scache_p = RANGE_CTRL(unit)->range_used_by_module;
    495     scache_p++;
    496 
    497     range_p = RANGE_CTRL(unit)->ranges;
    498 
    499     while(range_p) {
    500         /* The following fields from the Range Structure needs to
    501            be synced for recovery :
    502            1. pipe_instance to which this range is mapped to.
    503            2. Range Id,
    504            3. UDF id mapped with the Range,
    505            4. Range Offset,
    506            5. Range Width,
    507            Rest all fields in the range structure can be recovered from the Hardware.
    508          */
    509         *scache_p = range_p->pipe_instance;
    510         scache_p++;
    511 
    512         sal_memcpy(scache_p, &(range_p->rid), sizeof(uint32));
    513         scache_p += sizeof(uint32);
    514 
    515         sal_memcpy(scache_p, &(range_p->udf_id), sizeof(bcm_udf_id_t));
    516         scache_p += sizeof(bcm_udf_id_t);
    517 
    518         *scache_p = range_p->offset;
    519         scache_p++;
    520 
    521         *scache_p = range_p->width;
    522         scache_p++;
    523 
    524         range_p = range_p->next;
    525     }
    526 
    527     return BCM_E_NONE;
    528 }
    529 
    530 
    531 /*  Function    :   bcmi_xgs5_range_wb_sync_1_1
    532  *  Purpose     :   Sync Range module info into scache for version = 1_0
    533  *  Parameters  :   unit            - (IN)  Unit number
    534  *                  scache_ptr      - (IN)  Pointer to scache
    535  *  Returns     :   BCM_E_XXX
    536  */
    537 STATIC int
    538 bcmi_xgs5_range_wb_sync_1_1(int unit, uint8 **scache_ptr)
    539 {
    540     uint8       *scache_p;  /* Scache pointer */
    541 
    542     scache_p = (uint8 *)(*scache_ptr);
    543     sal_memcpy(scache_p,
    544                &(RANGE_CTRL(unit)->range_group_used_bitmap),
    545                (sizeof(SHR_BITDCL) * SOC_MAX_NUM_PIPES));
    546     scache_p++;
    547 
    548     return BCM_E_NONE;
    549 }
    550 
    551 /*  Function    :   bcmi_xgs5_range_wb_sync
    552  *  Purpose     :   Sync Range module warmboot state to scache
    553  *  Parameters  :   unit            - (IN)  Unit number.
    554  *  Returns     :   BCM_E_XXX
    555  */
    556 int
    557 bcmi_xgs5_range_wb_sync(int unit)
    558 {
    559     uint8               *scache_ptr;    /* Scache pointer */
    560     soc_scache_handle_t scache_handle;  /* Scache handle */
    561 
    562     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_RANGE, 0);
    563 
    564     BCM_IF_ERROR_RETURN
    565         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    566                                  0, &scache_ptr,
    567                                  BCM_WB_DEFAULT_VERSION, NULL));
    568 
    569     BCM_IF_ERROR_RETURN(bcmi_xgs5_range_wb_sync_1_0(unit, &scache_ptr));
    570     BCM_IF_ERROR_RETURN(bcmi_xgs5_range_wb_sync_1_1(unit, &scache_ptr));
    571     return BCM_E_NONE;
    572 }
    573 
    574 /*  Function    :   bcmi_xgs5_range_reinit
    575  *  Purpose     :   Recovers Range module warmboot state from scache
    576  *  Parameters  :   unit            - (IN)  Unit number.
    577  *  Returns     :   BCM_E_XXX
    578  */
    579 STATIC int
    580 bcmi_xgs5_range_reinit(int unit)
    581 {
    582     int                 rv = BCM_E_INTERNAL;    /* Operation return value */
    583     uint8               *scache_ptr;            /* Scache pointer         */
    584     uint16              recovered_ver = 0;      /* Recovered warmboot version */
    585     soc_scache_handle_t scache_handle;          /* Scache handle */
    586 
    587     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_RANGE, 0);
    588 
    589     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    590                                  0, &scache_ptr,
    591                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    592 
    593     if (BCM_E_NOT_FOUND == rv) {
    594         /* Proceed with Level 1 Warm Boot */
    595         rv = BCM_E_NONE;
    596     } else if (BCM_E_NONE == rv) {
    597         if (recovered_ver >= BCM_WB_VERSION_1_0) {
    598             BCM_IF_ERROR_RETURN(bcmi_xgs5_range_wb_reinit_1_0(unit, &scache_ptr));
    599         }
    600         if (recovered_ver >= BCM_WB_VERSION_1_1) {
    601             BCM_IF_ERROR_RETURN(bcmi_xgs5_range_wb_reinit_1_1(unit, &scache_ptr));
    602         }
    603     }
    604 
    605     return rv;
    606 }
    607 
    608 #endif /*BCM_WARM_BOOT_SUPPORT*/
    609 
    610 /* Function : bcmi_xgs5_range_init
    611  *
    612  * Purpose  : Initialize range module
    613  *
    614  * Parameters : unit - (IN) Unit number.
    615  *
    616  * Returns:
    617  *          BCM_E_NONE     : Range Module initialized successfully.
    618  *          BCM_E_UNIT     : Invalid BCM Unit number.
    619  *          BCM_E_XXX      : Standard error code.
    620  */
    621 int
    622 bcmi_xgs5_range_init( int unit )
    623 {
    624     int rv;     /* Operation return value */
    625 
    626     /* Init control structures */
    627     rv = bcmi_xgs5_range_ctrl_init(unit);
    628     if (BCM_E_NONE != rv) {
    629         LOG_ERROR(BSL_LS_BCM_RANGE,
    630                 (BSL_META_U(unit,
    631                             "Range(unit %d) Error: Module ctrl init failed.\n"),
    632                  unit));
    633     }
    634     BCM_IF_ERROR_RETURN(rv);
    635 
    636 #if defined (BCM_WARM_BOOT_SUPPORT)
    637     if (SOC_WARM_BOOT(unit)) {
    638         rv = bcmi_xgs5_range_reinit(unit);
    639         if (BCM_E_NONE != rv) {
    640             LOG_ERROR(BSL_LS_BCM_RANGE,
    641                     (BSL_META_U(unit,
    642                                 "Range(unit %d) Error: Module reinit failed.\n"),
    643                     unit));
    644         }
    645         BCM_IF_ERROR_RETURN(rv);
    646     } else
    647 #endif /* BCM_WARM_BOOT_SUPPORT */
    648     {
    649         rv = bcmi_xgs5_range_hw_init(unit);
    650         if (BCM_E_NONE != rv) {
    651              LOG_ERROR(BSL_LS_BCM_RANGE,
    652                     (BSL_META_U(unit,
    653                                 "Range(unit %d) Error: Module hw init failed.\n"),
    654                      unit));
    655         }
    656         BCM_IF_ERROR_RETURN(rv);
    657 
    658 #if defined (BCM_WARM_BOOT_SUPPORT)
    659         rv = bcmi_xgs5_range_wb_alloc(unit);
    660         if (BCM_E_NONE != rv) {
    661             LOG_ERROR(BSL_LS_BCM_RANGE,
    662                     (BSL_META_U(unit,
    663                                 "Range(unit %d) Error: Module warmboot alloc failed.\n"),
    664                      unit));
    665         }
    666         BCM_IF_ERROR_RETURN(rv);
    667 #endif /* BCM_WARM_BOOT_SUPPORT */
    668     }
    669 
    670     return BCM_E_NONE;
    671 }
    672 
    673 /*  Function    :   bcmi_xgs5_range_detach
    674  *  Purpose     :   Detaches Range module and cleans software state
    675  *  Parameters  :   unit            - (IN)      Unit number
    676  *  Returns     :   BCM_E_XXX
    677  */
    678 int
    679 bcmi_xgs5_range_detach(int unit)
    680 {
    681     RANGE_INIT_CHECK(unit);
    682 
    683     /* Free resources related to Range module */
    684     BCM_IF_ERROR_RETURN(bcmi_xgs5_range_ctrl_free(unit, RANGE_CTRL(unit)));
    685 
    686     return BCM_E_NONE;
    687 }
    688 
    689 /*  Function    :   bcmi_range_id_generate
    690  *  Purpose     :   Find an unused range ID.
    691  *  Parameters  :   unit            - (IN)      Unit number.
    692  *                  rid             - (OUT)     Range ID.
    693  *  Returns     :   BCM_E_XXX
    694  */
    695 int bcmi_range_id_generate(
    696         int unit,
    697         bcm_range_t *rid)
    698 {
    699     bcm_range_config_t range_config; /* Range config structure */
    700 
    701     *rid = _RANGE_ID_BASE;
    702 
    703     memset(&range_config, 0, sizeof(range_config));
    704     while(*rid <= RANGE_CTRL(unit)->max_ranges) {
    705         range_config.rid = *rid;
    706 
    707         if(BCM_E_NONE != (bcmi_xgs5_range_get(unit, &range_config)))
    708         {
    709             LOG_DEBUG(BSL_LS_BCM_RANGE,
    710                     (BSL_META_U(unit,
    711                                 "bcmi_range_id_generate: Generated Rid = %d \n"), range_config.rid));
    712             return BCM_E_NONE;
    713         }
    714         else {
    715             (*rid)++;
    716         }
    717     }
    718 
    719     if (*rid > RANGE_CTRL(unit)->max_ranges) {
    720         LOG_DEBUG(BSL_LS_BCM_RANGE,
    721                 (BSL_META_U(unit,
    722                             "bcmi_range_id_generate: All ranges are used up\n")));
    723         return BCM_E_RESOURCE;
    724     }
    725 
    726     return BCM_E_NONE;
    727 }
    728 
    729 /*  Function    :   bcmi_xgs5_range_create
    730  *  Purpose     :   Create a Range object
    731  *  Parameters  :   unit - (IN) Unit number.
    732  *                  flags   - (IN) Flags to create a Range
    733  *                  range_config   - (IN) Range config structure.
    734  *  Returns     :   BCM_E_XXX
    735  */
    736 int bcmi_xgs5_range_create(
    737         int unit,
    738         int flags,
    739         bcm_range_config_t *range_config)
    740 {
    741     int                 rv;             /* Operation return value */
    742     uint32              max_field_val;  /* Max value that the field in memory can hold */
    743     SHR_BITDCL          *range_bmap;    /* Used indexes map.        */
    744     int                 hw_index  = -1; /* Free/matching rang index.*/
    745     int                 idx_max;        /* Loop termination index.  */
    746     _range_t            *tmp = NULL;    /* Range pointer */
    747     soc_mem_t           mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */
    748     bcmi_xgs4_udf_offset_info_t           *udf_offset_info;/* UDF offset info */
    749     uint16              udf_mask = ~0;  /* UDF mask */
    750     bcm_range_oper_mode_t   oper_mode = 0;  /*Range module operational mode */
    751     int pipe_instance = 0;                   /* Pipe instance */
    752 
    753 
    754     /* Input parameters check */
    755     BCM_IF_NULL_RETURN_PARAM(range_config);
    756 
    757     if (RANGE_CTRL(unit)->range_used_by_module == RANGE_USED_BY_FIELD_MODULE) {
    758         LOG_CLI((BSL_META("Range resource is used by FIELD module. \n")));
    759         return BCM_E_UNAVAIL;
    760     }
    761 
    762     rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode);
    763     LOG_DEBUG(BSL_LS_BCM_RANGE,
    764             (BSL_META_U(unit,
    765                         "bcmi_xgs5_range_create: Error fetching Range Oper Mode \n")));
    766     BCM_IF_ERROR_RETURN(rv);
    767 
    768     rv = bcmi_xgs5_range_validate_port_config (unit, oper_mode, range_config->ports, &pipe_instance) ;
    769     LOG_DEBUG(BSL_LS_BCM_RANGE,
    770             (BSL_META_U(unit,
    771                         "bcmi_xgs5_range_create: Error Validating Port Config \n")));
    772     BCM_IF_ERROR_RETURN (rv);
    773 
    774     max_field_val = (1 << soc_mem_field_length(unit, mem, LOWER_BOUNDSf)) - 1 ;
    775     if(range_config->min > max_field_val) {
    776         return (BCM_E_PARAM);
    777     }
    778 
    779     max_field_val = (1 << soc_mem_field_length(unit, mem, UPPER_BOUNDSf)) - 1 ;
    780     if(range_config->max > max_field_val) {
    781         return (BCM_E_PARAM);
    782     }
    783 
    784     if((range_config->rtype < bcmRangeTypeL4SrcPort)
    785             || (range_config->rtype > bcmRangeTypeUdf)) {
    786         return (BCM_E_PARAM);
    787     }
    788 
    789     if (range_config->rtype == bcmRangeTypeUdf) {
    790         if (soc_feature(unit, soc_feature_udf_td3x_support)) {
    791            uint8 num_chunks;
    792            uint32 chunk_bmap;
    793            bcm_udf_chunk_info_t udf_chunk_info;
    794 
    795            rv = bcm_esw_udf_chunk_info_get(unit, range_config->udf_id, &udf_chunk_info);
    796            BCM_IF_ERROR_RETURN(rv);
    797 
    798            rv = bcm_esw_udf_range_checker_chunk_info_get(unit, &num_chunks, &chunk_bmap);
    799            BCM_IF_ERROR_RETURN(rv);
    800 
    801            if (udf_chunk_info.chunk_bmap != chunk_bmap) {
    802               return BCM_E_PARAM;
    803            }
    804         } else if (soc_feature(unit, soc_feature_udf_support)) {
    805            /* Check UDF chunk id */
    806            memset(&udf_offset_info, 0, sizeof(udf_offset_info));
    807 
    808            rv = bcmi_xgs4_udf_offset_node_get(unit, range_config->udf_id, &udf_offset_info);
    809            LOG_DEBUG(BSL_LS_BCM_RANGE,
    810                    (BSL_META_U(unit,
    811                                "bcmi_xgs5_range_create: Error fetching Udf Offset Node \n")));
    812            BCM_IF_ERROR_RETURN(rv);
    813 
    814            if(!(udf_offset_info->flags & BCMI_XGS4_UDF_OFFSET_RANGE_CHECK)) {
    815                /* UDF should be created with Range Check hints */
    816                return (BCM_E_PARAM);
    817            }
    818 
    819            /* UDF1 Chunk 2: (47 - 32 bits) which is UDF_OFFSET5*/
    820            if(udf_offset_info->hw_bmap != 0x20) {
    821                return BCM_E_PARAM;
    822            }
    823         } else {
    824            return BCM_E_PARAM;
    825         }
    826     }
    827 
    828     idx_max = soc_mem_index_max(unit, mem);
    829     range_bmap = NULL;
    830 
    831     RANGE_MALLOC(range_bmap, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges");
    832     if (NULL == range_bmap) {
    833         LOG_DEBUG(BSL_LS_BCM_RANGE,
    834                 (BSL_META_U(unit,
    835                         "bcmi_xgs5_range_create: Error Allocating memory for range_bmap \n")));
    836         return (BCM_E_MEMORY);
    837     }
    838 
    839     /* Search existing ranges */
    840     if (flags & BCM_RANGE_CREATE_WITH_ID) {
    841         if ((soc_feature(unit, soc_feature_th3_style_fp)) &&
    842               (range_config->rid > RANGE_CTRL(unit)->max_ranges)) {
    843               sal_free(range_bmap);
    844               return (BCM_E_PARAM);
    845         }
    846         for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) {
    847             if(tmp->rid == range_config->rid) {
    848                 LOG_DEBUG(BSL_LS_BCM_RANGE,
    849                     (BSL_META_U(unit,
    850                             "bcmi_xgs5_range_create: Duplicate Range Id \n")));
    851                 sal_free(range_bmap);
    852                 return BCM_E_EXISTS;
    853             }
    854         }
    855     } else {
    856         rv = bcmi_range_id_generate(unit, &(range_config->rid));
    857         if (BCM_FAILURE(rv)) {
    858             sal_free(range_bmap);
    859             return rv;
    860         }
    861     }
    862 
    863     /* Search existing ranges */
    864     for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) {
    865         SHR_BITSET(range_bmap, tmp->hw_index);
    866         /* Found an exisiting match so use it. */
    867         if (tmp->rtype == range_config->rtype && tmp->min == range_config->min
    868                 && tmp->max == range_config->max) {
    869             hw_index = tmp->hw_index;
    870         }
    871     }
    872 
    873     /* If no match found, allocate a new hardware index. */
    874     if (hw_index < 0) {
    875         hw_index = soc_mem_index_min(unit, RANGE_CTRL(unit)->range_mem);
    876         for (; hw_index <= idx_max; hw_index++) {
    877             if (0 == SHR_BITGET(range_bmap, hw_index)) {
    878                 break;
    879             }
    880         }
    881         /* No hardware indexes left. */
    882         if (hw_index == (idx_max + 1)) {
    883             sal_free(range_bmap);
    884             return (BCM_E_RESOURCE);
    885         }
    886     }
    887 
    888     /* Create a new range entry for the list */
    889     if ((tmp = sal_alloc(sizeof(*tmp), "Range")) == NULL) {
    890         sal_free(range_bmap);
    891         return (BCM_E_MEMORY);
    892     }
    893 
    894 
    895     memset(tmp, 0, sizeof(_range_t));
    896     udf_mask <<= (range_config->width);
    897     udf_mask = ~udf_mask;
    898     udf_mask <<= range_config->offset;
    899 
    900     tmp->rid = range_config->rid;
    901     tmp->hw_index = hw_index;
    902     tmp->min = range_config->min;
    903     tmp->max = range_config->max;
    904     tmp->rtype  = range_config->rtype;
    905     tmp->offset = range_config->offset;
    906     tmp->width = range_config->width;
    907     tmp->udf_id = range_config->udf_id;
    908 
    909     if (oper_mode == bcmRangeOperModeGlobal) {
    910         tmp->ports = PBMP_ALL(unit);
    911     } else if (oper_mode == bcmRangeOperModePipeLocal) {
    912         tmp->ports = range_config->ports;
    913     }
    914 
    915     tmp->pipe_instance = pipe_instance;
    916 
    917     rv = bcmi_range_check_set(unit, tmp, hw_index, 1, udf_mask);
    918 
    919     if (BCM_FAILURE(rv)) {
    920         sal_free(range_bmap);
    921         sal_free(tmp);
    922         return rv;
    923     }
    924 
    925     /* Add to list of range checkers. */
    926     {
    927         _range_t *p, **pp;
    928         for (pp = &RANGE_CTRL(unit)->ranges; (p = *pp) && tmp->hw_index > p->hw_index; pp = &p->next);
    929         (*pp = tmp)->next = p;
    930     }
    931 
    932     LOG_DEBUG(BSL_LS_BCM_RANGE,
    933             (BSL_META_U(unit,
    934                         "bcmi_xgs5_range_create: Range Create Successful \n")));
    935 
    936     sal_free(range_bmap);
    937     return rv;
    938 
    939 }
    940 
    941 /*  Function    :   bcmi_xgs5_range_get
    942  *  Purpose     :   Retrieve range info given the range ID
    943  *  Parameters  :   unit            - (IN)      Unit number.
    944  *                  range_config    - (OUT)     range config structure
    945  *  Returns     :   BCM_E_XXX
    946  */
    947 int bcmi_xgs5_range_get(
    948         int unit,
    949         bcm_range_config_t *range_config)
    950 {
    951     int rv;     /* Operation return value */
    952 
    953     /* Input parameters check */
    954     BCM_IF_NULL_RETURN_PARAM(range_config);
    955 
    956     rv = bcmi_xgs5_range_node_get(unit, range_config);
    957 
    958     return rv;
    959 }
    960 
    961 /*  Function    :   bcmi_xgs5_range_destroy
    962  *  Purpose     :   To destroy range object
    963  *  Parameters  :   unit            - (IN)      Unit number
    964  *                  rid             - (IN)      Range Id to be destroyed
    965  */
    966 int bcmi_xgs5_range_destroy(
    967         int unit,
    968         bcm_range_t rid)
    969 {
    970     int         rv;         /* Operation return value */
    971     _range_t    *cur = NULL;    /* Ptr to Current range being traversed */
    972     _range_t    *prev = NULL;   /* Ptr to Previous range traversed */
    973     _range_t    range_tmp;      /* Range structure */
    974 
    975     memset(&range_tmp, 0, sizeof(range_tmp));
    976 
    977     if (RANGE_CTRL(unit)->range_used_by_module == RANGE_USED_BY_FIELD_MODULE) {
    978         LOG_CLI((BSL_META("Range resource is used by FIELD module. \n")));
    979         return BCM_E_UNAVAIL;
    980     }
    981 
    982     for (cur = RANGE_CTRL(unit)->ranges; cur != NULL; cur = cur->next) {
    983         if(cur->rid == rid) {
    984             /* Found the node. */
    985             break;
    986         }
    987         prev = cur;
    988     }
    989 
    990     /* Matching node not found */
    991     if (cur == NULL) {
    992         return BCM_E_NOT_FOUND;
    993     }
    994 
    995     range_tmp.rid       = cur->rid;
    996     range_tmp.pipe_instance = cur->pipe_instance;
    997     range_tmp.hw_index = cur->hw_index;
    998 
    999     rv = bcmi_range_check_set(unit, &range_tmp, range_tmp.hw_index, 0, 0);
   1000 
   1001     if (BCM_FAILURE(rv)) {
   1002         return rv;
   1003     }
   1004 
   1005     /* Free the cur node */
   1006     if (prev == NULL) {
   1007         RANGE_CTRL(unit)->ranges = cur->next;
   1008     } else {
   1009         prev->next = cur->next;
   1010     }
   1011     sal_free(cur);
   1012 
   1013     RANGE_CTRL(unit)->num_ranges -= 1;
   1014 
   1015     return BCM_E_NONE;
   1016 }
   1017 
   1018 /*  Function    :   bcmi_xgs5_range_node_get
   1019  *  Purpose     :   Retrieve range node given the range id
   1020  *  Parameters  :   unit            - (IN)      Unit number
   1021  *                  range_config    - (IN)      Range config structure
   1022  *  Returns     :   BCM_E_XXX
   1023  */
   1024 int
   1025 bcmi_xgs5_range_node_get(
   1026         int unit,
   1027         bcm_range_config_t *range_config)
   1028 {
   1029     _range_t                *tmp = NULL;        /* Range structure. */
   1030     int                     rv   = BCM_E_NONE;  /* Operation return value. */
   1031 
   1032     tmp = RANGE_CTRL(unit)->ranges;
   1033 
   1034     while (tmp != NULL) {
   1035         if(tmp->rid == range_config->rid) {
   1036             /* Found the node. */
   1037             break;
   1038         }
   1039         tmp = tmp->next;
   1040     }
   1041 
   1042     if (tmp == NULL) {
   1043         rv = BCM_E_NOT_FOUND;
   1044     } else {
   1045         range_config->rtype     = tmp->rtype;
   1046         range_config->min       = tmp->min;
   1047         range_config->max       = tmp->max;
   1048         range_config->offset    = tmp->offset;
   1049         range_config->width     = tmp->width;
   1050         range_config->udf_id    = tmp->udf_id;
   1051         range_config->ports     = tmp->ports;
   1052     }
   1053 
   1054     return rv;
   1055 
   1056 }
   1057 
   1058 /*  Function    :   bcmi_range_check_set
   1059  *  Purpose     :   Write the range check parameters into the memory
   1060  *  Parameters  :   unit    - (IN) BCM unit number
   1061  *                  range   - (IN) range structure
   1062  *                  hw_index - (IN) Range hw index
   1063  *                  enable  - (IN) True or False
   1064  *                  udf_mask - (IN) Udf mask
   1065  *  Returns     :   BCM_E_XXX
   1066  */
   1067 int
   1068 bcmi_range_check_set(
   1069         int unit,
   1070         _range_t *range,
   1071         int     hw_index,
   1072         int enable,
   1073         uint16 udf_mask)
   1074 {
   1075     int                     rv;                         /* Operation return value */
   1076     soc_mem_t               range_check_mem = INVALIDm; /* Range Checker Memory ID */
   1077     uint32                  tbl_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Range checker entry buffer. */
   1078     bcm_range_oper_mode_t   oper_mode = 0;              /* Range module operational mode */
   1079     uint32                  mask = udf_mask;
   1080 
   1081     rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode);
   1082     BCM_IF_ERROR_RETURN(rv);
   1083 
   1084     /* Get the memory to which the configurations need to be written to. */
   1085     if (oper_mode == bcmRangeOperModeGlobal) {
   1086         range_check_mem = RANGE_CTRL(unit)->range_mem;
   1087     } else if(oper_mode == bcmRangeOperModePipeLocal) {
   1088         if (range->pipe_instance < SOC_MAX_NUM_PIPES) {
   1089             BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   1090                                 IFP_RANGE_CHECKm,
   1091                                 range->pipe_instance,
   1092                                 &range_check_mem));
   1093         } else {
   1094             return BCM_E_INTERNAL;
   1095         }
   1096 
   1097     }
   1098 
   1099     if (INVALIDm == range_check_mem) {
   1100         return (BCM_E_UNAVAIL);
   1101     }
   1102 
   1103     /* Index sanity check. */
   1104     if (!soc_mem_index_valid(unit, range_check_mem, hw_index)) {
   1105         return (BCM_E_PARAM);
   1106     }
   1107 
   1108     /* write range check memory */
   1109     sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1110 
   1111     /* Set source/destination port selection. */
   1112     soc_mem_field_set(unit, range_check_mem, tbl_entry,
   1113             FIELD_SELECTf, &(range->rtype));
   1114 
   1115     if (SOC_MEM_FIELD_VALID(unit, range_check_mem, ENABLEf)) {
   1116         soc_mem_field_set(unit, range_check_mem, tbl_entry,
   1117                 ENABLEf, (uint32 *) &enable);
   1118     }
   1119 
   1120     /* Set range min value. */
   1121     soc_mem_field_set(unit, range_check_mem, tbl_entry,
   1122             LOWER_BOUNDSf, (uint32 *) &(range->min));
   1123 
   1124     /* Set range max value. */
   1125     soc_mem_field_set(unit, range_check_mem, tbl_entry,
   1126             UPPER_BOUNDSf, (uint32 *) &(range->max));
   1127 
   1128     if(range->rtype == bcmRangeTypeUdf) {
   1129         soc_mem_field_set(unit, range_check_mem, tbl_entry,
   1130                 UDF_MASKf, (uint32 *) &(mask));
   1131     }
   1132 
   1133     /* Write entry back to hw. */
   1134     BCM_IF_ERROR_RETURN(soc_mem_write(unit, range_check_mem,
   1135                 MEM_BLOCK_ALL, hw_index, tbl_entry));
   1136 
   1137     return BCM_E_NONE;
   1138 }
   1139 
   1140 /*  Function    :   bcmi_xgs5_range_hw_clear
   1141  *  Purpose     :   Clear hardware
   1142  *  Parameters  :   unit    -   (IN) BCM unit number
   1143  *  Returns     :   BCM_E_XXX
   1144  */
   1145 int bcmi_xgs5_range_hw_clear(
   1146         int unit)
   1147 {
   1148     /* DO NOT CLEAR HW when in warmboot mode. */
   1149     if (SOC_WARM_BOOT(unit)) {
   1150         return (BCM_E_NONE);
   1151     }
   1152 
   1153     BCM_IF_ERROR_RETURN(soc_mem_clear(unit, RANGE_CTRL(unit)->range_mem,
   1154                 COPYNO_ALL, TRUE));
   1155 
   1156     return BCM_E_NONE;
   1157 }
   1158 
   1159 /*
   1160  * Function     :   bcmi_xgs5_range_oper_mode_set
   1161  * Purpose      :   Configure Range Module Operational Mode
   1162  * Parameters   :   unit        - (IN) BCM Device number.
   1163  *                  oper_mode   - (IN) Range Operational Mode enum value.
   1164  * Returns      :   BCM_E_XXX
   1165  */
   1166 int bcmi_xgs5_range_oper_mode_set(
   1167         int unit,
   1168         bcm_range_oper_mode_t oper_mode)
   1169 {
   1170     /* Validate input parameters */
   1171     if ((oper_mode != bcmRangeOperModeGlobal) &&
   1172         (oper_mode != bcmRangeOperModePipeLocal)){
   1173         return BCM_E_PARAM;
   1174     }
   1175 
   1176     /* Range Module Init Check */
   1177     RANGE_INIT_CHECK(unit);
   1178 
   1179     /* Verify whether mode is already set */
   1180     if (RANGE_CTRL(unit)->range_oper_mode == oper_mode) {
   1181         return BCM_E_NONE;
   1182     }
   1183 
   1184     /* Range Module Lock */
   1185     RANGE_LOCK(unit);
   1186 
   1187     if (RANGE_CTRL(unit)->ranges) {
   1188         /*Cannot set opermode when there are already existing ranges*/
   1189         return BCM_E_BUSY;
   1190     }
   1191 
   1192     /* Hw_clear*/
   1193     BCM_IF_ERROR_RETURN(bcmi_xgs5_range_hw_clear(unit));
   1194 
   1195     /* Set Oper mode */
   1196     RANGE_CTRL(unit)->range_oper_mode = oper_mode;
   1197 
   1198     /* Unlock Range Module */
   1199     RANGE_UNLOCK(unit);
   1200 
   1201     return BCM_E_NONE;
   1202 }
   1203 
   1204 /*
   1205  * Function     :  bcmi_xgs5_range_oper_mode_get
   1206  * Purpose      :  Retrieve Range Module Operational Mode
   1207  * Parameters   :  unit    - (IN)  BCM Device number.
   1208  *                 mode    - (OUT) Reference to Range Operational Mode value.
   1209  * Returns      :  BCM_E_XXX
   1210  */
   1211 int bcmi_xgs5_range_oper_mode_get(
   1212         int unit,
   1213         bcm_range_oper_mode_t *oper_mode)
   1214 {
   1215     /* Validate Input parameters */
   1216     if (oper_mode == NULL) {
   1217         return BCM_E_PARAM;
   1218     }
   1219 
   1220     /* Range Module Init Check */
   1221     RANGE_INIT_CHECK(unit);
   1222 
   1223     /* Fetch the mode */
   1224     *oper_mode = RANGE_CTRL(unit)->range_oper_mode;
   1225 
   1226     return BCM_E_NONE;
   1227 }
   1228 
   1229 /*
   1230  * Function     :   bcmi_xgs5_range_traverse
   1231  * Purpose      :   Traverse all the ranges in the system, calling a specified
   1232  *                  callback for each one
   1233  * Parameters   :   unit - (IN) Unit number.
   1234  *                  callback - (IN) A pointer to the callback function to call for each range
   1235  *                  user_data - (IN) Pointer to user data to supply in the callback
   1236  * Returns      :   BCM_E_XXX
   1237  */
   1238 int bcmi_xgs5_range_traverse(
   1239         int unit,
   1240         bcm_range_traverse_cb callback,
   1241         void *user_data)
   1242 {
   1243     bcm_range_config_t    range_config;     /* Range config structure */
   1244     int             rv = BCM_E_NONE;        /* Operation return value */
   1245     _range_t        *tmp = NULL;            /* Range structure        */
   1246 
   1247     /* Validate Input Parameters */
   1248     if (NULL == callback) {
   1249         return BCM_E_PARAM;
   1250     }
   1251 
   1252     /* Range Module Init Check */
   1253     RANGE_INIT_CHECK(unit);
   1254 
   1255     /* Range Module Lock */
   1256     RANGE_LOCK(unit);
   1257 
   1258     tmp = RANGE_CTRL(unit)->ranges;
   1259 
   1260     if (tmp == NULL) {
   1261         RANGE_UNLOCK(unit);
   1262         return BCM_E_NOT_FOUND;
   1263     }
   1264 
   1265     while (tmp) {
   1266         memset (&range_config, 0, sizeof(range_config));
   1267         range_config.rid       = tmp->rid;
   1268         range_config.rtype     = tmp->rtype;
   1269         range_config.min       = tmp->min;
   1270         range_config.max       = tmp->max;
   1271         range_config.offset    = tmp->offset;
   1272         range_config.width     = tmp->width;
   1273         range_config.udf_id    = tmp->udf_id;
   1274         range_config.ports     = tmp->ports;
   1275 
   1276         /* Call user callback. */
   1277         rv = (callback)(unit, &range_config, user_data);
   1278         if (BCM_FAILURE(rv)) {
   1279             break;
   1280         }
   1281         tmp = tmp->next;
   1282     }
   1283 
   1284     RANGE_UNLOCK(unit);
   1285     return (BCM_E_NONE);
   1286 }
   1287 
   1288 /*  Function    :   bcmi_xgs5_range_get_hw_index
   1289  *  Purpose     :   Retrieve hardware index used by a range id
   1290  *  Parameters  :   unit - (IN) Unit number.
   1291  *                  rid  - (IN) Range ID.
   1292  *                  hw_index    - (OUT) hw index
   1293  *  Returns     :   BCM_E_XXX
   1294  */
   1295 int
   1296 bcmi_xgs5_range_get_hw_index(
   1297         int unit,
   1298         bcm_range_t rid,
   1299         int *hw_index)
   1300 {
   1301     _range_t *tmp = NULL;   /* Range structure */
   1302 
   1303     if(!hw_index) {
   1304         return BCM_E_PARAM;
   1305     }
   1306 
   1307     for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) {
   1308         /* Find the matching Range Id */
   1309         if(tmp->rid == rid) {
   1310             *hw_index = tmp->hw_index;
   1311             return BCM_E_NONE;
   1312         }
   1313     }
   1314 
   1315     return BCM_E_NOT_FOUND;
   1316 }
   1317 
   1318 /*  Function    :   bcmi_xgs5_range_validate_port_config
   1319  *  Purpose     :   Validate the ports config against the Oper mode of the Range module.
   1320  *                  When Global mode is set, only all port bitmaps are allowed.
   1321  *                  When perpipe mode is set, only perpipe port bitmaps are allowed.
   1322  *  Parameters  :   unit - (IN) Unit number.
   1323  *                  oper_mode - (IN) Range module Operational mode
   1324  *                  ports - (IN) PBMP given by user
   1325  *                  pipe_instance - (OUT) Pipe number when in PerPipe mode
   1326  *  Returns     :   BCM_E_XXX
   1327  */
   1328 int bcmi_xgs5_range_validate_port_config (
   1329         int unit,
   1330         bcm_range_oper_mode_t oper_mode,
   1331         bcm_pbmp_t ports,
   1332         int *pipe_instance)
   1333 {
   1334     int                 pipe;   /* Device pipe iterator.    */
   1335     bcm_port_config_t   pc;     /* Port configuration.      */
   1336     int rv;                     /* Operation return value.  */
   1337 
   1338     /* Initialize port configuration structure. */
   1339     bcm_port_config_t_init(&pc);
   1340 
   1341     /* Get device port configuration. */
   1342     rv = bcm_esw_port_config_get(unit, &pc);
   1343     if (BCM_FAILURE(rv)) {
   1344         return rv;
   1345     }
   1346 
   1347     if (oper_mode == bcmRangeOperModeGlobal) {
   1348         /* Global Mode : All ports must be part of IPBM value, if supplied. */
   1349         if (BCM_PBMP_NEQ(pc.all, ports)) {
   1350             return BCM_E_PARAM;
   1351         }
   1352         /* Default value is 0*/
   1353         *pipe_instance = 0;
   1354     }
   1355     else if (oper_mode == bcmRangeOperModePipeLocal) {
   1356         for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   1357             if (BCM_PBMP_EQ(pc.per_pipe[pipe], ports)) {
   1358                 *pipe_instance = pipe;
   1359                 break;
   1360             }
   1361         }
   1362         if (NUM_PIPE(unit) == pipe) {
   1363             return BCM_E_PARAM;
   1364         }
   1365     }
   1366     return (BCM_E_NONE);
   1367 }
   1368 
   1369 /*  Function    :   bcmi_xgs5_range_validate_field_stage_oper_mode
   1370  *  Purpose     :   Validate Field Stage Oper Mode against Range Module Oper Mode
   1371  *  Parameters  :   unit - (IN) Unit number.
   1372  *                  oper_mode  - (IN) Operational mode of the Field Group's Stage
   1373  *  Returns     :   BCM_E_XXX
   1374  */
   1375 int bcmi_xgs5_range_validate_field_stage_oper_mode (
   1376         int unit,
   1377         bcm_field_group_oper_mode_t grp_oper_mode)
   1378 {
   1379     int         rv;     /* Operation return value */
   1380     bcm_range_oper_mode_t   range_oper_mode = 0; /* Range module operational mode */
   1381 
   1382     rv = bcmi_xgs5_range_oper_mode_get(unit, &range_oper_mode);
   1383     BCM_IF_ERROR_RETURN(rv);
   1384 
   1385     if (((grp_oper_mode == bcmFieldGroupOperModeGlobal) &&
   1386         (range_oper_mode != bcmRangeOperModeGlobal)))
   1387     {
   1388         return BCM_E_PARAM;
   1389     }
   1390 
   1391     return BCM_E_NONE;
   1392 }
   1393 
   1394 /*  Function    :   bcmi_xgs5_validate_field_group_instance
   1395  *  Purpose     :   Retrieve hardware index used by a range id
   1396  *  Parameters  :   unit - (IN) Unit number.
   1397  *                  rid  - (IN) Range ID.
   1398  *                  grp_instance - (IN) pipe instance, the field group is configured on
   1399  *  Returns     :   BCM_E_XXX
   1400  */
   1401 int bcmi_xgs5_range_validate_field_group_instance(
   1402         int unit,
   1403         bcm_range_t rid,
   1404         int grp_instance)
   1405 {
   1406     int rv;
   1407     _range_t *tmp = NULL;   /* Range structure */
   1408     bcm_range_oper_mode_t   range_oper_mode = 0; /* Range module operational mode */
   1409 
   1410     tmp = RANGE_CTRL(unit)->ranges;
   1411 
   1412     if (tmp == NULL) {
   1413         return BCM_E_NOT_FOUND;
   1414     }
   1415 
   1416     rv = bcmi_xgs5_range_oper_mode_get(unit, &range_oper_mode);
   1417     BCM_IF_ERROR_RETURN(rv);
   1418 
   1419     if (range_oper_mode == bcmRangeOperModeGlobal) {
   1420         return BCM_E_NONE;
   1421     }
   1422 
   1423     for (; tmp != NULL; tmp = tmp->next) {
   1424         if(tmp->rid == rid) {
   1425             if (tmp->pipe_instance == grp_instance) {
   1426                 return BCM_E_NONE;
   1427             }
   1428         }
   1429     }
   1430 
   1431     return BCM_E_PARAM;
   1432 }
   1433 
   1434 /*
   1435  * Function     :   bcmi_xgs5_range_RangeCheckersAPIType_set
   1436  * Purpose      :   Configure Switch Control for RangeCheckersAPIType
   1437  * Parameters   :   unit        - (IN) BCM Device number.
   1438  *                  api_type    - (IN) Setting this switch control to 0 allows to use only field API's.
   1439  *                                     Setting it to 1 allows to use only new range module API's.
   1440  * Returns      :   BCM_E_XXX
   1441  */
   1442 int bcmi_xgs5_range_RangeCheckersAPIType_set (
   1443         int unit,
   1444         int api_type)
   1445 {
   1446 
   1447     RANGE_INIT_CHECK(unit);
   1448 
   1449     if ((api_type < 0) || (api_type >1)) {
   1450         /* Value of 0 or 1 only is allowed*/
   1451         return BCM_E_PARAM;
   1452     }
   1453 
   1454     if (api_type == 0) {
   1455         if (RANGE_CTRL(unit)->ranges) {
   1456             LOG_DEBUG(BSL_LS_BCM_RANGE,
   1457                 (BSL_META_U(unit,
   1458                             "Range resource is used by RANGE module. \n")));
   1459             return BCM_E_UNAVAIL;
   1460         }
   1461         RANGE_CTRL(unit)->range_used_by_module = RANGE_USED_BY_FIELD_MODULE;
   1462     }
   1463     else {
   1464         if (_bcm_field_is_stage_range_check_exist(unit,
   1465                     _BCM_FIELD_STAGE_INGRESS) == BCM_E_EXISTS) {
   1466             LOG_DEBUG(BSL_LS_BCM_RANGE,
   1467                 (BSL_META_U(unit,
   1468                             "Range resource is used by FIELD module. \n")));
   1469             return BCM_E_UNAVAIL;
   1470         }
   1471         RANGE_CTRL(unit)->range_used_by_module = RANGE_USED_BY_RANGE_MODULE;
   1472     }
   1473 
   1474     return BCM_E_NONE;
   1475 }
   1476 
   1477 /*
   1478  * Function     :   bcmi_xgs5_range_RangeCheckersAPIType_get
   1479  * Purpose      :   Configure Switch Control for RangeCheckersAPIType
   1480  * Parameters   :   unit        - (IN) BCM Device number.
   1481  *                  api_type    - (OUT) Get this switch control value.
   1482  *                                      0 - Only field API's are allowed.
   1483  *                                      1 - Only new range module API's are allowed.
   1484  * Returns      :   BCM_E_XXX
   1485  */
   1486 int bcmi_xgs5_range_RangeCheckersAPIType_get (
   1487         int unit,
   1488         int *api_type)
   1489 {
   1490     RANGE_INIT_CHECK(unit);
   1491 
   1492     *api_type = RANGE_CTRL(unit)->range_used_by_module;
   1493     return BCM_E_NONE;
   1494 }
   1495 
   1496 /* Function to install group  bitmap to HW */
   1497 int bcmi_range_group_hw_install(int unit,
   1498                                 uint32 range_group_id,
   1499                                 SHR_BITDCL *range_hw_bmap,
   1500                                 bcm_range_oper_mode_t oper_mode,
   1501                                 int pipe_instance)
   1502 {
   1503     soc_mem_t mem = INVALIDm;                   /* Memory for Range check */
   1504     uint32 tbl_entry[SOC_MAX_MEM_FIELD_WORDS] = {0};  /* Range checker entry buffer. */
   1505 
   1506     if (SOC_MEM_IS_VALID(unit, IFP_RANGE_CHECK_MASKm)) {
   1507         mem = (oper_mode == bcmRangeOperModeGlobal)     \
   1508               ? (IFP_RANGE_CHECK_MASKm)                 \
   1509               : (SOC_MEM_UNIQUE_ACC(unit, IFP_RANGE_CHECK_MASKm)[pipe_instance]) ;
   1510         sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1511         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, range_group_id, tbl_entry));
   1512         soc_mem_field_set(unit, mem, tbl_entry, MASKf, range_hw_bmap);
   1513 
   1514         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, range_group_id, tbl_entry));
   1515 
   1516         return BCM_E_NONE;
   1517     }
   1518 
   1519     if (oper_mode == bcmRangeOperModeGlobal) {
   1520         if (range_group_id < (RANGE_CTRL(unit)->max_groups/2)) {
   1521              mem = IFP_RANGE_CHECK_MASK_Am;
   1522          } else {
   1523              mem = IFP_RANGE_CHECK_MASK_Bm;
   1524          }
   1525     } else if (oper_mode == bcmRangeOperModePipeLocal) {
   1526         if (range_group_id < (RANGE_CTRL(unit)->max_groups/2)) {
   1527              BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   1528                                                  IFP_RANGE_CHECK_MASK_Am,
   1529                                                  pipe_instance,
   1530                                                  &mem));
   1531          } else {
   1532              BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   1533                                                  IFP_RANGE_CHECK_MASK_Bm,
   1534                                                  pipe_instance,
   1535                                                  &mem));
   1536          }
   1537     } else {
   1538          return (BCM_E_INTERNAL);
   1539     }
   1540 
   1541 
   1542     /* Write range check memory */
   1543     sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1544 
   1545     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 0, tbl_entry));
   1546 
   1547     soc_mem_field_set(unit, mem, tbl_entry,
   1548                       range_group_fields[range_group_id],
   1549                       range_hw_bmap);
   1550 
   1551         /* Write entry back to hw. */
   1552     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem,
   1553                         MEM_BLOCK_ALL, 0, tbl_entry));
   1554 
   1555     return BCM_E_NONE;
   1556 }
   1557 
   1558 /* Function to install group  bitmap to HW */
   1559 int bcmi_range_group_hw_get(int unit,
   1560                             uint32 range_group_id,
   1561                             SHR_BITDCL *range_hw_bmap,
   1562                             bcm_range_oper_mode_t oper_mode,
   1563                             int pipe_instance)
   1564 {
   1565     soc_mem_t mem = INVALIDm;                   /* Memory for Range check */
   1566     uint32 tbl_entry[SOC_MAX_MEM_FIELD_WORDS];  /* Range checker entry buffer. */
   1567 
   1568     if (SOC_MEM_IS_VALID(unit, IFP_RANGE_CHECK_MASKm)) {
   1569         mem = (oper_mode == bcmRangeOperModeGlobal)     \
   1570               ? (IFP_RANGE_CHECK_MASKm)                 \
   1571               : (SOC_MEM_UNIQUE_ACC(unit, IFP_RANGE_CHECK_MASKm)[pipe_instance]);
   1572         sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1573         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, range_group_id, tbl_entry));
   1574         soc_mem_field_get(unit, mem, tbl_entry, MASKf, range_hw_bmap);
   1575         return BCM_E_NONE;
   1576     }
   1577 
   1578     if (oper_mode == bcmRangeOperModeGlobal) {
   1579         if (range_group_id < (RANGE_CTRL(unit)->max_groups/2)) {
   1580              mem = IFP_RANGE_CHECK_MASK_Am;
   1581          } else {
   1582              mem = IFP_RANGE_CHECK_MASK_Bm;
   1583          }
   1584     } else if (oper_mode == bcmRangeOperModePipeLocal) {
   1585         if (range_group_id < (RANGE_CTRL(unit)->max_groups/2)) {
   1586              BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   1587                                                  IFP_RANGE_CHECK_MASK_Am,
   1588                                                  pipe_instance,
   1589                                                  &mem));
   1590          } else {
   1591              BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   1592                                                  IFP_RANGE_CHECK_MASK_Bm,
   1593                                                  pipe_instance,
   1594                                                  &mem));
   1595          }
   1596     } else {
   1597          return (BCM_E_INTERNAL);
   1598     }
   1599 
   1600     /* Write range check memory */
   1601     sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   1602 
   1603     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, 0, tbl_entry));
   1604 
   1605     soc_mem_field_get(unit, mem, tbl_entry,
   1606                       range_group_fields[range_group_id],
   1607                       range_hw_bmap);
   1608     return BCM_E_NONE;
   1609 }
   1610 
   1611 
   1612 /*
   1613  * This API will help to combine different Range Checkers into a single
   1614  * group. It returns a range group identifier that can be passed to
   1615  * 'bcm_field_qualify_RangeGroup' API, to qualify a Field entry with
   1616  * Range Group match criteria. The Individual RangeCheck conditions and
   1617  * its IDs has to be created separately using bcm_range_create API.
   1618  */
   1619 int bcmi_xgs5_range_group_create(
   1620     int unit,
   1621     bcm_range_group_config_t *range_group_config)
   1622 {
   1623     SHR_BITDCL          *range_hw_bmap;    /* Used indexes map.        */
   1624     SHR_BITDCL          *range_hw_bmap_cmp;/* Used indexes map.        */
   1625     int                 idx;            /* Loop termination index.  */
   1626     _range_t            *tmp = NULL;    /* Range pointer */
   1627     int                 idx_max;        /* Loop termination index.  */
   1628     soc_mem_t           mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */
   1629     bcm_range_oper_mode_t   oper_mode = 0;  /*Range module operational mode */
   1630     int pipe_instance = 0;
   1631     uint8 resource_avail = 0;
   1632     int rv = 0;
   1633     uint32 range_group_id = -1;
   1634 
   1635     /* Input parameters check */
   1636     BCM_IF_NULL_RETURN_PARAM(range_group_config);
   1637 
   1638     rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode);
   1639     if (BCM_FAILURE(rv)) {
   1640         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1641                 (BSL_META_U(unit,
   1642                             "bcmi_xgs5_range_group_create: Error Fetching Range Oper Mode \n")));
   1643         return (rv);
   1644     }
   1645 
   1646     rv = bcmi_xgs5_range_validate_port_config(unit, oper_mode,
   1647                                               range_group_config->ports, &pipe_instance);
   1648     if (BCM_FAILURE(rv)) {
   1649         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1650                 (BSL_META_U(unit,
   1651                             "bcmi_xgs5_range_group_create: Error Validating Port Config \n")));
   1652         return (rv);
   1653     }
   1654 
   1655     /* Validate resource availability */
   1656     for (idx = 0; idx < RANGE_CTRL(unit)->max_groups; idx++) {
   1657          if (0 == SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), idx)) {
   1658              resource_avail = 1;
   1659              range_group_id = idx;
   1660              break;
   1661          }
   1662     }
   1663     if (!resource_avail) {
   1664         LOG_CLI((BSL_META("bcmi_xgs5_range_group_create: Range group resources are not available\n")));
   1665         return BCM_E_RESOURCE;
   1666     }
   1667 
   1668     idx_max = soc_mem_index_max(unit, mem);
   1669     range_hw_bmap = NULL;
   1670 
   1671     RANGE_MALLOC(range_hw_bmap, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges");
   1672     if (NULL == range_hw_bmap) {
   1673         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1674                 (BSL_META_U(unit,
   1675                         "bcmi_xgs5_range_group_create: Error Allocating memory for range_bmap \n")));
   1676         return (BCM_E_MEMORY);
   1677     }
   1678 
   1679     range_hw_bmap_cmp = NULL;
   1680 
   1681     RANGE_MALLOC(range_hw_bmap_cmp, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges");
   1682     if (NULL == range_hw_bmap_cmp) {
   1683         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1684                 (BSL_META_U(unit,
   1685                         "bcmi_xgs5_range_group_create: Error Allocating memory for range_bmap_cmp \n")));
   1686         sal_free(range_hw_bmap);
   1687         return (BCM_E_MEMORY);
   1688     }
   1689 
   1690 
   1691     /* Get HW index of range ids in bitmap */
   1692     for (idx = 0; idx < RANGE_CTRL(unit)->max_ranges; idx ++ ) {
   1693          if (BCM_RANGE_ID_BMP_TEST(range_group_config->range_bmp, idx)) {
   1694              for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) {
   1695                   if (idx == tmp->rid) {
   1696                       SHR_BITSET(range_hw_bmap, tmp->hw_index);
   1697                   }
   1698              }
   1699          }
   1700     }
   1701 
   1702     /* Check if same range group already exists */
   1703     for (idx = 0; idx < RANGE_CTRL(unit)->max_groups; idx++) {
   1704          if (SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), idx)) {
   1705              rv = bcmi_range_group_hw_get(unit, idx, range_hw_bmap_cmp,
   1706                                           oper_mode, pipe_instance);
   1707              if (BCM_FAILURE(rv)) {
   1708                  sal_free(range_hw_bmap);
   1709                  sal_free(range_hw_bmap_cmp);
   1710                  return rv;
   1711              }
   1712 
   1713              if (!(sal_memcmp(range_hw_bmap, range_hw_bmap_cmp,
   1714                             (SHR_BITALLOCSIZE(idx_max + 1))))) {
   1715                  sal_free(range_hw_bmap);
   1716                  sal_free(range_hw_bmap_cmp);
   1717                  return (BCM_E_EXISTS);
   1718 
   1719              }
   1720          }
   1721     }
   1722 
   1723     /* Call install function with mask id[range group id] */
   1724 
   1725     rv = bcmi_range_group_hw_install(unit, range_group_id,
   1726                                      range_hw_bmap, oper_mode, pipe_instance);
   1727     if (BCM_SUCCESS(rv)) {
   1728         SHR_BITSET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance),
   1729                      range_group_id);
   1730         range_group_config->range_group_id = (range_group_id
   1731                                               + (RANGE_CTRL(unit)->max_groups * pipe_instance));
   1732     }
   1733 
   1734     LOG_DEBUG(BSL_LS_BCM_RANGE,
   1735             (BSL_META_U(unit,
   1736                         "bcmi_xgs5_range_group_create: Range Create Successful \n")));
   1737 
   1738     sal_free(range_hw_bmap);
   1739     sal_free(range_hw_bmap_cmp);
   1740     return rv;
   1741 }
   1742 
   1743 
   1744 /*
   1745  * This API will help to delete the range group created using
   1746  * bcm_range_group_create.
   1747  */
   1748 int bcmi_xgs5_range_group_delete(
   1749     int unit,
   1750     bcm_range_group_config_t *range_group_config)
   1751 {
   1752     SHR_BITDCL          *range_hw_bmap;    /* Used indexes map.        */
   1753     int                 idx_max;        /* Loop termination index.  */
   1754     soc_mem_t           mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */
   1755     bcm_range_oper_mode_t   oper_mode = 0;  /*Range module operational mode */
   1756     int pipe_instance = 0;
   1757     int rv = 0;
   1758     uint32 range_group_id = 0;
   1759 
   1760     /* Input parameters check */
   1761     BCM_IF_NULL_RETURN_PARAM(range_group_config);
   1762 
   1763     rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode);
   1764     if (BCM_FAILURE(rv)) {
   1765         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1766                 (BSL_META_U(unit,
   1767                             "bcmi_xgs5_range_group_delete: Error Fetching Range Oper Mode \n")));
   1768         return (rv);
   1769     }
   1770 
   1771     pipe_instance = (range_group_config->range_group_id / RANGE_CTRL(unit)->max_groups);
   1772     range_group_id = (range_group_config->range_group_id % RANGE_CTRL(unit)->max_groups);
   1773 
   1774     if ((pipe_instance < 0) || (pipe_instance >= SOC_MAX_NUM_PIPES)) {
   1775          LOG_DEBUG(BSL_LS_BCM_RANGE,
   1776                  (BSL_META_U(unit,
   1777                              "bcmi_xgs5_range_group_delete: Error Validating Range Group ID \n")));
   1778          return (BCM_E_INTERNAL);
   1779     }
   1780 
   1781     BCM_IF_ERROR_RETURN (rv);
   1782 
   1783     idx_max = soc_mem_index_max(unit, mem);
   1784     range_hw_bmap = NULL;
   1785 
   1786     RANGE_MALLOC(range_hw_bmap, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges");
   1787     if (NULL == range_hw_bmap) {
   1788         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1789                 (BSL_META_U(unit,
   1790                         "bcmi_xgs5_range_group_delete: Error Allocating memory for range_bmap \n")));
   1791         return (BCM_E_MEMORY);
   1792     }
   1793 
   1794     if (SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance),
   1795                      range_group_id)) {
   1796         rv = bcmi_range_group_hw_install(unit, range_group_id,
   1797                                          range_hw_bmap, oper_mode, pipe_instance);
   1798         SHR_BITCLR(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance),
   1799                      range_group_id);
   1800     } else {
   1801         rv = BCM_E_NOT_FOUND;
   1802     }
   1803 
   1804     LOG_DEBUG(BSL_LS_BCM_RANGE,
   1805             (BSL_META_U(unit,
   1806                         "bcmi_xgs5_range_group_delete: Range Create Successful \n")));
   1807 
   1808     sal_free(range_hw_bmap);
   1809     return rv;
   1810 }
   1811 
   1812 /*
   1813  * This API will help to update the range IDs in the range group created
   1814  * using bcm_range_group_create.
   1815  */
   1816 int bcmi_xgs5_range_group_update(
   1817     int unit,
   1818     bcm_range_group_config_t *range_group_config)
   1819 {
   1820     SHR_BITDCL          *range_hw_bmap;    /* Used indexes map.        */
   1821     SHR_BITDCL          *range_hw_bmap_cmp;/* Used indexes map.        */
   1822     int                 idx;            /* Loop termination index.  */
   1823     _range_t            *tmp = NULL;    /* Range pointer */
   1824     int                 idx_max;        /* Loop termination index.  */
   1825     soc_mem_t           mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */
   1826     bcm_range_oper_mode_t   oper_mode = 0;  /*Range module operational mode */
   1827     int pipe_instance = 0;
   1828     int rv = 0;
   1829     uint32 range_group_id = 0;
   1830 
   1831     /* Input parameters check */
   1832     BCM_IF_NULL_RETURN_PARAM(range_group_config);
   1833 
   1834     rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode);
   1835     if (BCM_FAILURE(rv)) {
   1836         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1837                 (BSL_META_U(unit,
   1838                             "bcmi_xgs5_range_group_update: Error Fetching Range Oper Mode \n")));
   1839         return (rv);
   1840     }
   1841 
   1842     pipe_instance = (range_group_config->range_group_id / RANGE_CTRL(unit)->max_groups);
   1843     range_group_id = (range_group_config->range_group_id % RANGE_CTRL(unit)->max_groups);
   1844 
   1845     if ((pipe_instance < 0) || (pipe_instance >= SOC_MAX_NUM_PIPES)) {
   1846          LOG_DEBUG(BSL_LS_BCM_RANGE,
   1847                  (BSL_META_U(unit,
   1848                              "bcmi_xgs5_range_group_update: Error Validating Range Group ID \n")));
   1849          return (BCM_E_INTERNAL);
   1850     }
   1851 
   1852     idx_max = soc_mem_index_max(unit, mem);
   1853     range_hw_bmap = NULL;
   1854 
   1855     RANGE_MALLOC(range_hw_bmap, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges");
   1856     if (NULL == range_hw_bmap) {
   1857         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1858                 (BSL_META_U(unit,
   1859                         "bcmi_xgs5_range_group_update: Error Allocating memory for range_bmap \n")));
   1860         return (BCM_E_MEMORY);
   1861     }
   1862 
   1863     range_hw_bmap_cmp = NULL;
   1864 
   1865     RANGE_MALLOC(range_hw_bmap_cmp, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges");
   1866     if (NULL == range_hw_bmap_cmp) {
   1867         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1868                 (BSL_META_U(unit,
   1869                         "bcmi_xgs5_range_group_update: Error Allocating memory for range_bmap_cmp \n")));
   1870         sal_free(range_hw_bmap);
   1871         return (BCM_E_MEMORY);
   1872     }
   1873 
   1874     /* Get HW index of range ids in bitmap */
   1875     for (idx = 0; idx < RANGE_CTRL(unit)->max_ranges; idx ++ ) {
   1876          if (BCM_RANGE_ID_BMP_TEST(range_group_config->range_bmp, idx)) {
   1877              for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) {
   1878                   if (idx == tmp->rid) {
   1879                       SHR_BITSET(range_hw_bmap, tmp->hw_index);
   1880                   }
   1881              }
   1882          }
   1883     }
   1884 
   1885     /* Check if same range group already exists */
   1886     for (idx = 0; idx < RANGE_CTRL(unit)->max_groups; idx++) {
   1887          if (SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance), idx)) {
   1888              rv = bcmi_range_group_hw_get(unit, idx, range_hw_bmap_cmp,
   1889                                           oper_mode, pipe_instance);
   1890              if (BCM_FAILURE(rv)) {
   1891                  sal_free(range_hw_bmap);
   1892                  sal_free(range_hw_bmap_cmp);
   1893                  return rv;
   1894              }
   1895 
   1896              if (!(sal_memcmp(range_hw_bmap, range_hw_bmap_cmp,
   1897                             (SHR_BITALLOCSIZE(idx_max + 1))))) {
   1898                  sal_free(range_hw_bmap);
   1899                  sal_free(range_hw_bmap_cmp);
   1900                  return (BCM_E_EXISTS);
   1901 
   1902              }
   1903          }
   1904     }
   1905 
   1906     if (SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance),
   1907                      range_group_id)) {
   1908         rv = bcmi_range_group_hw_install(unit, range_group_id,
   1909                                          range_hw_bmap, oper_mode, pipe_instance);
   1910     } else {
   1911         rv = BCM_E_NOT_FOUND;
   1912     }
   1913 
   1914     LOG_DEBUG(BSL_LS_BCM_RANGE,
   1915             (BSL_META_U(unit,
   1916                         "bcmi_xgs5_range_group_update: Range Create Successful \n")));
   1917 
   1918     sal_free(range_hw_bmap);
   1919     sal_free(range_hw_bmap_cmp);
   1920     return rv;
   1921 
   1922 }
   1923 
   1924 /*
   1925  * This API will help to fetch the range group configuration created
   1926  * using bcm_range_group_create.
   1927  */
   1928 int bcmi_xgs5_range_group_get(
   1929     int unit,
   1930     bcm_range_group_config_t *range_group_config)
   1931 {
   1932     SHR_BITDCL          *range_hw_bmap;    /* Used indexes map.        */
   1933     int                 idx;            /* Loop termination index.  */
   1934     _range_t            *tmp = NULL;    /* Range pointer */
   1935     int                 idx_max;        /* Loop termination index.  */
   1936     soc_mem_t           mem = RANGE_CTRL(unit)->range_mem; /* Range Checker Memory ID */
   1937     bcm_range_oper_mode_t   oper_mode = 0;  /*Range module operational mode */
   1938     int pipe_instance = 0;
   1939     int rv = 0;
   1940     uint32 range_group_id = 0;
   1941 
   1942     /* Input parameters check */
   1943     BCM_IF_NULL_RETURN_PARAM(range_group_config);
   1944 
   1945     rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode);
   1946     if (BCM_FAILURE(rv)) {
   1947         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1948                 (BSL_META_U(unit,
   1949                             "bcmi_xgs5_range_group_get: Error Fetching Range Oper Mode \n")));
   1950         return (rv);
   1951     }
   1952 
   1953     pipe_instance = (range_group_config->range_group_id / RANGE_CTRL(unit)->max_groups);
   1954     range_group_id = (range_group_config->range_group_id % RANGE_CTRL(unit)->max_groups);
   1955 
   1956     if ((pipe_instance < 0) || (pipe_instance >= SOC_MAX_NUM_PIPES)) {
   1957          LOG_DEBUG(BSL_LS_BCM_RANGE,
   1958                  (BSL_META_U(unit,
   1959                              "bcmi_xgs5_range_group_get: Error Validating Range Group ID \n")));
   1960          return (BCM_E_INTERNAL);
   1961     }
   1962 
   1963     idx_max = soc_mem_index_max(unit, mem);
   1964     range_hw_bmap = NULL;
   1965 
   1966     RANGE_MALLOC(range_hw_bmap, SHR_BITDCL, SHR_BITALLOCSIZE(idx_max + 1), "Valid Ranges");
   1967     if (NULL == range_hw_bmap) {
   1968         LOG_DEBUG(BSL_LS_BCM_RANGE,
   1969                 (BSL_META_U(unit,
   1970                         "bcmi_xgs5_range_group_get: Error Allocating memory for range_bmap \n")));
   1971         return (BCM_E_MEMORY);
   1972     }
   1973 
   1974     if (SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap) + pipe_instance),
   1975                      range_group_id)) {
   1976         rv = bcmi_range_group_hw_get(unit, range_group_id,
   1977                                      range_hw_bmap, oper_mode, pipe_instance);
   1978     } else {
   1979         rv = BCM_E_NOT_FOUND;
   1980     }
   1981 
   1982     /* Convert hw bmap to range id bmap */
   1983     for (idx = 0; idx < RANGE_CTRL(unit)->max_ranges; idx ++ ) {
   1984          if (SHR_BITGET(range_hw_bmap, idx)) {
   1985              for (tmp = RANGE_CTRL(unit)->ranges; tmp != NULL; tmp = tmp->next) {
   1986                   if (idx == tmp->hw_index) {
   1987                       BCM_RANGE_ID_BMP_ADD(range_group_config->range_bmp, tmp->rid);
   1988                   }
   1989              }
   1990          }
   1991     }
   1992 
   1993     LOG_DEBUG(BSL_LS_BCM_RANGE,
   1994             (BSL_META_U(unit,
   1995                         "bcmi_xgs5_range_group_get: Range Create Successful \n")));
   1996 
   1997     sal_free(range_hw_bmap);
   1998     return rv;
   1999 }
   2000 
   2001 /*  Function    :   bcmi_xgs5_range_group_hw_idx_get
   2002  *  Purpose     :   Fetch Range Group HW Index
   2003  *  Parameters  :   unit - (IN) Unit number.
   2004  *                  range_group_id  - (IN) Range Group ID.
   2005                     pipe_id - (IN) Pipe Instance
   2006                     hw_index - (OUT) Hardware index
   2007  *  Returns     :   BCM_E_XXX
   2008  */
   2009 int bcmi_xgs5_range_group_hw_idx_get(
   2010         int unit,
   2011         uint8 range_grp_id,
   2012         uint8 pipe_id,
   2013         uint8 *hw_index)
   2014 {
   2015     uint32 range_group_id = 0;
   2016     int pipe_instance = 0;
   2017     bcm_range_oper_mode_t   oper_mode = 0;  /*Range module operational mode */
   2018     int rv = BCM_E_NONE;
   2019 
   2020     if (range_grp_id > ((RANGE_CTRL(unit)->max_groups * SOC_MAX_NUM_PIPES) - 1)) {
   2021          return BCM_E_PARAM;
   2022     }
   2023 
   2024     pipe_instance = (range_grp_id / RANGE_CTRL(unit)->max_groups);
   2025     range_group_id = (range_grp_id % RANGE_CTRL(unit)->max_groups);
   2026 
   2027     rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode);
   2028     if (BCM_FAILURE(rv)) {
   2029         LOG_DEBUG(BSL_LS_BCM_RANGE,
   2030                 (BSL_META_U(unit,
   2031                             "bcmi_xgs5_range_group_hw_idx_get: Error Fetching Range Oper Mode \n")));
   2032         return (rv);
   2033     }
   2034 
   2035     if ((pipe_instance != pipe_id) && (oper_mode == bcmRangeOperModePipeLocal)) {
   2036          LOG_DEBUG(BSL_LS_BCM_RANGE,
   2037                  (BSL_META_U(unit,
   2038                              "bcmi_xgs5_range_group_hw_idx_get: Error Validating Pipe Instance \n")));
   2039          return BCM_E_PARAM;
   2040     }
   2041 
   2042     if ((pipe_instance < 0) || (pipe_instance >= SOC_MAX_NUM_PIPES)) {
   2043          LOG_DEBUG(BSL_LS_BCM_RANGE,
   2044                  (BSL_META_U(unit,
   2045                              "bcmi_xgs5_range_group_hw_idx_get: Error Validating Range Group ID \n")));
   2046          return BCM_E_PARAM;
   2047     }
   2048 
   2049     if (!(SHR_BITGET(((RANGE_CTRL(unit)->range_group_used_bitmap)
   2050           + pipe_instance), range_group_id))) {
   2051         return BCM_E_PARAM;
   2052     }
   2053 
   2054     *hw_index = range_group_id;
   2055     return rv;
   2056 }
   2057 
   2058 /*  Function    :   bcmi_xgs5_range_group_id_get
   2059  *  Purpose     :   Fetch Range Group Id
   2060  *  Parameters  :   unit - (IN) Unit number.
   2061                     pipe_id - (IN) Pipe Instance.
   2062                     hw_index - (IN) Hardware index
   2063  *                  range_group_id  - (OUT) Range Group ID.
   2064  *  Returns     :   BCM_E_XXX
   2065  */
   2066 int bcmi_xgs5_range_group_id_get(
   2067         int unit,
   2068         uint8 pipe_id,
   2069         uint8 *range_grp_id)
   2070 {
   2071     int rv = BCM_E_NONE;
   2072     bcm_range_oper_mode_t   oper_mode = 0;  /*Range module operational mode */
   2073 
   2074     rv = bcmi_xgs5_range_oper_mode_get(unit, &oper_mode);
   2075     if (BCM_FAILURE(rv)) {
   2076         LOG_DEBUG(BSL_LS_BCM_RANGE,
   2077                 (BSL_META_U(unit,
   2078                             "bcmi_xgs5_range_group_hw_idx_get: Error Fetching Range Oper Mode \n")));
   2079         return (rv);
   2080     }
   2081 
   2082     if (oper_mode == bcmRangeOperModePipeLocal) {
   2083         *range_grp_id = (*range_grp_id)
   2084                  + (RANGE_CTRL(unit)->max_groups * pipe_id);
   2085     }
   2086 
   2087     return rv;
   2088 }
   2089