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

flowcnt_common.c (155806B)


      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:        flowcnt_common.c
      8  * Purpose:     Manage common functionality for flow counter implementation
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <bcm/stat.h>
     14 #include <bcm/module.h>
     15 #include <bcm_int/esw/flowcnt.h>
     16 #include <bcm_int/esw/stat.h>
     17 #include <soc/scache.h>
     18 
     19 
     20 static _bcm_esw_flowcnt_control_t *flowcnt_control[SOC_MAX_NUM_DEVICES]={NULL};
     21 
     22 typedef struct {
     23     uint32 entry_data[BYTES2WORDS(5)];
     24 }counter_table_entry_t;
     25 
     26 #define MAX_FLOWCNT_COUNTER_TABLE_SIZE  (512)
     27 
     28 static counter_table_entry_t *flowcnt_temp_counter[SOC_MAX_NUM_DEVICES] = {NULL};
     29 
     30 /* for those counter indexes created but not attached */
     31 #define MAX_FLOWCNT_SCACHE_SIZE (32)
     32 static uint8 *local_scache_ptr[SOC_MAX_NUM_DEVICES]={NULL};
     33 static uint32 local_scache_size=0;
     34 
     35 #define FLOWCNT_SCACHE_SIZE_1 (MAX_FLOWCNT_SCACHE_SIZE * sizeof(uint32))
     36 #ifdef BCM_WARM_BOOT_SUPPORT
     37 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3)
     38 static soc_scache_handle_t handle=0;
     39 static uint32 flowcnt_scache_allocated_size[SOC_MAX_NUM_DEVICES]= {0};
     40 static uint8 *flowcnt_scache_ptr[SOC_MAX_NUM_DEVICES]={NULL};
     41 STATIC int _bcm_esw_flowcnt_warmboot_info_recover(int unit,uint8 *scache_ptr);
     42 STATIC int _bcm_esw_flowcnt_warmboot_object_retrive(int unit);
     43 /* scache layout of flowcnt
     44  *   1. stat_counter_id
     45  *   2. default_attr_mode_id (size maybe change because of
     46  *                            bcmStatGroupModeAttrMaxValue)
     47  *          local   : the size according the current mode attr max value
     48  *          recover : the size in scache
     49  *             when firmware upgrade, "local" maybe be larger than "recover"
     50  *             when firmware downgrade, "local" maybe be less than "recover"
     51  *   3. flowcnt_group_info
     52  */
     53 #define FLOWCNT_SCACHE_SIZE_2_LOCAL (sizeof(_bcm_flowcnt_warmboot_info_t))
     54 #define FLOWCNT_SCACHE_SIZE_2_RECOVER(unit) (flowcnt_scache_allocated_size[unit]\
     55                                        - FLOWCNT_SCACHE_SIZE_1\
     56                                        - FLOWCNT_SCACHE_SIZE_3)
     57 #define FLOWCNT_SCACHE_SIZE_3 (sizeof(_bcm_flowcnt_warmboot_group_info_t) *\
     58                               _BCM_STAT_FLOWCNT_MAX_PROFILE_GROUP *\
     59                               _BCM_STAT_FLOWCNT_MAX_PROFILES)
     60 #endif
     61 
     62 #define _BCM_FLOWCNT_MODE_ID_VALID  (0x80000000)
     63 
     64 /* need to add bias to tell if value of the pgroup is valid*/
     65 #define _BCM_FLOWCNT_PGROUP_BIAS   (0xF)
     66 /*
     67  * Macro:
     68  *     _FLOWCNT_IS_INIT (internal)
     69  * Purpose:
     70  *     Check that the unit is valid and confirm that the oam functions
     71  *     are initialized.
     72  * Parameters:
     73  *     unit - BCM device number
     74  * Notes:
     75  *     Results in return(BCM_E_UNIT), return(BCM_E_UNAVAIL), or
     76  *     return(BCM_E_INIT) if fails.
     77  */
     78 #define _FLOWCNT_IS_INIT(unit)                                               \
     79             do {                                                             \
     80                 if (!soc_feature(unit, soc_feature_flowcnt)) {               \
     81                     return (BCM_E_UNAVAIL);                                  \
     82                 }                                                            \
     83                 if (flowcnt_control[unit] == NULL) {                            \
     84                     LOG_ERROR(BSL_LS_BCM_FLEXCTR, \
     85                               (BSL_META_U(unit, \
     86                                           "Flowcnt Error: Module not initialized\n"))); \
     87                     return (BCM_E_INIT);                                     \
     88                 }                                                            \
     89             } while (0)
     90 
     91 /*
     92  * Macro:
     93  *     _FLOWCNT_ALLOC
     94  * Purpose:
     95  *      Generic memory allocation routine.
     96  * Parameters:
     97  *    _unit_    - Unit.
     98  *    _ptr_     - Pointer to allocated memory.
     99  *    _ptype_   - Pointer type.
    100  *    _size_    - Size of heap memory to be allocated.
    101  *    _descr_   - Information about this memory allocation.
    102  *    _dma_     - use sal_alloc or soc_cm_alloc.
    103  *    _rv_      - return value
    104  */
    105 #define _FLOWCNT_ALLOC(_unit_,_ptr_,_ptype_,_size_,_descr_,_dma_,_rv_) \
    106             do { \
    107                 if (NULL == (_ptr_)) { \
    108                     if (0 == (_dma_)) { \
    109                         (_ptr_) = (_ptype_ *) sal_alloc((_size_), (_descr_)); \
    110                     } else { \
    111                         (_ptr_) = (_ptype_ *) soc_cm_salloc((_unit_),(_size_), \
    112                                                             (_descr_)); \
    113                     } \
    114                 } \
    115                 if((_ptr_) != NULL) { \
    116                     sal_memset((_ptr_), 0, (_size_)); \
    117                     _rv_ = BCM_E_NONE; \
    118                 }  else { \
    119                     LOG_ERROR(BSL_LS_BCM_FLEXCTR, \
    120                               (BSL_META("Flowcnt Error: Allocation failure %s\n"), \
    121                                (_descr_))); \
    122                     _rv_ = BCM_E_MEMORY; \
    123                 } \
    124             } while (0)
    125 
    126 #define _FLOWCNT_FREE(_unit, _ptr, _dma) \
    127             do {\
    128                     if (0 == (_dma)) { \
    129                         sal_free((_ptr)); \
    130                     } else { \
    131                         soc_cm_sfree((_unit), (_ptr)); \
    132                     }\
    133                 } while (0)
    134 
    135 #define _FLOWCNT_LOCK(fc) \
    136         sal_mutex_take((fc)->flowcnt_mutex, sal_mutex_FOREVER);
    137 #define _FLOWCNT_UNLOCK(fc) \
    138         sal_mutex_give((fc)->flowcnt_mutex);
    139 
    140 #define _FLOWCNT_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
    141 
    142 typedef struct flowcnt_profile_table_info_s {
    143     soc_mem_t   mem;        /* profile mem */
    144     int         num_groups;  /* numbers of group per profile */
    145     bcm_stat_group_mode_attr_t  attr;
    146     bcm_stat_flex_direction_t   direction;
    147 } flowcnt_profile_table_info_t;
    148 
    149 typedef struct flowcnt_object_table_fields_s {
    150     char    *key_type;
    151     soc_field_t base_index_field;
    152     soc_field_t profile_ptr_field;
    153 } flowcnt_object_table_fields_t;
    154 
    155 typedef struct flowcnt_object_info_s {
    156     bcm_stat_object_t   object;
    157     soc_mem_t   object_mem;
    158     soc_mem_t   offset_mem;
    159     soc_mem_t   counter_mem;
    160     soc_field_t view_field;
    161     flowcnt_object_table_fields_t counter_fields;
    162 }flowcnt_object_info_t;
    163 
    164 /* 
    165   * Normally reserve_count is 1. i.e. reserve index 0 for warmboot 
    166   */
    167 typedef struct flowcnt_pool_table_info_s {
    168     soc_mem_t pool_mem;
    169     uint32    reserve_base;
    170     uint32    reserve_count;
    171 }flowcnt_pool_table_info_t;
    172 
    173 static flowcnt_profile_table_info_t _hr3_flowcnt_profile_table[] = {
    174     {ING_VLAN_COUNTER_PRI_COS_MAPm, 4, 
    175         bcmStatGroupModeAttrPktCfiPri, bcmStatFlexDirectionIngress},
    176     {EGR_VLAN_COUNTER_PRI_COS_MAPm, 4, 
    177         bcmStatGroupModeAttrPktCfiPri, bcmStatFlexDirectionEgress},
    178 };
    179 
    180 /* in HR3, reserve indx0-7 for ambiguous count */
    181 static flowcnt_pool_table_info_t _hr3_flowcnt_pool_table[] = {
    182     {ING_VLAN_COUNTER_TABLEm, 0, 8},
    183     {EGR_VLAN_COUNTER_TABLEm, 0, 8},
    184 };
    185 
    186 static int _hr3_stat_group_mode_info[] = {
    187     bcmStatGroupModeSingle,
    188     -1
    189 };
    190 
    191 static flowcnt_object_info_t _hr3_stat_object_info[] = {
    192     {bcmStatObjectIngVlanXlate, VLAN_XLATEm, 
    193         ING_VLAN_COUNTER_PRI_COS_MAPm,
    194         ING_VLAN_COUNTER_TABLEm, KEY_TYPEf,
    195         {"XLATE", XLATE__VLAN_CTR_BASE_INDEXf, XLATE__VLAN_CTR_PROFILE_PTRf}
    196         },
    197     {bcmStatObjectIngFieldStageLookup, VFP_POLICY_TABLEm,
    198         ING_VLAN_COUNTER_PRI_COS_MAPm,
    199         ING_VLAN_COUNTER_TABLEm, -1,
    200         {"", VLAN_CTR_BASE_INDEXf, VLAN_CTR_PROFILE_PTRf}
    201         },
    202     {bcmStatObjectEgrVlanXlate, EGR_VLAN_XLATEm, 
    203         EGR_VLAN_COUNTER_PRI_COS_MAPm,
    204         EGR_VLAN_COUNTER_TABLEm, ENTRY_TYPEf,
    205         {"XLATE", XLATE__VLAN_CTR_BASE_INDEXf, XLATE__VLAN_CTR_PROFILE_PTRf}
    206         },
    207     {-1, -1, -1, -1, -1,{NULL,-1,-1}}
    208 };
    209 
    210 static flowcnt_pool_table_info_t *flowcnt_pool_table[SOC_MAX_NUM_DEVICES] = {NULL};
    211 static flowcnt_profile_table_info_t *flowcnt_profile_table[SOC_MAX_NUM_DEVICES] = {NULL};
    212 static int *valid_stat_group_mode_list[SOC_MAX_NUM_DEVICES] = {NULL};
    213 static flowcnt_object_info_t *valid_stat_object_list[SOC_MAX_NUM_DEVICES] = {NULL};
    214 
    215 
    216 STATIC int
    217 _bcm_esw_flowcnt_control_get(int unit, _bcm_esw_flowcnt_control_t **fc)
    218 {
    219     if (NULL == fc) {
    220         return (BCM_E_PARAM);
    221     }
    222     /* Ensure flowcnt module is initialized. */
    223     _FLOWCNT_IS_INIT(unit);
    224 
    225     *fc = flowcnt_control[unit];
    226 
    227     return (BCM_E_NONE);
    228 }
    229 
    230 STATIC 
    231 int _bcm_esw_flowcnt_stat_object_validate(
    232     int unit, 
    233     bcm_stat_object_t object)
    234 {
    235     int i;
    236     int rv = BCM_E_PARAM;
    237     flowcnt_object_info_t *stat_object_list;
    238 
    239     if (valid_stat_object_list[unit] == NULL){
    240         return BCM_E_INTERNAL;
    241     }
    242     stat_object_list = valid_stat_object_list[unit];
    243     for (i = 0; stat_object_list[i].object != -1; i++) {
    244         if (stat_object_list[i].object == object){
    245             rv = BCM_E_NONE;
    246             break;
    247         }
    248     }
    249 
    250     return rv;
    251 
    252 }
    253 
    254 STATIC int 
    255 _bcm_esw_flowcnt_stat_group_mode_validate(int unit,
    256                 bcm_stat_group_mode_t group_mode)
    257 {
    258     int i;
    259     int rv = BCM_E_PARAM;
    260 
    261     if (valid_stat_group_mode_list[unit] == NULL){
    262         return BCM_E_INTERNAL;
    263     }
    264     for (i = 0; valid_stat_group_mode_list[unit][i] != -1; i++) {
    265         if (valid_stat_group_mode_list[unit][i] == group_mode){
    266             rv = BCM_E_NONE;
    267             break;
    268         }
    269     }
    270     return rv;
    271 }
    272 
    273 STATIC int
    274 _bcm_hr3_flowcnt_ctrl_init(int unit, _bcm_esw_flowcnt_control_t *fc)
    275 {
    276     int rv;
    277     valid_stat_group_mode_list[unit] = _hr3_stat_group_mode_info;
    278     valid_stat_object_list[unit] = _hr3_stat_object_info;
    279     flowcnt_profile_table[unit] = _hr3_flowcnt_profile_table;
    280     flowcnt_pool_table[unit] = _hr3_flowcnt_pool_table;
    281     fc->num_profiles = _FLOWCNT_ARRAY_SIZE(_hr3_flowcnt_profile_table);
    282     fc->num_pools = _FLOWCNT_ARRAY_SIZE(_hr3_flowcnt_pool_table);
    283     /* The max value of the offset field on ING/EGR_VLAN_COUNTER_PRI_COS_MAP 
    284        in power of two */
    285     fc->counter_block = 3;
    286     _FLOWCNT_ALLOC(unit, flowcnt_temp_counter[unit], counter_table_entry_t,
    287                    MAX_FLOWCNT_COUNTER_TABLE_SIZE *
    288                    sizeof(counter_table_entry_t),
    289                    "temp_counter", 1, rv);
    290 
    291     if (BCM_FAILURE(rv)) {
    292         return rv;
    293     }
    294     return BCM_E_NONE;
    295 }
    296 
    297 /*
    298  * Function:
    299  *      _bcm_esw_flowcnt_object_table_index_get
    300  * Description:
    301  *      Get the object table index based on the object mem informantion based
    302  *      on the object or object_mem.
    303  * Parameters:
    304  *      unit                - (IN) unit number
    305  *      index               - (IN) index in the object mem.
    306  *      table               - (IN) object memory.
    307  *      data                - (IN) entry data
    308  *      object_index        - (OUT) valid_stat_object_list index
    309  *
    310  * Return Value:
    311  *      BCM_E_XXX
    312  * Notes:
    313  */
    314 STATIC int
    315 _bcm_esw_flowcnt_object_table_index_get(
    316     int       unit,
    317     uint32    index,
    318     soc_mem_t table,
    319     void      *data,
    320     int *object_index)
    321 {
    322     int i;
    323     soc_field_t view_field = INVALIDf;
    324     soc_mem_info_t *memp;
    325     uint32 key_type=0;
    326     flowcnt_object_info_t *stat_object_list;
    327     flowcnt_object_table_fields_t   *o_fields;
    328 
    329     *object_index = -1;
    330     stat_object_list = valid_stat_object_list[unit];
    331     for (i = 0; stat_object_list[i].object_mem != -1; i++) {
    332         if (stat_object_list[i].object_mem == table) {
    333             memp = &SOC_MEM_INFO(unit, table);
    334             view_field = stat_object_list[i].view_field;
    335             o_fields = &stat_object_list[i].counter_fields;
    336             if (view_field == INVALIDf) {
    337                 *object_index = i;
    338                 break;
    339             } else {
    340                 key_type = soc_mem_field32_get(unit, table, data, view_field);
    341                 LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
    342                           (BSL_META_U(unit,
    343                                       "key_type %d "),
    344                           key_type));
    345                 if (sal_strcmp(memp->views[key_type], o_fields->key_type) == 0) {
    346                     *object_index = i;
    347                     break;
    348                 }
    349             }
    350         }
    351     }
    352     if (*object_index == -1) {
    353         return BCM_E_INTERNAL;
    354     }
    355 
    356     return BCM_E_NONE;
    357 }
    358 
    359 STATIC int
    360 _bcm_esw_flowcnt_object_table_fields_get(
    361     int       unit,
    362     uint32    index,
    363     soc_mem_t table,
    364     void      *data,
    365     soc_field_t    *profile_ptr_field,
    366     soc_field_t    *base_idx_field)
    367 {
    368     int object_index=-1,rv=BCM_E_NONE;
    369     flowcnt_object_table_fields_t   *o_fields;
    370     flowcnt_object_info_t *stat_object_list;
    371 
    372     rv = _bcm_esw_flowcnt_object_table_index_get(
    373             unit, index, table, data, &object_index);
    374     if (BCM_FAILURE(rv)){
    375         return rv;
    376     }
    377     stat_object_list = valid_stat_object_list[unit];
    378     o_fields = &stat_object_list[object_index].counter_fields;
    379 
    380     *profile_ptr_field = o_fields->profile_ptr_field;
    381     *base_idx_field = o_fields->base_index_field;
    382 
    383     /* Just a safety check */
    384     if ((soc_mem_field_valid(unit,table,*profile_ptr_field) == FALSE) ||
    385         (soc_mem_field_valid(unit,table,*base_idx_field) == FALSE)){
    386         LOG_WARN(BSL_LS_BCM_FLEXCTR,
    387                  (BSL_META_U(unit,
    388                              "INTERNAL Error i.e. "
    389                               "required offset,base_idx fields are "
    390                               "not valid \n")));
    391         return BCM_E_INTERNAL;
    392     }
    393 
    394     return BCM_E_NONE;
    395 }
    396 
    397 
    398 STATIC int
    399 _bcm_esw_flowcnt_object_table_fields_values_get(
    400     int       unit,
    401     uint32    index,
    402     soc_mem_t table,
    403     void      *data,
    404     uint32    *profile_ptr,
    405     uint32    *base_idx)
    406 {
    407     int rv = BCM_E_NONE;
    408     soc_field_t profile_ptr_field = INVALIDf;
    409     soc_field_t base_index_field = INVALIDf;
    410 
    411     rv = _bcm_esw_flowcnt_object_table_fields_get(
    412          unit, index, table, data, &profile_ptr_field,
    413          &base_index_field);
    414 
    415     if (BCM_FAILURE(rv)){
    416         return rv;
    417     }
    418     *profile_ptr =  soc_mem_field32_get(unit,table,data,profile_ptr_field);
    419     *base_idx =  soc_mem_field32_get(unit,table,data,base_index_field);
    420     return rv;
    421 }
    422 
    423 STATIC int
    424 _bcm_esw_flowcnt_object_table_fields_values_set(
    425     int       unit,
    426     uint32    index,
    427     soc_mem_t table,
    428     void      *data,
    429     uint32    profile_ptr,
    430     uint32    base_idx)
    431 {
    432     int rv = BCM_E_NONE;
    433     soc_field_t profile_ptr_field = INVALIDf;
    434     soc_field_t base_index_field = INVALIDf;
    435 
    436     rv = _bcm_esw_flowcnt_object_table_fields_get(
    437          unit, index, table, data, &profile_ptr_field,
    438          &base_index_field);
    439 
    440     if (BCM_FAILURE(rv)){
    441         return rv;
    442     }
    443     soc_mem_field32_set(unit,table,data,profile_ptr_field,profile_ptr);
    444     soc_mem_field32_set(unit,table,data,base_index_field,base_idx);
    445     return rv;
    446 }
    447 
    448 /*
    449  * Function:
    450  *      _bcm_esw_flowcnt_stat_id_insert
    451  * Description:
    452  *      Inserts stat id in local scache table. Useful for WARM-BOOT purpose
    453  * Parameters:
    454  *      scache_ptr            - (IN) Local scache table pointer
    455  *      stat_counter_id       - (IN) Flex Stat Counter Id
    456  * Return Value:
    457  *      BCM_E_XXX
    458  * Notes:
    459  */
    460 static int
    461 _bcm_esw_flowcnt_stat_id_insert(uint8 *scache_ptr, uint32 stat_counter_id)
    462 {
    463     uint32 index = 0;
    464     uint32 *ptr = (uint32 *)scache_ptr;
    465     LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
    466               (BSL_META("Inserting %d "),
    467                stat_counter_id));
    468     for (index = 0; index < MAX_FLOWCNT_SCACHE_SIZE; index++) {
    469          if (ptr[index] == 0) {
    470              LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
    471                        (BSL_META("Inserted \n")));
    472              ptr[index] = stat_counter_id;
    473              break;
    474          }
    475     }
    476     if (index == MAX_FLOWCNT_SCACHE_SIZE) {
    477         return BCM_E_FAIL;
    478     }
    479     return BCM_E_NONE;
    480 }
    481 /*
    482  * Function:
    483  *      _bcm_esw_flowcnt_stat_id_delete
    484  * Description:
    485  *      Deletes stat id from local scache table. Useful for WARM-BOOT purpose
    486  * Parameters:
    487  *      scache_ptr            - (IN) Local scache table pointer
    488  *      stat_counter_id       - (IN) Flex Stat Counter Id
    489  * Return Value:
    490  *      BCM_E_XXX
    491  * Notes:
    492  */
    493 static int
    494 _bcm_esw_flowcnt_stat_id_delete(uint8 *scache_ptr,uint32 stat_counter_id)
    495 {
    496     uint32 index = 0;
    497     uint32 *ptr = (uint32 *)scache_ptr;
    498     LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
    499               (BSL_META("Deleting ID:%d "),
    500                stat_counter_id));
    501     for (index = 0; index < MAX_FLOWCNT_SCACHE_SIZE; index++) {
    502          if (ptr[index] == stat_counter_id) {
    503              LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
    504                        (BSL_META("Deleted \n")));
    505              ptr[index] = 0;
    506              break;
    507          }
    508     }
    509     if (index == MAX_FLOWCNT_SCACHE_SIZE) {
    510         return BCM_E_FAIL;
    511     }
    512     return BCM_E_NONE;
    513 }
    514 /*
    515  * Function:
    516  *      _bcm_esw_flowcnt_accounting_object_info_get
    517  * Description:
    518  *      Get object table info for given accounting table and index
    519  * Parameters
    520  *      unit                  - (IN) unit number
    521  *      table                 - (IN) Accounting Tables
    522  *      index                 - (IN) index of the accounting tables 
    523  *      profile_ptr           - (OUT) profile group mode
    524  *      base_index            - (OUT) base index
    525  *      object_index          - (OUT) index to internal object table 
    526  *                                      valid_stat_object_list
    527  * Return Value:
    528  *      BCM_E_XXX
    529  * Notes:
    530  */
    531 STATIC int 
    532 _bcm_esw_flowcnt_accounting_object_info_get(
    533             int         unit,
    534             soc_mem_t   table,
    535             int         index,
    536             uint32      *profile_ptr,
    537             uint32      *base_index,
    538             int         *object_index)
    539 {
    540     soc_mem_info_t *memp = NULL;
    541     int rv = BCM_E_NONE;
    542     void *entry_data = NULL;
    543     uint32 entry_data_size = 0;
    544 
    545     memp = &SOC_MEM_INFO(unit, table);
    546     entry_data_size = WORDS2BYTES(BYTES2WORDS(memp->bytes));
    547     _FLOWCNT_ALLOC(unit, entry_data, void, entry_data_size,
    548                "object table entry", 0, rv);
    549     if (BCM_FAILURE(rv)){
    550         return rv;
    551     }
    552     if (soc_mem_read(unit, table, MEM_BLOCK_ANY,
    553                      index,
    554                      entry_data) != SOC_E_NONE) {
    555         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
    556                   (BSL_META_U(unit,
    557                               "Read failure for Table %s with index %d \n"),
    558                    SOC_MEM_UFNAME(unit, table),index));
    559         _FLOWCNT_FREE(unit, entry_data, 0);
    560         return  BCM_E_INTERNAL;
    561     }
    562     if (soc_mem_field_valid(unit,table,VALIDf)) {
    563         if (soc_mem_field32_get(unit, table, entry_data, VALIDf)==0) {
    564             LOG_ERROR(BSL_LS_BCM_FLEXCTR,
    565                       (BSL_META_U(unit,
    566                                   "Table %s  with index %d is Not valid \n"),
    567                        SOC_MEM_UFNAME(unit, table),index));
    568             _FLOWCNT_FREE(unit, entry_data, 0);
    569             return BCM_E_PARAM;
    570         }
    571     }
    572 
    573     rv = _bcm_esw_flowcnt_object_table_fields_values_get(
    574             unit, index, table, entry_data,
    575             profile_ptr, base_index);
    576     if (BCM_FAILURE(rv)){
    577         _FLOWCNT_FREE(unit, entry_data, 0);
    578         return rv;
    579     }
    580     rv = _bcm_esw_flowcnt_object_table_index_get(
    581             unit, index, table, entry_data, object_index);
    582     if (BCM_FAILURE(rv)){
    583         _FLOWCNT_FREE(unit, entry_data, 0);
    584         return rv;
    585     }
    586     _FLOWCNT_FREE(unit, entry_data, 0);
    587 
    588     return BCM_E_NONE;
    589 }
    590 
    591 
    592 /*
    593  * Function:
    594  *      _bcm_flowcnt_ctrl_common_init
    595  * Description:
    596  *      Initialize and allocate all required resources for Hurricane3
    597  * Parameters:
    598  *      unit                  - (IN) unit number
    599  * Return Value:
    600  *      BCM_E_XXX
    601  *                            - if resource allocation errored, just returned.
    602  *                              Resource free should be taken care in upper layer.
    603  * Notes:
    604  *   
    605  *   _bcm_esw_flowcnt_profile_t *flowcnt_profile;
    606  *   int num_profiles;
    607  *   _bcm_esw_flowcnt_pool_t *flowcnt_pool;
    608  *   int num_pool;
    609  *   Above should be allocated and assigned per chip profile table.
    610  *
    611  *   shr_aidxres_list_handle_t flowcnt_aidxres_list_handle;
    612  *   uint32 flow_packet_counter;
    613  *   uint64 flow_byte_counter;
    614  *   uint64 flow_packet64_counter;
    615  *   uint16 flow_base_index_reference_count; 
    616  *   Above should be allocated and assigned per chip counter table.
    617  */
    618 STATIC int
    619 _bcm_flowcnt_ctrl_common_init(int unit, _bcm_esw_flowcnt_control_t *fc)
    620 {
    621     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
    622     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
    623     int i;
    624     int rv = BCM_E_NONE;
    625     soc_mem_t   mem;
    626     soc_mem_info_t *memp;
    627     int entry_words, num_ctr;
    628     flowcnt_profile_table_info_t  *profile_table;
    629     flowcnt_pool_table_info_t *pool_table;
    630 
    631     if (fc == NULL) {
    632         return BCM_E_MEMORY;
    633     }
    634     /* Allocate default attr mode id */
    635     _FLOWCNT_ALLOC(unit, fc->default_attr_mode_id, uint32,
    636                    bcmStatGroupModeAttrMaxValue * sizeof(uint32),
    637                    "Flowcnt default attr mode_id", 0, rv);
    638     if (BCM_FAILURE(rv)) {
    639         return rv;
    640     }
    641 
    642     /* Allocate the profile resource */
    643     _FLOWCNT_ALLOC(unit, fc->flowcnt_profile, _bcm_esw_flowcnt_profile_t,
    644                    fc->num_profiles * sizeof(_bcm_esw_flowcnt_profile_t),
    645                    "Flowcnt profile", 0, rv);
    646     if (BCM_FAILURE(rv)) {
    647         return rv;
    648     }
    649     profile_table = flowcnt_profile_table[unit];
    650     for (i = 0; i < fc->num_profiles; i++) {
    651         fc_profile = &fc->flowcnt_profile[i];
    652         mem = profile_table[i].mem;
    653         memp = &SOC_MEM_INFO(unit, mem);
    654         entry_words = BYTES2WORDS(memp->bytes);
    655         soc_profile_mem_t_init(&fc_profile->profile_mem);
    656         rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
    657                                     &fc_profile->profile_mem);
    658         if (BCM_FAILURE(rv)) {
    659             LOG_ERROR(BSL_LS_BCM_FLEXCTR,
    660                       (BSL_META_U(unit,
    661                                   "Flowcnt profile create - Failed.\n")));
    662             return (rv);
    663         }
    664         fc_profile->num_groups = profile_table[i].num_groups;
    665         _FLOWCNT_ALLOC(unit, fc_profile->flowcnt_group,
    666                    _bcm_esw_flowcnt_profile_group_t,
    667                    fc_profile->num_groups *
    668                    sizeof(_bcm_esw_flowcnt_profile_group_t),
    669                    "Flowcnt profile group", 0, rv);
    670         if (BCM_FAILURE(rv)) {
    671             return rv;
    672         }
    673         fc_profile->direction = profile_table[i].direction;
    674         fc_profile->attr = profile_table[i].attr;
    675         fc_profile->profile_table = mem;
    676         fc_profile->num_entries = soc_mem_index_count(unit, mem) /
    677                                     profile_table[i].num_groups;
    678     }
    679 
    680     /* Allocate the counter table resource */
    681     _FLOWCNT_ALLOC(unit, fc->flowcnt_pool, _bcm_esw_flowcnt_pool_t,
    682                    fc->num_pools * sizeof (_bcm_esw_flowcnt_pool_t),
    683                    "Flowcnt pool", 0, rv);
    684     if (BCM_FAILURE(rv)) {
    685         return rv;
    686     }
    687     pool_table = flowcnt_pool_table[unit];
    688     for (i = 0; i < fc->num_pools; i++) {
    689         fc_pool = &fc->flowcnt_pool[i];
    690         fc_pool->mem = pool_table[i].pool_mem;
    691         num_ctr = soc_mem_index_count(unit, fc_pool->mem);
    692 
    693         _FLOWCNT_ALLOC(unit, fc_pool->flow_byte_counter,
    694                        uint64,
    695                        sizeof(uint64) * num_ctr,
    696                        "Flow byte counter", 1, rv);
    697         if (BCM_FAILURE(rv)) {
    698             return rv;
    699         }
    700         _FLOWCNT_ALLOC(unit, fc_pool->flow_packet64_counter,
    701                        uint64,
    702                        sizeof(uint64) * num_ctr,
    703                        "Flow packet64 counter", 1, rv);
    704         if (BCM_FAILURE(rv)) {
    705             return rv;
    706         }
    707         _FLOWCNT_ALLOC(unit, fc_pool->flow_packet_counter,
    708                        uint32,
    709                        sizeof(uint32) * num_ctr,
    710                        "Flow packet counter", 1, rv);
    711         if (BCM_FAILURE(rv)) {
    712             return rv;
    713         }
    714         _FLOWCNT_ALLOC(unit, fc_pool->flow_base_index_reference_count,
    715                        uint16,
    716                        sizeof(uint16) * num_ctr,
    717                        "Flow BaseIndexAllocation", 0, rv);
    718         if (BCM_FAILURE(rv)) {
    719             return rv;
    720         }
    721         _FLOWCNT_ALLOC(unit, fc_pool->associate_profile_group,
    722                        uint16,
    723                        sizeof(uint16) * num_ctr,
    724                        "Flow associate_profile_group", 0, rv);
    725         if (BCM_FAILURE(rv)) {
    726             return rv;
    727         }
    728         _FLOWCNT_ALLOC(unit, fc_pool->object,
    729                        bcm_stat_object_t,
    730                        sizeof(bcm_stat_object_t) * num_ctr,
    731                        "Flow stat object", 0, rv);
    732         if (BCM_FAILURE(rv)) {
    733             return rv;
    734         }
    735         _FLOWCNT_ALLOC(unit, fc_pool->flow_stat_type,
    736                        _bcm_flowcnt_stat_type_t, 
    737                        sizeof(_bcm_flowcnt_stat_type_t) * num_ctr,
    738                        "Flow stat type", 0, rv);
    739         if (BCM_FAILURE(rv)) {
    740             return rv;
    741         }
    742         if (shr_aidxres_list_create(
    743              &fc_pool->flowcnt_aidxres_list_handle,
    744              0, num_ctr-1,
    745              0, num_ctr-1,
    746              fc->counter_block, 
    747              "flow-counter") != BCM_E_NONE) {
    748             LOG_ERROR(BSL_LS_BCM_FLEXCTR,
    749                     (BSL_META_U(unit,
    750                                 "Unrecoverable error. "
    751                                 "Couldn't Create AllignedList:"
    752                                 "FlowCounter\n")));
    753             return BCM_E_INTERNAL;
    754         }
    755         /* reserve first counter entry for warmboot recovery */
    756         shr_aidxres_list_reserve_block(
    757             fc_pool->flowcnt_aidxres_list_handle,
    758             pool_table->reserve_base,
    759             pool_table->reserve_count);
    760     }
    761 
    762     return BCM_E_NONE;
    763 }
    764 
    765 /*
    766  * Function:
    767  *      _bcm_esw_flowcnt_counter_collect
    768  * Description:
    769  *      Flex Counter accumulation routine called periodically
    770  *      to sync s/w copy with h/w copy.
    771  * Parameters:
    772  *      unit                  - (IN) unit number
    773  *      mem                   - (IN) Ingress or Egress flow counter memory
    774  *                                   if -1 Both Ingress and Egress memories
    775  *                                   else Ingress or Egress pool.
    776  *      counter_idx           - (IN) counter index.
    777  *                                   if -1 accumulate for all counters
    778  *                                   else retrieve a specific counter.
    779  * Return Value:
    780  *      None
    781  * Notes:
    782  *       This routine accumulates all the flow counters and
    783  *       update the software copy of the flow counters.
    784  *       Counter thread invokes periodically this routine.
    785  *       If counter index is not -1 then only a specific counter
    786  *       value is read from harware and synced to the software copy.
    787  *       used by all the counter_sync_get API's
    788  */
    789 STATIC void
    790 _bcm_esw_flowcnt_counter_collect(int unit,
    791                                  soc_mem_t mem,
    792                                  uint32 counter_idx)
    793 {
    794 
    795     uint32 packet_count=0, count_mode;
    796     uint64 byte_count;
    797     uint32 mem_index_min;
    798     uint32 mem_index_max;
    799     uint32 zero=0;
    800     uint32 one=1;
    801     uint64 packet64_count;
    802     uint64 prev_masked_byte_count, prev_masked_packet64_count;
    803     uint64 max_byte_size, max_byte_mask, max_packet64_size, max_packet64_mask;
    804     soc_memacc_t memacc_pkt;
    805     soc_memacc_t memacc_byte;
    806     soc_memacc_t memacc_countmode;
    807     soc_mem_t l_mem;
    808     int i, index;
    809     _bcm_esw_flowcnt_control_t *fc = NULL;
    810     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
    811     (void)_bcm_esw_flowcnt_control_get(unit, &fc);
    812 
    813     if (fc == NULL) {
    814         return;
    815     }
    816 
    817     COMPILER_64_ZERO(byte_count);
    818     COMPILER_64_ZERO(prev_masked_byte_count);
    819     COMPILER_64_ZERO(max_byte_size);
    820     COMPILER_64_ZERO(max_byte_mask);
    821 
    822     COMPILER_64_ZERO(packet64_count);
    823     COMPILER_64_ZERO(prev_masked_packet64_count);
    824     COMPILER_64_ZERO(max_packet64_size);
    825     COMPILER_64_ZERO(max_packet64_mask);
    826 
    827     l_mem = fc->flowcnt_pool[0].mem;
    828     COMPILER_64_SET(max_byte_size, zero, one);
    829     COMPILER_64_SHL(max_byte_size,
    830                     soc_mem_field_length(unit, l_mem, BYTE_COUNTERf));
    831 
    832     COMPILER_64_SET(max_byte_mask,
    833                     COMPILER_64_HI(max_byte_size),
    834                     COMPILER_64_LO(max_byte_size));
    835     COMPILER_64_SUB_32(max_byte_mask,one);
    836 
    837     COMPILER_64_SET(max_packet64_size, zero, one);
    838     COMPILER_64_SHL(max_packet64_size,
    839                     soc_mem_field_length(unit, l_mem, PACKET_COUNTERf));
    840 
    841     COMPILER_64_SET(max_packet64_mask,
    842                     COMPILER_64_HI(max_packet64_size),
    843                     COMPILER_64_LO(max_packet64_size));
    844     COMPILER_64_SUB_32(max_packet64_mask,one);
    845 
    846     for (i = 0; i < fc->num_pools; i ++) {
    847         l_mem = fc->flowcnt_pool[i].mem;
    848         if ((mem == -1) || (l_mem == mem)){
    849             fc_pool = &fc->flowcnt_pool[i];
    850 
    851             mem_index_min = soc_mem_index_min(unit, l_mem);
    852             mem_index_max = soc_mem_index_max(unit, l_mem);
    853             /*
    854              * if counter_idx != -1, retrieve specific
    855              * counter index from the flex counter memory pool.
    856              */
    857             if (counter_idx != -1) {
    858                 if ((counter_idx < mem_index_min) ||
    859                     (counter_idx > mem_index_max)) {
    860                     return;
    861                 }
    862                 mem_index_min = mem_index_max = counter_idx;
    863             }
    864             /* read all the counters or a specific counter from memory */
    865             if (counter_idx == -1 ) {
    866                 if (soc_mem_read_range(unit, l_mem, MEM_BLOCK_ANY,
    867                                        mem_index_min, mem_index_max,
    868                                        flowcnt_temp_counter[unit])
    869                                        != BCM_E_NONE) {
    870                     return;
    871                 }
    872             } else {
    873                 if (soc_mem_read(unit, l_mem, MEM_BLOCK_ANY,
    874                                  counter_idx,
    875                                 &flowcnt_temp_counter[unit][counter_idx])
    876                                  != BCM_E_NONE) {
    877                     return;
    878                 }
    879             }
    880             if (((soc_memacc_init(unit, l_mem, PACKET_COUNTERf, &memacc_pkt))) ||
    881                 ((soc_memacc_init(unit, l_mem, BYTE_COUNTERf, &memacc_byte))) ||
    882                 ((soc_memacc_init(unit, l_mem, COUNT_BYTEf, &memacc_countmode)))) {
    883                   return;
    884             }
    885 
    886             for (index = mem_index_min; index <= mem_index_max; index++) {
    887                 count_mode = soc_memacc_field32_get(&memacc_countmode,
    888                             (uint32 *)&flowcnt_temp_counter[unit][index]);
    889 
    890                 if (count_mode) {
    891                     soc_memacc_field64_get(&memacc_byte,
    892                             (uint32 *)&flowcnt_temp_counter[unit][index],
    893                             &byte_count);
    894                 } else {
    895                     packet_count = soc_memacc_field32_get(&memacc_pkt,
    896                             (uint32 *)&flowcnt_temp_counter[unit][index]);
    897                     if (fc_pool->flow_packet_counter[index] != packet_count) {
    898                         LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    899                                     (BSL_META_U(unit,
    900                                                 "Pool:%d==>"
    901                                                  "Old Packet Count Value\t:"
    902                                                  "Index:%d %x\t"
    903                                                  "New Packet Count Value %x\n"),
    904                                      i,
    905                                      index,
    906                                      fc_pool->flow_packet_counter[index],
    907                                      packet_count));
    908                         fc_pool->flow_packet_counter[index] = packet_count;
    909                     }
    910                 }
    911 
    912                 COMPILER_64_SET(packet64_count,0, packet_count);
    913                 COMPILER_64_SET(prev_masked_packet64_count, 
    914                     COMPILER_64_HI(fc_pool->flow_packet64_counter[index]),
    915                     COMPILER_64_LO(fc_pool->flow_packet64_counter[index]));
    916                 COMPILER_64_AND(prev_masked_packet64_count,max_packet64_mask);
    917 
    918                 if (COMPILER_64_GT(prev_masked_packet64_count, packet64_count)) {
    919                     LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    920                                (BSL_META_U(unit,
    921                                            "Roll over  happend \n")));
    922                     LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    923                                (BSL_META_U(unit,
    924                                            "...Read Packet64 Count    : %x:%x\n"),
    925                                 COMPILER_64_HI(packet64_count),
    926                                 COMPILER_64_LO(packet64_count)));
    927                     COMPILER_64_ADD_64(packet64_count,max_packet64_size);
    928                     COMPILER_64_SUB_64(packet64_count,prev_masked_packet64_count);
    929                     LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    930                                 (BSL_META_U(unit,
    931                                             "...Diffed 64-Packet Count    : %x:%x\n"),
    932                                  COMPILER_64_HI(packet64_count),
    933                                  COMPILER_64_LO(packet64_count)));
    934                 } else {
    935                     COMPILER_64_SUB_64(packet64_count,prev_masked_packet64_count);
    936                 }
    937                 /* Add difference (if it is) */
    938                 if (!COMPILER_64_IS_ZERO(packet64_count)) {
    939                     LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    940                                 (BSL_META_U(unit,
    941                                             "Pool:%d==>"
    942                                             "Old 64-Packet Count Value\t"
    943                                             ":Index:%d %x:%x\t"),
    944                                  i, index,
    945                                  COMPILER_64_HI(fc_pool->
    946                                                 flow_packet64_counter[index]),
    947                                  COMPILER_64_LO(fc_pool->
    948                                                 flow_packet64_counter[index])));
    949                     COMPILER_64_ADD_64(fc_pool->flow_packet64_counter[index],
    950                                        packet64_count);
    951                     LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    952                                (BSL_META_U(unit,
    953                                            "New 64-Packet Value : %x:%x\n"),
    954                                 COMPILER_64_HI(fc_pool->
    955                                                flow_packet64_counter[index]),
    956                                 COMPILER_64_LO(fc_pool->
    957                                                flow_packet64_counter[index])));
    958                 }
    959                 COMPILER_64_SET(prev_masked_byte_count,
    960                                COMPILER_64_HI(fc_pool->flow_byte_counter
    961                                               [index]),
    962                                COMPILER_64_LO(fc_pool->flow_byte_counter
    963                                               [index]));
    964                 COMPILER_64_AND(prev_masked_byte_count,max_byte_mask);
    965                 if (COMPILER_64_GT(prev_masked_byte_count, byte_count)) {
    966                     LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    967                                (BSL_META_U(unit,
    968                                            "Roll over  happend \n")));
    969                     LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    970                                (BSL_META_U(unit,
    971                                            "...Read Byte Count    : %x:%x\n"),
    972                                 COMPILER_64_HI(byte_count),
    973                                 COMPILER_64_LO(byte_count)));
    974                     COMPILER_64_ADD_64(byte_count,max_byte_size);
    975                     COMPILER_64_SUB_64(byte_count,prev_masked_byte_count);
    976                     LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    977                                (BSL_META_U(unit,
    978                                            "...Diffed Byte Count    : %x:%x\n"),
    979                                 COMPILER_64_HI(byte_count),
    980                                 COMPILER_64_LO(byte_count)));
    981                 } else {
    982                    COMPILER_64_SUB_64(byte_count,prev_masked_byte_count);
    983                 }
    984                 /* Add difference (if it is) */
    985                 if (!COMPILER_64_IS_ZERO(byte_count)) {
    986                    LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    987                                (BSL_META_U(unit,
    988                                            "Pool:%d==>"
    989                                             "Old Byte Count Value\t"
    990                                             ":Index:%d %x:%x\t"),
    991                                 i, index,
    992                                 COMPILER_64_HI(fc_pool->
    993                                                flow_byte_counter[index]),
    994                                 COMPILER_64_LO(fc_pool->
    995                                                flow_byte_counter[index])));
    996                    COMPILER_64_ADD_64(fc_pool->flow_byte_counter[index],
    997                                       byte_count);
    998                    LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
    999                                (BSL_META_U(unit,
   1000                                            "New Byte Count Value : %x:%x\n"),
   1001                                 COMPILER_64_HI(fc_pool->
   1002                                                flow_byte_counter[index]),
   1003                                 COMPILER_64_LO(fc_pool->
   1004                                                flow_byte_counter[index])));
   1005                 }
   1006             }
   1007         }
   1008     }
   1009     return;
   1010 }
   1011 
   1012 
   1013 /*
   1014  * Function:
   1015  *      _bcm_esw_flowcnt_callback
   1016  * Description:
   1017  *      Flex Counter threads callback function. It is called periodically
   1018  *      to sync s/w copy with h/w copy.
   1019  * Parameters:
   1020  *      unit                  - (IN) unit number
   1021  * Return Value:
   1022  *      BCM_E_XXX
   1023  * Notes:
   1024  */
   1025 void _bcm_esw_flowcnt_callback(int unit)
   1026 {
   1027     _bcm_esw_flowcnt_control_t *fc = NULL;
   1028 
   1029     (void)_bcm_esw_flowcnt_control_get(unit, &fc);
   1030     if (fc == NULL) {
   1031         return;
   1032     }
   1033     _FLOWCNT_LOCK(fc);
   1034     _bcm_esw_flowcnt_counter_collect(unit, -1, -1);
   1035     _FLOWCNT_UNLOCK(fc);
   1036 
   1037     return;
   1038 }
   1039 
   1040 /*
   1041  * Function:
   1042  *      _bcm_esw_flowcnt_cleanup
   1043  * Description:
   1044  *      Clean and free all allocated flow counter resources
   1045  * Parameters:
   1046  *      unit                  - (IN) unit number
   1047  * Return Value:
   1048  *      BCM_E_XXX
   1049  * Notes:
   1050  */
   1051 int 
   1052 _bcm_esw_flowcnt_cleanup(int unit)
   1053 {
   1054     _bcm_esw_flowcnt_control_t  *fc = NULL;
   1055     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   1056     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   1057     int i;
   1058 
   1059     LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   1060               (BSL_META_U(unit,
   1061                           "_bcm_esw_flowcnt_cleanup \n")));
   1062     if (flowcnt_control[unit] != NULL) {
   1063         fc = flowcnt_control[unit];
   1064         if (valid_stat_group_mode_list[unit] != NULL) {
   1065             valid_stat_group_mode_list[unit] = NULL;
   1066         }
   1067         if (valid_stat_object_list[unit] != NULL) {
   1068             valid_stat_object_list[unit] = NULL;
   1069         }
   1070         if (flowcnt_profile_table[unit] != NULL) {
   1071             flowcnt_profile_table[unit] = NULL;
   1072         }
   1073         if (flowcnt_pool_table[unit] != NULL) {
   1074             flowcnt_pool_table[unit] = NULL;
   1075         }
   1076         if (flowcnt_temp_counter[unit] != NULL) {
   1077             _FLOWCNT_FREE(unit, flowcnt_temp_counter[unit], 1);
   1078             flowcnt_temp_counter[unit] = NULL;
   1079         }
   1080         if (local_scache_ptr[unit] != NULL) {
   1081             _FLOWCNT_FREE(unit, local_scache_ptr[unit], 0);
   1082             local_scache_ptr[unit] = NULL;
   1083         }
   1084         if (fc->default_attr_mode_id != NULL) {
   1085             _FLOWCNT_FREE(unit, fc->default_attr_mode_id, 0);
   1086         }
   1087 
   1088         if(fc->flowcnt_profile != NULL) {
   1089             for (i = 0; i < fc->num_profiles; i++) {
   1090                 fc_profile = &fc->flowcnt_profile[i];
   1091                 if (fc_profile->flowcnt_group != NULL) {
   1092                     _FLOWCNT_FREE(unit, fc_profile->flowcnt_group, 0);
   1093                     fc_profile->flowcnt_group = NULL;
   1094                 }
   1095                 if (fc_profile->profile_mem.tables != NULL) {
   1096                     soc_profile_mem_destroy(unit, &fc_profile->profile_mem);
   1097                 }
   1098                 sal_memset(fc_profile, 0, sizeof(_bcm_esw_flowcnt_profile_t));
   1099             }
   1100             _FLOWCNT_FREE(unit, fc->flowcnt_profile, 0);
   1101             fc->flowcnt_profile = NULL;
   1102         }
   1103 
   1104         if(fc->flowcnt_pool != NULL) {
   1105             for (i = 0; i < fc->num_pools; i++) {
   1106                 fc_pool = &fc->flowcnt_pool[i];
   1107                 if (fc_pool->flow_byte_counter != NULL) {
   1108                     _FLOWCNT_FREE(unit, fc_pool->flow_byte_counter, 1);
   1109                     fc_pool->flow_byte_counter = NULL;
   1110                 }
   1111                 if (fc_pool->flow_packet64_counter != NULL) {
   1112                     _FLOWCNT_FREE(unit, fc_pool->flow_packet64_counter, 1);
   1113                     fc_pool->flow_packet64_counter = NULL;
   1114                 }
   1115                 if (fc_pool->flow_packet_counter != NULL) {
   1116                     _FLOWCNT_FREE(unit, fc_pool->flow_packet_counter, 1);
   1117                     fc_pool->flow_packet_counter = NULL;
   1118                 }
   1119                 if (fc_pool->flow_base_index_reference_count != NULL) {
   1120                     _FLOWCNT_FREE(unit,
   1121                                   fc_pool->flow_base_index_reference_count,
   1122                                   0);
   1123                     fc_pool->flow_base_index_reference_count = NULL;
   1124                 }
   1125                 if (fc_pool->associate_profile_group != NULL) {
   1126                     _FLOWCNT_FREE(unit,
   1127                                   fc_pool->associate_profile_group,
   1128                                   0);
   1129                     fc_pool->associate_profile_group = NULL;
   1130                 }
   1131                 if (fc_pool->object != NULL) {
   1132                     _FLOWCNT_FREE(unit,
   1133                                   fc_pool->object,
   1134                                   0);
   1135                     fc_pool->object = NULL;
   1136                 }
   1137                 if (fc_pool->flow_stat_type != NULL) {
   1138                     _FLOWCNT_FREE(unit, fc_pool->flow_stat_type, 0);
   1139                     fc_pool->flow_stat_type = NULL;
   1140                 }
   1141                 if (fc_pool->flowcnt_aidxres_list_handle != 0) {
   1142                     shr_aidxres_list_destroy(fc_pool->flowcnt_aidxres_list_handle);
   1143                     fc_pool->flowcnt_aidxres_list_handle = 0;
   1144                 }
   1145                 sal_memset(fc_pool, 0, sizeof(_bcm_esw_flowcnt_pool_t));
   1146             }
   1147             _FLOWCNT_FREE(unit, fc->flowcnt_pool, 0);
   1148             fc->flowcnt_pool = NULL;
   1149         }
   1150         soc_counter_extra_unregister(unit, _bcm_esw_flowcnt_callback);
   1151         if (fc->flowcnt_mutex != NULL) {
   1152             sal_mutex_destroy(fc->flowcnt_mutex);
   1153             fc->flowcnt_mutex = NULL;
   1154         }
   1155         _FLOWCNT_FREE(unit, flowcnt_control[unit], 0);
   1156         flowcnt_control[unit] = NULL;
   1157     }
   1158 
   1159     return BCM_E_NONE;
   1160 }
   1161 
   1162 void
   1163 _bcm_esw_flowcnt_counter_id_set(
   1164      bcm_stat_group_mode_t group,
   1165      bcm_stat_object_t     object,
   1166      uint32                profile_group,
   1167      uint32                pool_idx,
   1168      uint32                base_idx,
   1169      uint32                *stat_counter_id)
   1170 {
   1171      *stat_counter_id = ((profile_group & _BCM_FLOWCNT_MODE_MASK)   <<
   1172                                  _BCM_FLOWCNT_MODE_START_BIT)       |
   1173                         ((group & _BCM_FLOWCNT_GROUP_MASK)          <<
   1174                                  _BCM_FLOWCNT_GROUP_START_BIT)      |
   1175                         ((pool_idx & _BCM_FLOWCNT_POOL_MASK)        <<
   1176                                  _BCM_FLOWCNT_POOL_START_BIT)       |
   1177                         ((object & _BCM_FLOWCNT_OBJECT_MASK)        <<
   1178                                  _BCM_FLOWCNT_OBJECT_START_BIT)     |
   1179                          (base_idx & _BCM_FLOWCNT_BASE_IDX_MASK);
   1180 }
   1181 void 
   1182 _bcm_esw_flowcnt_counter_id_get(
   1183      uint32                stat_counter_id,
   1184      bcm_stat_group_mode_t *group,
   1185      bcm_stat_object_t     *object,
   1186      uint32                *profile_group,
   1187      uint32                *pool_idx,
   1188      uint32                *base_idx)
   1189 {
   1190      *profile_group= (uint32 ) ((stat_counter_id >> 
   1191                                               _BCM_FLOWCNT_MODE_START_BIT) &
   1192                                              (_BCM_FLOWCNT_MODE_MASK));
   1193      *group       = (bcm_stat_group_mode_t) ((stat_counter_id >> 
   1194                                               _BCM_FLOWCNT_GROUP_START_BIT) &
   1195                                              (_BCM_FLOWCNT_GROUP_MASK));
   1196      *pool_idx = ((stat_counter_id >> _BCM_FLOWCNT_POOL_START_BIT) &
   1197                                        (_BCM_FLOWCNT_POOL_MASK));
   1198      *object = (bcm_stat_object_t) ((stat_counter_id >>
   1199                                       _BCM_FLOWCNT_OBJECT_START_BIT) &
   1200                                       (_BCM_FLOWCNT_OBJECT_MASK));
   1201      *base_idx    = (stat_counter_id & _BCM_FLOWCNT_BASE_IDX_MASK);
   1202 }
   1203 
   1204 /* **********************************************************/
   1205 /*              COMPOSITION OF CUSTOM MODE ID               */
   1206 /* **********************************************************/
   1207 /*              profile_id  8 bit                           */
   1208 /*              profile_group_id 8 bits                     */
   1209 /*              -----       00     -   00                   */
   1210 /*              Reserved profile_id profile_group_id        */
   1211 /* **********************************************************/
   1212 #define _BCM_FLOWCNT_PROFILE_ID_START_BIT       8
   1213 #define _BCM_FLOWCNT_PROFILE_ID_END_BIT        15
   1214 #define _BCM_FLOWCNT_PROFILE_GROUP_ID_START_BIT 0
   1215 #define _BCM_FLOWCNT_PROFILE_GROUP_ID_END_BIT   7
   1216 
   1217 #define _BCM_FLOWCNT_PROFILE_ID_MASK \
   1218     ((1<<(_BCM_FLOWCNT_PROFILE_ID_END_BIT - _BCM_FLOWCNT_PROFILE_ID_START_BIT+1))-1)
   1219 #define _BCM_FLOWCNT_PROFILE_GROUP_ID_MASK \
   1220     ((1<<(_BCM_FLOWCNT_PROFILE_GROUP_ID_END_BIT - _BCM_FLOWCNT_PROFILE_GROUP_ID_START_BIT+1))-1)
   1221 
   1222 static
   1223 void _bcm_esw_flowcnt_custom_mode_id_get(
   1224         uint32 mode_id, int *profile_index, int *group_index)
   1225 {
   1226     *profile_index = ((mode_id >> _BCM_FLOWCNT_PROFILE_ID_START_BIT) &
   1227                         (_BCM_FLOWCNT_PROFILE_ID_MASK));
   1228     *group_index = mode_id & _BCM_FLOWCNT_PROFILE_GROUP_ID_MASK;
   1229 }
   1230 
   1231 static
   1232 void _bcm_esw_flowcnt_custom_mode_id_set(
   1233         int profile_index, int group_index, uint32 *mode_id)
   1234 {
   1235     *mode_id = ((profile_index & _BCM_FLOWCNT_PROFILE_ID_MASK) <<
   1236                                  _BCM_FLOWCNT_PROFILE_ID_START_BIT) |
   1237                 (group_index & _BCM_FLOWCNT_PROFILE_GROUP_ID_MASK);
   1238 }
   1239 
   1240 /* 
   1241  * internal fuction : _bcm_esw_flowcnt_selectors_cmp
   1242  * Description: : compare the profile table contents
   1243  * 
   1244  * Parameters:
   1245  *      unit                - (IN) unit number
   1246  *      table               - (IN) profile table
   1247  *      num_entries         - (IN) num entries to be compared
   1248  *      num_src_selectors   - (IN) num of selectores
   1249  *      num_dst_selectors   - (IN) num of selectores
   1250  *      src_attr_selectors  - (IN) src attr selectors
   1251  *      dst_attr_selectors  - (IN) target sttr selectors
   1252  *
   1253  * Return Value:
   1254  *      0: identical content
   1255  */
   1256 static
   1257 int
   1258 _bcm_esw_flowcnt_selectors_cmp(int unit, soc_mem_t table, 
   1259     int num_entries,
   1260     int num_src_selectors,
   1261     int num_dst_selectors,
   1262     _bcm_flowcnt_group_mode_attr_selector_t *src_attr_selectors,
   1263     bcm_stat_group_mode_attr_selector_t *dst_attr_selectors)
   1264 {
   1265     uint32 entry_data_size = 0;
   1266     uint32 *s_entries=NULL;
   1267     uint32 *d_entries=NULL;
   1268     int s_entry_index, d_entry_index;
   1269     int i, rv;
   1270 
   1271     entry_data_size = sizeof(uint32);
   1272     _FLOWCNT_ALLOC(unit, s_entries, uint32, entry_data_size * num_entries,
   1273                "temp selectors table src", 0, rv);
   1274     if (BCM_FAILURE(rv)) {
   1275         return BCM_E_RESOURCE;
   1276     }
   1277 
   1278     _FLOWCNT_ALLOC(unit, d_entries, uint32, entry_data_size * num_entries,
   1279                "temp selectors table dst", 0, rv); 
   1280     if (BCM_FAILURE(rv)) {
   1281         _FLOWCNT_FREE(unit, s_entries, 0);
   1282         return BCM_E_RESOURCE;
   1283     }
   1284 
   1285     /* Fill the entries according to attr_selectors*/
   1286     for (i = 0; i < num_src_selectors; i++){
   1287         s_entry_index = src_attr_selectors[i].attr_value;
   1288         if (SOC_MEM_FIELD_VALID(unit, table, OFFSET_VALIDf)){
   1289             soc_mem_field32_set(unit, table, &s_entries[s_entry_index],
   1290                 OFFSET_VALIDf, 1);
   1291         }
   1292         if (SOC_MEM_FIELD_VALID(unit, table, OFFSETf)){
   1293             soc_mem_field32_set(unit, table, &s_entries[s_entry_index],
   1294                 OFFSETf, src_attr_selectors[i].counter_offset);
   1295         }
   1296     }
   1297     /* Fill the entries according to attr_selectors*/
   1298     for (i = 0; i < num_dst_selectors; i++){
   1299         d_entry_index = dst_attr_selectors[i].attr_value;
   1300         if (SOC_MEM_FIELD_VALID(unit, table, OFFSET_VALIDf)){
   1301             soc_mem_field32_set(unit, table, &d_entries[d_entry_index],
   1302                 OFFSET_VALIDf, 1);
   1303         }
   1304         if (SOC_MEM_FIELD_VALID(unit, table, OFFSETf)){
   1305             soc_mem_field32_set(unit, table, &d_entries[d_entry_index],
   1306                 OFFSETf, dst_attr_selectors[i].counter_offset);
   1307         }
   1308     }
   1309 
   1310     rv = sal_memcmp(s_entries, d_entries, num_entries*entry_data_size);
   1311     _FLOWCNT_FREE(unit, s_entries, 0);
   1312     _FLOWCNT_FREE(unit, d_entries, 0);
   1313 
   1314     return rv;
   1315 }
   1316 
   1317 /*
   1318  * Function:
   1319  *      _bcm_esw_flowcnt_profile_group_create
   1320  * Description:
   1321  *      Create profile group
   1322  * Parameters:
   1323  *      unit                - (IN) unit number
   1324  *      direction           - (IN) ingress/egress profile table
   1325  *      group_mode          - (IN) group mode from API
   1326  *      total_counters      - (IN) numbers of counter
   1327  *      num_selectors       - (IN) numbers of selectors
   1328  *      attr_selectors      - (IN) attribute selectors 
   1329  *      profile_index       - (OUT) profile_index from API
   1330  *      group_index         - (OUT) group_index
   1331  *
   1332  * Return Value:
   1333  *      BCM_E_XXX
   1334  * Notes:
   1335  */
   1336 int
   1337 _bcm_esw_flowcnt_profile_group_create(
   1338                 int unit,
   1339                 bcm_stat_flex_direction_t direction,
   1340                 bcm_stat_group_mode_t group_mode,
   1341                 int total_counters,
   1342                 int num_selectors,
   1343                 bcm_stat_group_mode_attr_selector_t *attr_selectors,
   1344                 int *profile_index,
   1345                 int *group_index)
   1346 
   1347 { 
   1348     _bcm_esw_flowcnt_control_t *fc = NULL;
   1349     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   1350     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   1351     bcm_stat_group_mode_attr_t  attr;
   1352     int i, entry_size=0, entry_index, profile_group;
   1353     int rv = BCM_E_NONE;
   1354     soc_profile_mem_t   profile;
   1355     soc_mem_t target_table = -1;
   1356     int num_group, num_entry;
   1357     uint32 *entries = NULL;
   1358 
   1359 
   1360     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   1361 
   1362     if ((num_selectors !=0) && (attr_selectors == NULL)) {
   1363         return BCM_E_PARAM;
   1364     }
   1365     attr = attr_selectors->attr;
   1366 
   1367     _FLOWCNT_LOCK(fc);
   1368     for (i = 0; i < fc->num_profiles; i++) {
   1369         fc_profile = &fc->flowcnt_profile[i];
   1370         if ((fc_profile->direction == direction) && 
   1371             (fc_profile->attr == attr)){
   1372             target_table = fc_profile->profile_table;
   1373             *profile_index = i;
   1374             profile = fc_profile->profile_mem;
   1375             num_group = fc_profile->num_groups;
   1376             break;
   1377         }
   1378     }
   1379     if (target_table == -1) {
   1380         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   1381                   (BSL_META_U(unit,
   1382                               "Couldn't find the matched profile.\n")));
   1383         _FLOWCNT_UNLOCK(fc);
   1384         return BCM_E_INTERNAL;
   1385     }
   1386     if (total_counters > (1 << fc->counter_block)) {
   1387         _FLOWCNT_UNLOCK(fc);
   1388         return BCM_E_PARAM;
   1389     }
   1390     num_entry = soc_mem_index_count(unit, target_table) / num_group;
   1391     if (num_selectors > num_entry) {
   1392         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   1393                 (BSL_META_U(unit,
   1394                             "Couldn't support %d selectors. "
   1395                             "Maximum %d selectors\n"),
   1396                             num_selectors, num_entry));
   1397         _FLOWCNT_UNLOCK(fc);
   1398         return BCM_E_PARAM;
   1399     }
   1400     /* Allocate the entries */
   1401     entry_size = sizeof(uint32);
   1402     _FLOWCNT_ALLOC(unit, entries, uint32, num_entry * entry_size,
   1403                    "flowcnt offset table entries", 0, rv);
   1404 
   1405     if (BCM_FAILURE(rv)){
   1406         _FLOWCNT_UNLOCK(fc);
   1407         return rv;
   1408     }
   1409     _FLOWCNT_UNLOCK(fc);
   1410 
   1411     /* Fill the entries according to attr_selectors*/
   1412     for (i = 0; i < num_selectors; i++){
   1413         entry_index = attr_selectors[i].attr_value;
   1414         if (entry_index > (num_entry - 1)) {
   1415             _FLOWCNT_FREE(unit, entries, 0);
   1416             return BCM_E_PARAM;
   1417         }
   1418         if (attr_selectors[i].counter_offset > ((1 << fc->counter_block)-1)) {
   1419             _FLOWCNT_FREE(unit, entries, 0);
   1420             return BCM_E_PARAM;
   1421         }
   1422         if (SOC_MEM_FIELD_VALID(unit, target_table, OFFSET_VALIDf)){
   1423             soc_mem_field32_set(unit, target_table, &entries[entry_index],
   1424                 OFFSET_VALIDf, 1);
   1425         }
   1426         if (SOC_MEM_FIELD_VALID(unit, target_table, OFFSETf)){
   1427             soc_mem_field32_set(unit, target_table, &entries[entry_index],
   1428                 OFFSETf, attr_selectors[i].counter_offset);
   1429         }
   1430     }
   1431     soc_mem_lock(unit, target_table);
   1432     rv = soc_profile_mem_add(unit, &profile,
   1433                              (void *)&entries, num_entry, (uint32 *)group_index);
   1434     if (BCM_FAILURE(rv)) {
   1435         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   1436                   (BSL_META_U(unit,
   1437                               "Error: Adding profile entry"
   1438                                " - %s.\n"), bcm_errmsg(rv)));
   1439         _FLOWCNT_FREE(unit, entries, 0);
   1440         soc_mem_unlock(unit, target_table);
   1441         return (rv);
   1442     }
   1443     profile_group = *group_index / num_entry;
   1444     *group_index = profile_group;
   1445     soc_mem_unlock(unit, target_table);
   1446     _FLOWCNT_FREE(unit, entries, 0);
   1447 
   1448     /* Update the profile group reference count */
   1449     _FLOWCNT_LOCK(fc);
   1450     fc_profile = &fc->flowcnt_profile[*profile_index];
   1451     fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   1452 
   1453     if (fc_pgroup->available == 0) {
   1454         _FLOWCNT_ALLOC(unit, fc_pgroup->attr_selectors,
   1455                        _bcm_flowcnt_group_mode_attr_selector_t,
   1456                        num_selectors * 
   1457                        sizeof(_bcm_flowcnt_group_mode_attr_selector_t),
   1458                        "flowcnt pkt attr per profile group", 0, rv);
   1459 
   1460         if (BCM_FAILURE(rv)){
   1461             _FLOWCNT_FREE(unit, attr_selectors, 0);
   1462             _FLOWCNT_UNLOCK(fc);
   1463             return rv;
   1464         }
   1465         for (i = 0; i < num_selectors; i++) {
   1466             fc_pgroup->attr_selectors[i].attr =
   1467                 attr_selectors[i].attr;
   1468             fc_pgroup->attr_selectors[i].counter_offset =
   1469                 attr_selectors[i].counter_offset;
   1470             fc_pgroup->attr_selectors[i].attr_value =
   1471                 attr_selectors[i].attr_value;
   1472         }
   1473         fc_pgroup->num_selectors = num_selectors;
   1474         fc_pgroup->total_counters = total_counters;
   1475         fc_pgroup->group_mode = group_mode;
   1476         fc_pgroup->available = 1;
   1477     }
   1478     _FLOWCNT_UNLOCK(fc);
   1479 
   1480     return rv;
   1481 }
   1482 
   1483 int
   1484 _bcm_esw_flowcnt_default_attr_config(int unit,
   1485             bcm_stat_group_mode_attr_t attr,
   1486             int num_selctors, 
   1487             bcm_stat_group_mode_attr_selector_t *attr_selectors)
   1488 {
   1489     int i;
   1490     for (i = 0; i < num_selctors; i++){
   1491         attr_selectors[i].attr = attr;
   1492         attr_selectors[i].attr_value = i;
   1493         attr_selectors[i].counter_offset = 0;
   1494     }
   1495     return BCM_E_NONE;
   1496 }
   1497 
   1498 /*
   1499  * Function:
   1500  *      _bcm_esw_flowcnt_object_table_map
   1501  * Description:
   1502  *      Get the object table informantion based on the the giving object
   1503  * Parameters:
   1504  *      unit                - (IN) unit number
   1505  *      object              - (IN) object. 
   1506  *      profile_index       - (OUT) profile_index
   1507  *      pool_index          - (OUT) pool_index
   1508  *
   1509  * Return Value:
   1510  *      BCM_E_XXX
   1511  * Notes:
   1512  */
   1513 STATIC int
   1514 _bcm_esw_flowcnt_object_table_map(int unit,
   1515     bcm_stat_object_t object,
   1516     int *profile_index,
   1517     int *pool_index)
   1518 {
   1519     int i;
   1520     int object_index = -1;
   1521     soc_mem_t   pool_table, offset_table;
   1522     _bcm_esw_flowcnt_control_t *fc = NULL;
   1523 
   1524     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   1525 
   1526     *pool_index = -1;
   1527     *profile_index = -1;
   1528 
   1529     for (i = 0; valid_stat_object_list[unit][i].object != -1; i++) {
   1530         if (valid_stat_object_list[unit][i].object == object) {
   1531             object_index = i;
   1532             break;
   1533         }
   1534     }
   1535 
   1536     if (object_index == -1) {
   1537         return BCM_E_INTERNAL;
   1538     }
   1539     pool_table = valid_stat_object_list[unit][object_index].counter_mem;
   1540     offset_table = valid_stat_object_list[unit][object_index].offset_mem;
   1541 
   1542     for (i = 0; i < fc->num_profiles; i ++) {
   1543         if (flowcnt_profile_table[unit][i].mem == offset_table) {
   1544             *profile_index = i;
   1545             break;
   1546         }
   1547     }
   1548     if (*profile_index == -1) {
   1549         return BCM_E_INTERNAL;
   1550     }
   1551     for (i = 0; i < fc->num_pools; i ++) {
   1552         if (flowcnt_pool_table[unit][i].pool_mem == pool_table) {
   1553             *pool_index = i;
   1554             break;
   1555         }
   1556     }
   1557     if (*pool_index == -1) {
   1558         return BCM_E_INTERNAL;
   1559     }
   1560     return BCM_E_NONE;
   1561 }
   1562 
   1563 /*
   1564  * Function:
   1565  *      _bcm_esw_flowcnt_counter_destroy
   1566  * Description:
   1567  *      Destroy accounting table's statistics completely
   1568  * Parameters:
   1569  *      unit                  - (IN) unit number
   1570  *      object                - (IN) Accounting Object
   1571  *      profile_group         - (IN) profile group for Accounting Object
   1572  *      base_idx              - (IN) Base Index for Accounting Object
   1573  *      pool_number           - (IN) Pool Number for Accounting Object
   1574  *
   1575  * Return Value:
   1576  *      BCM_E_XXX
   1577  * Notes:
   1578  */
   1579 int
   1580 _bcm_esw_flowcnt_counter_destroy(
   1581             int                  unit,
   1582             bcm_stat_object_t    object,
   1583             uint32               profile_group,
   1584             uint32               base_idx,
   1585             uint32               pool_number)
   1586 {
   1587     _bcm_esw_flowcnt_control_t *fc = NULL;
   1588     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   1589     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   1590     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   1591     int pool_idx, profile_index;
   1592     int total_counters;
   1593     int rv, i;
   1594     uint32 free_count=0;
   1595     uint32 alloc_count=0;
   1596     uint32 largest_free=0, stat_counter_id=0;
   1597 
   1598     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   1599     rv = _bcm_esw_flowcnt_object_table_map(unit, object,
   1600                                            &profile_index,
   1601                                            &pool_idx);
   1602     if (BCM_FAILURE(rv)){
   1603         return rv;
   1604     }
   1605     if (pool_idx != pool_number){
   1606         return BCM_E_PARAM;
   1607     }
   1608 
   1609     _FLOWCNT_LOCK(fc);
   1610     fc_pool = &fc->flowcnt_pool[pool_idx];
   1611     fc_profile = &fc->flowcnt_profile[profile_index];
   1612     fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   1613 
   1614     if (fc_pgroup->available == 0) {
   1615         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   1616                   (BSL_META_U(unit,
   1617                               "The profile_group is not available.\n")));
   1618         _FLOWCNT_UNLOCK(fc);
   1619         return BCM_E_NOT_FOUND;
   1620     }
   1621     if (shr_aidxres_list_elem_state(fc_pool->flowcnt_aidxres_list_handle,
   1622                                     base_idx) != BCM_E_EXISTS) {
   1623         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   1624                   (BSL_META_U(unit,
   1625                               "Wrong base index %u \n"),
   1626                    base_idx));
   1627         _FLOWCNT_UNLOCK(fc);
   1628         return BCM_E_NOT_FOUND;
   1629     }
   1630 
   1631     total_counters = fc_pgroup->total_counters;
   1632     rv = shr_aidxres_list_free(fc_pool->flowcnt_aidxres_list_handle, base_idx);
   1633     if (BCM_SUCCESS(rv)){
   1634         fc_pool->pool_stat.used_entries -= total_counters;
   1635         for (i = 0; i < total_counters; i ++){
   1636             fc_pool->flow_stat_type[base_idx+i] = 0;
   1637         }
   1638         fc_pool->associate_profile_group[base_idx] = 0;
   1639         fc_pool->object[base_idx] = 0;
   1640         shr_aidxres_list_state(fc_pool->flowcnt_aidxres_list_handle,
   1641             NULL,NULL,NULL,NULL,&free_count,&alloc_count,&largest_free,
   1642             NULL);
   1643         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   1644                  (BSL_META_U(unit,
   1645                              "Current Pool status free_count:%d alloc_count:%d "
   1646                               "largest_free:%d "
   1647                               "used_entries:%d\n"),
   1648                   free_count,alloc_count,largest_free,
   1649                   fc_pool->pool_stat.used_entries));
   1650 
   1651         fc_pgroup->reference_count--;
   1652         _bcm_esw_flowcnt_counter_id_set(
   1653                 fc_pgroup->group_mode,
   1654                 object,
   1655                 profile_group,
   1656                 pool_idx,
   1657                 base_idx,
   1658                 &stat_counter_id);
   1659         if (_bcm_esw_flowcnt_stat_id_delete(
   1660                 local_scache_ptr[unit], stat_counter_id) != BCM_E_NONE) {
   1661             LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
   1662                         (BSL_META_U(unit,
   1663                                     "Could not delete entry in scache memory.\n")));
   1664         }
   1665     }
   1666     _FLOWCNT_UNLOCK(fc);
   1667 
   1668     return rv;
   1669 }
   1670 
   1671 /*
   1672  * Function:
   1673  *      _bcm_esw_flowcnt_counter_create
   1674  * Description:
   1675  *      Allocate counter based on pool_index basis
   1676  * Parameters:
   1677  *      unit                - (IN) unit number
   1678  *      object              - (IN) object.
   1679  *      total_counters      - (IN) Total Counters need to be allocated.
   1680  *      base_index          - (OUT) profile_index
   1681  *      pool_index          - (OUT) pool_index
   1682  *
   1683  * Return Value:
   1684  *      BCM_E_XXX
   1685  * Notes:
   1686  */ 
   1687 int
   1688 _bcm_esw_flowcnt_counter_create(int unit, bcm_stat_object_t object,
   1689                                 uint32 profile_group,
   1690                                 int total_counters, int *base_index,
   1691                                 int *pool_index)
   1692 {
   1693     _bcm_esw_flowcnt_control_t *fc = NULL;
   1694     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   1695     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   1696     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   1697     int rv, base_idx_l;
   1698     int pool_idx, profile_index, i;
   1699     uint32 free_count=0;
   1700     uint32 alloc_count=0;
   1701     uint32 largest_free=0;
   1702     uint32 stat_counter_id;
   1703 
   1704     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   1705     rv = _bcm_esw_flowcnt_object_table_map(unit, object,
   1706                                            &profile_index,
   1707                                            &pool_idx);
   1708     if (BCM_FAILURE(rv)){
   1709         return rv;
   1710     }
   1711     _FLOWCNT_LOCK(fc);
   1712     fc_profile = &fc->flowcnt_profile[profile_index];
   1713     fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   1714     fc_pool = &fc->flowcnt_pool[pool_idx];
   1715 
   1716     if (fc_pgroup->available == 0) {
   1717         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   1718                   (BSL_META_U(unit,
   1719                               "The profile_group is not available.\n")));
   1720         _FLOWCNT_UNLOCK(fc);
   1721         return BCM_E_PARAM;
   1722     }
   1723     rv = shr_aidxres_list_alloc_block(fc_pool->flowcnt_aidxres_list_handle,
   1724          total_counters, (uint32 *)&base_idx_l);
   1725 
   1726     if (BCM_SUCCESS(rv)){
   1727        LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   1728                  (BSL_META_U(unit,
   1729                              "Allocated  counter for Table:%s "
   1730                               "pool_idx:%d base_idx:%d \n"),
   1731                   SOC_MEM_UFNAME(unit, fc_pool->mem),
   1732                   pool_idx, base_idx_l));
   1733 
   1734         fc_pool->pool_stat.used_entries += total_counters;
   1735         for (i = 0; i < total_counters; i ++) {
   1736             fc_pool->flow_stat_type[base_idx_l+i] = bcmFlowcntStatTypePacket;
   1737         }
   1738         fc_pool->associate_profile_group[base_idx_l] = 
   1739                     profile_group + _BCM_FLOWCNT_PGROUP_BIAS;
   1740         fc_pool->object[base_idx_l] = object;
   1741         shr_aidxres_list_state(fc_pool->flowcnt_aidxres_list_handle,
   1742             NULL,NULL,NULL,NULL,&free_count,&alloc_count,&largest_free,
   1743             NULL);
   1744         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   1745                  (BSL_META_U(unit,
   1746                              "Current Pool status free_count:%d alloc_count:%d "
   1747                               "largest_free:%d "
   1748                               "used_entries:%d\n"),
   1749                   free_count,alloc_count,largest_free,
   1750                   fc_pool->pool_stat.used_entries));
   1751         *base_index = base_idx_l;
   1752         *pool_index = pool_idx;
   1753 
   1754         fc_pgroup->reference_count++;
   1755         _bcm_esw_flowcnt_counter_id_set(
   1756                  fc_pgroup->group_mode,
   1757                  object,
   1758                  profile_group,
   1759                  *pool_index,
   1760                  *base_index,
   1761                  &stat_counter_id);
   1762         if (_bcm_esw_flowcnt_stat_id_insert(
   1763                 local_scache_ptr[unit],stat_counter_id) != BCM_E_NONE) {
   1764             LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
   1765                         (BSL_META_U(unit,
   1766                                 "Could not add entry in scache memory."
   1767                                 "Attach it\n")));
   1768         }
   1769     }
   1770     _FLOWCNT_UNLOCK(fc);
   1771 
   1772     return rv;
   1773 }
   1774 /*
   1775  * Function:
   1776  *      _bcm_esw_flowcnt_object_table_detach
   1777  * Description:
   1778  *      Detach i.e. Disable Igresss accounting table's statistics
   1779  * Parameters:
   1780  *      unit                  - (IN) unit number
   1781  *      table         - (IN) Flex Accounting Table
   1782  *      index                 - (IN) Flex Accounting Table's Index
   1783  *
   1784  * Return Value:
   1785  *      BCM_E_XXX
   1786  * Notes:
   1787  */
   1788 int _bcm_esw_flowcnt_object_table_detach(
   1789             int       unit,
   1790             soc_mem_t table,
   1791             uint32    index)
   1792 {
   1793     _bcm_esw_flowcnt_control_t *fc = NULL;
   1794     _bcm_esw_flowcnt_pool_t *fc_pool = NULL; 
   1795     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   1796     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   1797     void *entry_data = NULL;
   1798     uint32 entry_data_size = 0;
   1799     soc_mem_info_t *memp = NULL;
   1800     int i, valid = -1;
   1801     uint32 profile_ptr, base_index;
   1802     flowcnt_object_info_t *stat_object_list;
   1803     int object_index, pool_index, profile_index;
   1804     counter_table_entry_t counter_entry;
   1805     int rv;
   1806     bcm_stat_object_t object;
   1807     uint32 stat_counter_id;
   1808 
   1809     stat_object_list = valid_stat_object_list[unit];
   1810     for (i = 0; stat_object_list[i].object_mem != -1; i++) {
   1811         if (table == stat_object_list[i].object_mem) {
   1812             object = stat_object_list[i].object;
   1813             valid = 1;
   1814             break;
   1815         }
   1816     }
   1817     if (valid == -1) {
   1818         return BCM_E_PARAM;
   1819     }
   1820 
   1821     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   1822 
   1823     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_accounting_object_info_get(
   1824                             unit, table, index,
   1825                             &profile_ptr, &base_index, &object_index));
   1826 
   1827     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_object_table_map(
   1828                             unit, stat_object_list[object_index].object,
   1829                             &profile_index, &pool_index));
   1830 
   1831     _FLOWCNT_LOCK(fc);
   1832     fc_pool = &fc->flowcnt_pool[pool_index];
   1833     fc_profile = &fc->flowcnt_profile[profile_index];
   1834     fc_pgroup = &fc_profile->flowcnt_group[profile_ptr];
   1835     fc_pool->flow_base_index_reference_count[base_index]--;
   1836     fc_pool->pool_stat.attached_entries -= fc_pgroup->total_counters;
   1837     /* Clear Counter Values */
   1838     if (fc_pool->flow_base_index_reference_count[base_index] == 0) {
   1839         sal_memset(&counter_entry, 0, sizeof(counter_table_entry_t));
   1840         for (i = 0; i < fc_pgroup->total_counters; i ++) {
   1841             COMPILER_64_SET(fc_pool->flow_packet64_counter[base_index + i],
   1842                             0, 0);
   1843             COMPILER_64_SET(fc_pool->flow_byte_counter[base_index + i],
   1844                             0, 0);
   1845             fc_pool->flow_packet_counter[base_index + i] = 0;
   1846             soc_mem_write(unit, fc_pool->mem, MEM_BLOCK_ALL,
   1847                           base_index + i,
   1848                           &counter_entry);
   1849         }
   1850     }
   1851     
   1852     memp = &SOC_MEM_INFO(unit, table);
   1853     entry_data_size = WORDS2BYTES(BYTES2WORDS(memp->bytes));
   1854     _FLOWCNT_ALLOC(unit, entry_data, void, entry_data_size,
   1855                "object table entry", 0, rv);
   1856 
   1857     rv = soc_mem_read(unit, table, MEM_BLOCK_ANY,
   1858                       index, entry_data);
   1859     if (BCM_FAILURE(rv)) {
   1860         _FLOWCNT_FREE(unit, entry_data, 0);
   1861         _FLOWCNT_UNLOCK(fc);
   1862         return rv;
   1863     }
   1864 
   1865     rv = _bcm_esw_flowcnt_object_table_fields_values_set(
   1866             unit, index, table, entry_data, 0, 0);
   1867 
   1868     if (BCM_FAILURE(rv)) {
   1869         _FLOWCNT_FREE(unit, entry_data, 0);
   1870         _FLOWCNT_UNLOCK(fc);
   1871         return rv;
   1872     }
   1873 
   1874     if (soc_mem_write(unit, table, MEM_BLOCK_ALL,
   1875                   index,
   1876                   entry_data) != SOC_E_NONE) {
   1877         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   1878                   (BSL_META_U(unit,
   1879                               "Table:%s:Index:%d: encounter some problem \n"),
   1880                    SOC_MEM_UFNAME(unit, table), index));
   1881         _FLOWCNT_FREE(unit, entry_data, 0);
   1882         _FLOWCNT_UNLOCK(fc);
   1883         return    BCM_E_INTERNAL;
   1884     }
   1885     LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   1886               (BSL_META_U(unit,
   1887                           "Deallocated Table:%s:Index:%d:mode:%d"
   1888                            "reference_count %d \n"),
   1889                SOC_MEM_UFNAME(unit, table),index,profile_ptr,
   1890                fc_pool->flow_base_index_reference_count[base_index]));
   1891 
   1892     _FLOWCNT_FREE(unit, entry_data, 0);
   1893 
   1894     _bcm_esw_flowcnt_counter_id_set(
   1895                  fc_pgroup->group_mode,
   1896                  object,
   1897                  profile_ptr,
   1898                  pool_index,
   1899                  base_index,
   1900                  &stat_counter_id);
   1901     if (fc_pool->flow_base_index_reference_count[base_index] == 0) {
   1902         if (_bcm_esw_flowcnt_stat_id_insert(
   1903                 local_scache_ptr[unit],stat_counter_id) != BCM_E_NONE) {
   1904                 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
   1905                             (BSL_META_U(unit,
   1906                                         "Could not add entry in scache memory.\n")));
   1907         }
   1908     }
   1909     _FLOWCNT_UNLOCK(fc);
   1910     return BCM_E_NONE;
   1911 }
   1912 
   1913 /*
   1914  * Function:
   1915  *      _bcm_esw_flowcnt_object_table_attach
   1916  * Description:
   1917  *      Atach i.e. Enable Ingresss accounting table's statistics
   1918  * Parameters:
   1919  *      unit                  - (IN) unit number
   1920  *      table         - (IN) Flex Accounting Table
   1921  *      index                 - (IN) Flex Accounting Table's Index
   1922  *      mode                  - (IN) Flex offset mode for Accounting Object
   1923  *      base_idx              - (IN) Flex Base Index for Accounting Object
   1924  *      pool_idx              - (IN) Flex Pool Index for Accounting Object
   1925  *      ingress_entry_data1   - (IN) Entry Data(Null or Valid)
   1926  *                                   Null, table will be modified
   1927  *                                   NON-Null, table won't be modified
   1928  * Return Value:
   1929  *      BCM_E_XXX
   1930  */
   1931 int _bcm_esw_flowcnt_object_table_attach(
   1932             int                 unit,
   1933             bcm_stat_object_t   object,
   1934             soc_mem_t           table,
   1935             uint32              index,
   1936             int                 profile_group,
   1937             uint32              base_idx,
   1938             uint32              pool_idx,
   1939             void                *entry_data1)
   1940 {
   1941     _bcm_esw_flowcnt_control_t *fc = NULL;
   1942     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   1943     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   1944     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   1945     int rv;
   1946     void    *entry_data_temp = NULL;
   1947     void    *entry_data = NULL;
   1948     uint32  entry_data_size = 0;
   1949     soc_mem_info_t *memp = NULL;
   1950     uint32 profile_ptr, base_index;
   1951     int object_table_index, pool_idx_l, profile_index;
   1952     uint32 stat_counter_id;
   1953 
   1954     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   1955 
   1956     rv = _bcm_esw_flowcnt_object_table_map(unit, object,
   1957                                            &profile_index, &pool_idx_l);
   1958     if (BCM_FAILURE(rv)) {
   1959         return rv;
   1960     }
   1961     if (pool_idx_l != pool_idx) {
   1962         return BCM_E_INTERNAL;
   1963     }
   1964 
   1965     _FLOWCNT_LOCK(fc);
   1966     fc_pool = &fc->flowcnt_pool[pool_idx];
   1967     fc_profile = &fc->flowcnt_profile[profile_index];
   1968     fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   1969 
   1970     if (fc_pgroup->available == 0) {
   1971         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   1972                   (BSL_META_U(unit,
   1973                               "flowcnt profile group:%d:Not configured yet\n"),
   1974                    profile_group));
   1975         _FLOWCNT_UNLOCK(fc);
   1976         return BCM_E_NOT_FOUND;
   1977     }
   1978     if (shr_aidxres_list_elem_state(fc_pool->flowcnt_aidxres_list_handle,
   1979                                     base_idx) != BCM_E_EXISTS) {
   1980         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   1981                   (BSL_META_U(unit,
   1982                               "Wrong base index %u \n"),
   1983                    base_idx));
   1984         _FLOWCNT_UNLOCK(fc);
   1985         return BCM_E_NOT_FOUND;
   1986     }
   1987     _FLOWCNT_UNLOCK(fc);
   1988 
   1989     memp = &SOC_MEM_INFO(unit, table);
   1990     entry_data_size = WORDS2BYTES(BYTES2WORDS(memp->bytes));
   1991 
   1992     if (entry_data1  == NULL ) {
   1993         _FLOWCNT_ALLOC(unit, entry_data, void, entry_data_size,
   1994                    "object table entry", 0, rv);
   1995         if (BCM_FAILURE(rv)){
   1996             return rv;
   1997         }
   1998         if (soc_mem_read(unit, table, MEM_BLOCK_ANY,
   1999                          index,
   2000                          entry_data) != SOC_E_NONE) {
   2001             LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   2002                       (BSL_META_U(unit,
   2003                                   "Read failure for Table %s with index %d \n"),
   2004                        SOC_MEM_UFNAME(unit, table),index));
   2005             _FLOWCNT_FREE(unit, entry_data, 0);
   2006             return    BCM_E_INTERNAL;
   2007         }
   2008         entry_data_temp = entry_data;
   2009     } else {
   2010         entry_data_temp = entry_data1;
   2011     }
   2012 
   2013     if (soc_mem_field_valid(unit, table, VALIDf)) {
   2014         if (soc_mem_field32_get(unit, table, entry_data_temp,
   2015             VALIDf) == 0) {
   2016             LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   2017                       (BSL_META_U(unit,
   2018                                   "Table %s  with index %d is Not valid \n"),
   2019                        SOC_MEM_UFNAME(unit, table),index));
   2020             if (entry_data1 == NULL) {
   2021                 _FLOWCNT_FREE(unit, entry_data, 0);
   2022             }
   2023             return BCM_E_PARAM;
   2024         }
   2025     }
   2026     rv = _bcm_esw_flowcnt_object_table_fields_values_get(
   2027             unit, index, table, entry_data_temp, 
   2028             &profile_ptr, &base_index);
   2029     if (BCM_FAILURE(rv)) {
   2030         if (entry_data1 == NULL) {
   2031             _FLOWCNT_FREE(unit, entry_data, 0);
   2032         }
   2033         return rv;
   2034     }
   2035     if (base_index != 0) {
   2036         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   2037                   (BSL_META_U(unit,
   2038                               "Table:%s Has already allocated with index:%d"
   2039                                "base %d mode %d."
   2040                                "First dealloc it \n"), 
   2041                    SOC_MEM_UFNAME(unit, table),
   2042                    index,base_index,profile_ptr));
   2043         if (entry_data1 == NULL) {
   2044             _FLOWCNT_FREE(unit, entry_data, 0);
   2045         }
   2046         return BCM_E_EXISTS;/*Either NotConfigured or deallocated before */
   2047     }
   2048     rv = _bcm_esw_flowcnt_object_table_fields_values_set(
   2049             unit, index, table, entry_data_temp, profile_group, base_idx);
   2050     if (BCM_FAILURE(rv)) {
   2051         if (entry_data1 == NULL) {
   2052             _FLOWCNT_FREE(unit, entry_data, 0);
   2053         }
   2054         return rv;
   2055     }
   2056     if (entry_data1 == NULL) {
   2057         if (soc_mem_write(unit, table, MEM_BLOCK_ALL,
   2058                           index,
   2059                           entry_data_temp) != SOC_E_NONE) {
   2060             _FLOWCNT_FREE(unit, entry_data, 0);
   2061             return    BCM_E_INTERNAL;
   2062         }
   2063     }
   2064 
   2065     rv = _bcm_esw_flowcnt_object_table_index_get(
   2066         unit, index, table, entry_data_temp, &object_table_index);
   2067     if (BCM_FAILURE(rv)) {
   2068         if (entry_data1 == NULL) {
   2069             _FLOWCNT_FREE(unit, entry_data, 0);
   2070         }
   2071         return rv;
   2072     }
   2073 
   2074     if (entry_data1 == NULL) {
   2075         _FLOWCNT_FREE(unit, entry_data, 0);
   2076     }
   2077 
   2078     _FLOWCNT_LOCK(fc);
   2079     _bcm_esw_flowcnt_counter_id_set(
   2080                  fc_pgroup->group_mode, 
   2081                  object,
   2082                  profile_group,
   2083                  pool_idx,
   2084                  base_idx,
   2085                  &stat_counter_id);
   2086     if (fc_pool->flow_base_index_reference_count[base_idx] == 0) {
   2087         if (_bcm_esw_flowcnt_stat_id_delete(
   2088                 local_scache_ptr[unit], stat_counter_id) != BCM_E_NONE) {
   2089                 LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
   2090                             (BSL_META_U(unit,
   2091                                         "Could not delete entry in scache memory.\n")));
   2092         }
   2093     }  
   2094     fc_pool->flow_base_index_reference_count[base_idx]++;
   2095     fc_pool->pool_stat.attached_entries += fc_pgroup->total_counters;
   2096     _FLOWCNT_UNLOCK(fc);
   2097 
   2098     return rv;
   2099 }
   2100 
   2101 /*
   2102  * Function:
   2103  *      _bcm_esw_flowcnt_init
   2104  * Description:
   2105  *      Initialize and allocate all required resources
   2106  * Parameters:
   2107  *      unit                  - (IN) unit number
   2108  * Return Value:
   2109  *      BCM_E_XXX
   2110  * Notes:
   2111  */
   2112 int
   2113 _bcm_esw_flowcnt_init(int unit)
   2114 {
   2115     int rv=BCM_E_NONE;
   2116     _bcm_esw_flowcnt_control_t  *fc = NULL;
   2117 #ifdef BCM_WARM_BOOT_SUPPORT
   2118     int stable_size=0;
   2119     int stable_used_size=0;
   2120     int additional_scache_size = 0;
   2121 #endif
   2122 
   2123     /* clean up the resource */
   2124     if (flowcnt_control[unit] != NULL) {
   2125         rv = _bcm_esw_flowcnt_cleanup(unit);
   2126         if (BCM_FAILURE(rv)){
   2127             return rv;
   2128         }
   2129     }
   2130 
   2131     /* Allocate Flowcnt control memeory for this unit. */
   2132     _FLOWCNT_ALLOC(unit, fc, _bcm_esw_flowcnt_control_t,
   2133                    sizeof(_bcm_esw_flowcnt_control_t),
   2134                    "Flowcnt control", 0, rv);
   2135     if (BCM_FAILURE(rv)){
   2136         return rv;
   2137     }
   2138 
   2139     /* Set up the unit flowcnt control structure. */
   2140     flowcnt_control[unit] = fc;
   2141 
   2142     /* Create protection mutex. */
   2143     fc->flowcnt_mutex = sal_mutex_create("flowcnt_control.lock");
   2144     if (NULL == fc->flowcnt_mutex) {
   2145         _bcm_esw_flowcnt_cleanup(unit);
   2146         return (BCM_E_INTERNAL);
   2147     }
   2148     /* 
   2149      * chip specific table assignment 
   2150      * NOTE: chip specific information need to be addressed here.
   2151      */
   2152     if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   2153         rv = _bcm_hr3_flowcnt_ctrl_init(unit, fc);
   2154         if (BCM_FAILURE(rv)) {
   2155             _bcm_esw_flowcnt_cleanup(unit);
   2156             return (BCM_E_MEMORY);
   2157         }
   2158     }
   2159     /* common flowcnt ctrl init */
   2160     rv = _bcm_flowcnt_ctrl_common_init(unit, fc);
   2161     if (BCM_FAILURE(rv)) {
   2162         _bcm_esw_flowcnt_cleanup(unit);
   2163         return (BCM_E_MEMORY);
   2164     }
   2165 
   2166     rv = soc_counter_extra_register(unit, _bcm_esw_flowcnt_callback);
   2167     if (BCM_FAILURE(rv)) {
   2168         _bcm_esw_flowcnt_cleanup(unit);
   2169         return (BCM_E_MEMORY);
   2170     }
   2171 
   2172     local_scache_size = FLOWCNT_SCACHE_SIZE_1;
   2173     _FLOWCNT_ALLOC(unit, local_scache_ptr[unit], uint8, 
   2174                    local_scache_size,
   2175                    "local scahced", 0, rv);
   2176     if (BCM_FAILURE(rv)) {
   2177         _bcm_esw_flowcnt_cleanup(unit);
   2178         return (BCM_E_MEMORY);
   2179     }
   2180 
   2181     /* WARMBOOT related */
   2182 #ifdef BCM_WARM_BOOT_SUPPORT
   2183     flowcnt_scache_allocated_size[unit] = 0;
   2184     /* flowcnt will not co-exist with flex cnt, use the same partition */
   2185     SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_STAT,
   2186                           _BCM_STAT_WARM_BOOT_CHUNK_FLEX);
   2187     SOC_SCACHE_MODULE_MAX_PARTITIONS_SET(unit, BCM_MODULE_STAT, 1);
   2188     local_scache_size += FLOWCNT_SCACHE_SIZE_2_LOCAL;
   2189     local_scache_size += FLOWCNT_SCACHE_SIZE_3;
   2190     if (!SOC_WARM_BOOT(unit)) {
   2191         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   2192                   (BSL_META_U(unit,
   2193                               "ColdBoot: Modified Local Scache Size %d \n"),
   2194                    local_scache_size));
   2195         rv = soc_stable_size_get(unit, &stable_size);
   2196         if (BCM_FAILURE(rv)) {
   2197             _bcm_esw_flowcnt_cleanup(unit);
   2198             return (rv);
   2199         }
   2200         if (stable_size == 0) {
   2201             LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   2202                       (BSL_META_U(unit,
   2203                                   "STABLE size is zero.Probably NotConfigured yet\n")));
   2204             return BCM_E_NONE;
   2205         }
   2206 
   2207         /* Check if scache already allocated */
   2208         rv = soc_scache_ptr_get(unit,
   2209                                 handle,
   2210                                 (uint8 **)&flowcnt_scache_ptr[unit],
   2211                                 &flowcnt_scache_allocated_size[unit]);
   2212         if (rv == BCM_E_NOT_FOUND) {
   2213             /* We have not allocated scache, continue with allocation */
   2214             rv = soc_stable_used_get(unit, &stable_used_size);
   2215             if (BCM_FAILURE(rv)) {
   2216                 _bcm_esw_flowcnt_cleanup(unit);
   2217                 return rv;
   2218             }
   2219 
   2220             if ((stable_size - stable_used_size) < local_scache_size) {
   2221                  LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   2222                            (BSL_META_U(unit,
   2223                                        "Not enough scache memory left...\n")));
   2224                  _bcm_esw_flowcnt_cleanup(unit);
   2225                  return BCM_E_CONFIG;
   2226             }
   2227 
   2228             rv = soc_scache_alloc(unit, handle, local_scache_size);
   2229             if (!((rv == BCM_E_NONE) || (rv == BCM_E_EXISTS))) {
   2230                  LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   2231                            (BSL_META_U(unit,
   2232                                        "Seems to be some internal "
   2233                                        "problem.\n")));
   2234                  _bcm_esw_flowcnt_cleanup(unit);
   2235                  return rv;
   2236             }
   2237         } else if (rv == SOC_E_NONE) {
   2238             /* We have already allocated scache (reload case) confirmed size */
   2239             if (flowcnt_scache_allocated_size[unit] < local_scache_size) {
   2240                 /* scache is increased due to increase in attribute selectors.
   2241                  * So realloc size to accomodate wb sync.
   2242                  */
   2243                 additional_scache_size = local_scache_size -
   2244                                          flowcnt_scache_allocated_size[unit];
   2245                 rv = soc_scache_realloc(unit, handle,
   2246                                         additional_scache_size);
   2247                 if (!((rv == BCM_E_NONE) || (rv == BCM_E_EXISTS))) {
   2248                     LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   2249                               (BSL_META_U(unit,
   2250                                           "Seems to be some internal "
   2251                                           "problem.\n")));
   2252                     _bcm_esw_flowcnt_cleanup(unit);
   2253                     return rv;
   2254                 }
   2255             }
   2256         } else {
   2257              LOG_WARN(BSL_LS_BCM_FLEXCTR,
   2258                       (BSL_META_U(unit,
   2259                                   "Seems to be some internal problem.\n")));
   2260              _bcm_esw_flowcnt_cleanup(unit);
   2261              return rv;
   2262         }
   2263 
   2264         rv = soc_scache_ptr_get(unit,
   2265                                 handle,
   2266                                 (uint8 **)&flowcnt_scache_ptr[unit],
   2267                                 &flowcnt_scache_allocated_size[unit]);
   2268         if (BCM_FAILURE(rv)) {
   2269             LOG_WARN(BSL_LS_BCM_FLEXCTR,
   2270                      (BSL_META_U(unit,
   2271                                  "Error getting scache handle\n")));
   2272             _bcm_esw_flowcnt_cleanup(unit);
   2273             return rv;
   2274         }
   2275     } else {
   2276         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   2277                   (BSL_META_U(unit,
   2278                               "WARM Booting... \n")));
   2279 
   2280         rv = soc_scache_ptr_get(unit,
   2281                                 handle,
   2282                                 (uint8 **)&flowcnt_scache_ptr[unit],
   2283                                 &flowcnt_scache_allocated_size[unit]);
   2284 
   2285         /* You may get BCM_E_NOT_FOUND for level 1 warm boot */
   2286         if (rv == BCM_E_NOT_FOUND) {
   2287              LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
   2288                          (BSL_META_U(unit,
   2289                                      "Seems to be Level-1 Warm boot..."
   2290                                      "continuing..\n")));
   2291             _bcm_esw_flowcnt_warmboot_object_retrive(unit);
   2292             return BCM_E_NONE;
   2293         }
   2294         if (rv != BCM_E_NONE) {
   2295              LOG_WARN(BSL_LS_BCM_FLEXCTR,
   2296                       (BSL_META_U(unit,
   2297                                   "Seems to be some internal problem.\n")));
   2298              _bcm_esw_flowcnt_cleanup(unit);
   2299              return rv;
   2300         }
   2301     }
   2302     if (flowcnt_scache_ptr[unit] == NULL) {
   2303         _bcm_esw_flowcnt_cleanup(unit);
   2304         return BCM_E_MEMORY;
   2305     }
   2306     if (flowcnt_scache_allocated_size[unit] != local_scache_size) {
   2307         if (!SOC_WARM_BOOT(unit)) {
   2308             _bcm_esw_flowcnt_cleanup(unit);
   2309             return BCM_E_INTERNAL;
   2310         } else if (flowcnt_scache_allocated_size[unit] > local_scache_size){
   2311             LOG_WARN(BSL_LS_BCM_FLEXCTR,
   2312                      (BSL_META_U(unit,
   2313                       "Seems like the info in scache is larger\
   2314                       (maybe because of firmware downgrade)\n")));
   2315         }
   2316     }
   2317     if (SOC_WARM_BOOT(unit)) {
   2318         sal_memcpy(&local_scache_ptr[unit][0],
   2319                    &flowcnt_scache_ptr[unit][0],
   2320                    FLOWCNT_SCACHE_SIZE_1);
   2321         _bcm_esw_flowcnt_warmboot_info_recover(unit, 
   2322             flowcnt_scache_ptr[unit]);
   2323         _bcm_esw_flowcnt_warmboot_object_retrive(unit);
   2324     }
   2325 #else
   2326     LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   2327               (BSL_META_U(unit,
   2328                           "COLD Booting... \n")));
   2329 #endif
   2330 
   2331     return BCM_E_NONE;
   2332 }
   2333 /*
   2334  * Function:
   2335  *  _bcm_esw_flowcnt_profile_group_destroy
   2336  * Description:
   2337  *  Destroys profile group resources
   2338  * Parameters:
   2339  *  
   2340  *  unit                : (IN)  UNIT number      
   2341  *  profile_index       : (IN) index to profile table
   2342  *  group_index         : (IN) index to profile group
   2343  *
   2344  * Returns:
   2345  *  BCM_E_*
   2346  */
   2347 STATIC int
   2348 _bcm_esw_flowcnt_profile_group_destroy(
   2349     int unit,
   2350     int profile_index,
   2351     int group_index)
   2352 {
   2353     _bcm_esw_flowcnt_control_t *fc = NULL;
   2354     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   2355     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   2356     bcm_stat_group_mode_attr_t attr;
   2357     int d_profile_index, d_profile_group;
   2358     int rv;
   2359 
   2360     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   2361     _FLOWCNT_LOCK(fc);
   2362     if (profile_index >= fc->num_profiles) {
   2363         _FLOWCNT_UNLOCK(fc);
   2364         return BCM_E_PARAM;
   2365     }
   2366     fc_profile = &fc->flowcnt_profile[profile_index];
   2367     if (group_index >= fc_profile->num_groups) {
   2368         _FLOWCNT_UNLOCK(fc);
   2369         return BCM_E_PARAM;
   2370     }
   2371     fc_pgroup = &fc_profile->flowcnt_group[group_index];
   2372 
   2373     if (fc_pgroup->available == 0) {
   2374         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   2375                   (BSL_META_U(unit,
   2376                               "flex counter mode %d not configured yet\n"),
   2377                    group_index));
   2378         _FLOWCNT_UNLOCK(fc);
   2379         return BCM_E_NOT_FOUND;
   2380     }
   2381     if (fc_pgroup->reference_count != 0) {
   2382         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   2383                   (BSL_META_U(unit,
   2384                               "FlexCounterMode:%d:IsBeingUsed."
   2385                               "ReferenceCount:%d:\n"),
   2386                    group_index,fc_pgroup->reference_count));
   2387         _FLOWCNT_UNLOCK(fc);
   2388         return BCM_E_INTERNAL;
   2389     }
   2390     soc_mem_lock(unit, fc_profile->profile_table);
   2391     /* Reset profile(offset) table */
   2392     rv = soc_profile_mem_delete(unit, &fc_profile->profile_mem, 
   2393                                 group_index*fc_profile->num_entries);
   2394     soc_mem_unlock(unit, fc_profile->profile_table);
   2395     if (BCM_FAILURE(rv)) {
   2396         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   2397                   (BSL_META_U(unit,
   2398                               "Fail to reset profile group %d\n"),
   2399                    group_index));
   2400         _FLOWCNT_UNLOCK(fc);
   2401         return rv;
   2402     }
   2403     attr = fc_profile->attr;
   2404     d_profile_index = -1;
   2405     d_profile_group = -1;
   2406     if (fc->default_attr_mode_id[attr] != 0) {
   2407         _bcm_esw_flowcnt_custom_mode_id_get(fc->default_attr_mode_id[attr],
   2408                                             &d_profile_index, &d_profile_group);
   2409         if ((d_profile_index == profile_index) &&
   2410             (d_profile_group == group_index)) {
   2411             fc->default_attr_mode_id[attr] = 0;
   2412         }
   2413     }
   2414     fc_pgroup->available = 0;
   2415     _FLOWCNT_FREE(unit, fc_pgroup->attr_selectors, 0);
   2416     sal_memset(fc_pgroup, 0, sizeof(_bcm_esw_flowcnt_profile_group_t));
   2417     _FLOWCNT_UNLOCK(fc);
   2418     return BCM_E_NONE;
   2419 }    
   2420 /*
   2421  * Function:
   2422  *      _bcm_esw_flowcnt_group_destroy
   2423  * Description:
   2424  *      Release HW counter resources as per given counter id and makes system
   2425  *      unavailable for any further stat collection action
   2426  * Parameters:
   2427  *      unit            - (IN) unit number
   2428  *      Stat_counter_id - (IN) Stat Counter Id
   2429  * Return Value:
   2430  *      BCM_E_XXX
   2431  * Notes:
   2432  */
   2433 int _bcm_esw_flowcnt_group_destroy(
   2434             int    unit,
   2435             uint32 stat_counter_id)
   2436 {    
   2437     bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle;
   2438     bcm_stat_object_t object = bcmStatObjectIngPort;
   2439     uint32  profile_group, pool_index, base_index;
   2440     int profile_index, pool_idx;
   2441     int rv = BCM_E_NONE;
   2442 
   2443     _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode, &object,
   2444                                     &profile_group, &pool_index, &base_index);
   2445 
   2446     LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   2447               (BSL_META_U(unit,
   2448                           "Deleting : mode:%d group_mode:%d pool:%d object:%d"
   2449                           "base:%d\n stat_counter_id:%d\n"),profile_group,
   2450                           group_mode, pool_index, object, base_index,
   2451                           stat_counter_id));
   2452 
   2453     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_object_table_map(
   2454                             unit, object, &profile_index, &pool_idx));
   2455 
   2456     if (pool_idx != pool_index) {
   2457         return BCM_E_INTERNAL;
   2458     }
   2459     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_counter_destroy(
   2460                             unit, object, profile_group, 
   2461                             base_index, pool_index));
   2462 
   2463     /* clean up the profile_group when no stat_couter_id assocated with */
   2464     /* rv = BCM_E_INTERNAL could be ignored here */
   2465     rv = _bcm_esw_flowcnt_profile_group_destroy(
   2466                             unit, profile_index, profile_group);
   2467     if (rv == BCM_E_INTERNAL) {
   2468         rv = BCM_E_NONE;
   2469     }
   2470 
   2471     return rv;
   2472 }
   2473 
   2474 /*
   2475  * Function:
   2476  *  _bcm_esw_flowcnt_group_mode_id_destroy
   2477  * Description:
   2478  *  Destroys Customized Group mode
   2479  * Parameters:
   2480  *  
   2481  *  unit                : (IN)  UNIT number
   2482  *  mode_id             : (IN) Created Mode Identifier for Flowcnt Group Mode
   2483  *
   2484  * Returns:
   2485  *  BCM_E_*
   2486  */
   2487 int _bcm_esw_flowcnt_group_mode_id_destroy(
   2488     int unit,
   2489     uint32 mode_id)
   2490 {
   2491     int profile_id, profile_group_id;
   2492 
   2493     _bcm_esw_flowcnt_custom_mode_id_get(mode_id, &profile_id, &profile_group_id);
   2494 
   2495     return _bcm_esw_flowcnt_profile_group_destroy(unit, profile_id, profile_group_id);
   2496 }
   2497 
   2498 /*
   2499  * Function:
   2500  *  _bcm_esw_flowcnt_group_mode_id_get
   2501  * Description:
   2502  *  Retrieves Customized Stat Group mode Attributes for given mode_id
   2503  * Parameters:
   2504  *  
   2505  *  unit                : (IN)  UNIT number
   2506  *  mode_id             : (IN) Created Mode Identifier for Stat Flex Group Mode
   2507  *  flags               : (OUT)  STAT_GROUP_MODE_* flags (INGRESS/EGRESS)
   2508  *  total_counters      : (OUT)  Total Counters for Stat Flex Group Mode
   2509  *  num_selectors       : (IN)  Number of Selectors for Stat Flex Group Mode
   2510  *  attr_selectors      : (OUT)  Attribute Selectors for Stat Flex Group Mode
   2511  *  actual_num_selectors: (OUT) Actual Number of Selectors for Stat Flex
   2512  *                              Group Mode
   2513  *
   2514  * Returns:
   2515  *  BCM_E_*
   2516  */
   2517 int _bcm_esw_flowcnt_group_mode_id_get(
   2518     int unit,
   2519     uint32 mode_id,
   2520     uint32 *flags,
   2521     uint32 *total_counters,
   2522     uint32 num_selectors,
   2523     bcm_stat_group_mode_attr_selector_t *attr_selectors,
   2524     uint32 *actual_num_selectors)
   2525 {    
   2526     int profile_id, profile_group_id, i;
   2527     _bcm_esw_flowcnt_control_t *fc = NULL;
   2528     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   2529     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   2530     int effect_num;
   2531 
   2532     if ((flags == NULL) ||
   2533         (total_counters == NULL) ||
   2534         (actual_num_selectors == NULL)) {
   2535          return BCM_E_PARAM;
   2536     }
   2537 
   2538     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   2539     _bcm_esw_flowcnt_custom_mode_id_get(mode_id, &profile_id, &profile_group_id);
   2540 
   2541     _FLOWCNT_LOCK(fc);
   2542     if (profile_id >= fc->num_profiles) {
   2543         _FLOWCNT_UNLOCK(fc);
   2544         return BCM_E_PARAM;
   2545     }
   2546     fc_profile = &fc->flowcnt_profile[profile_id];
   2547     if (profile_group_id >= fc_profile->num_groups) {
   2548         _FLOWCNT_UNLOCK(fc);
   2549         return BCM_E_PARAM;
   2550     }
   2551     fc_pgroup = &fc_profile->flowcnt_group[profile_group_id];
   2552 
   2553     if (fc_pgroup->available == 0) {
   2554         _FLOWCNT_UNLOCK(fc);
   2555         return BCM_E_NOT_FOUND;
   2556     }
   2557 
   2558     *flags = fc_pgroup->flags;
   2559     *total_counters = fc_pgroup->total_counters;
   2560     *actual_num_selectors = fc_pgroup->num_selectors;
   2561 
   2562     if (num_selectors <= *actual_num_selectors) {
   2563         effect_num = num_selectors;
   2564     } else {
   2565         effect_num = *actual_num_selectors;
   2566     }
   2567     for (i = 0 ; i < effect_num; i++) {
   2568         sal_memset(&(attr_selectors[i]), 0,
   2569                    sizeof(bcm_stat_group_mode_attr_selector_t));
   2570         attr_selectors[i].attr
   2571             = fc_pgroup->attr_selectors[i].attr;
   2572         attr_selectors[i].counter_offset
   2573             = fc_pgroup->attr_selectors[i].counter_offset;
   2574         attr_selectors[i].attr_value
   2575             = fc_pgroup->attr_selectors[i].attr_value;
   2576     }
   2577     _FLOWCNT_UNLOCK(fc);
   2578 
   2579     return BCM_E_NONE;
   2580 }
   2581 
   2582 /*
   2583  * Function:
   2584  *  _bcm_esw_flowcnt_group_mode_id_create
   2585  * Description:
   2586  *  Create Customized Stat Group mode for given Counter Attributes
   2587  * Parameters:
   2588  *  
   2589  *  unit           : (IN)  UNIT number      
   2590  *  flags          : (IN)  STAT_GROUP_MODE_* flags (INGRESS/EGRESS)
   2591  *  total_counters : (IN)  Total Counters for Stat Flex Group Mode
   2592  *  num_selectors  : (IN)  Number of Selectors for Stat Flex Group Mode
   2593  *  attr_selectors : (IN)  Attribute Selectors for Stat Flex Group Mode
   2594  *  mode_id        : (OUT) Created Mode Identifier for Stat Flex Group Mode
   2595  *
   2596  * Returns:
   2597  *  BCM_E_*
   2598  */
   2599 int 
   2600 _bcm_esw_flowcnt_group_mode_id_create(
   2601     int unit,
   2602     uint32 flags,
   2603     uint32 total_counters,
   2604     uint32 num_selectors,
   2605     bcm_stat_group_mode_attr_selector_t *attr_selectors,
   2606     uint32 *mode_id)
   2607 {
   2608     int i, j;
   2609     bcm_stat_group_mode_attr_t attr;
   2610     _bcm_esw_flowcnt_control_t *fc = NULL;
   2611     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   2612     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   2613     int direction;
   2614     int rv;
   2615     int profile_group, profile_index;
   2616 
   2617     /* Perform Sanity Checks */
   2618     if (!((flags & BCM_STAT_GROUP_MODE_INGRESS) ||
   2619           (flags & BCM_STAT_GROUP_MODE_EGRESS))) {
   2620          return BCM_E_PARAM;
   2621     }
   2622 
   2623     if (total_counters == 0) {
   2624          return BCM_E_PARAM;
   2625     }
   2626     attr = -1;
   2627     for (i = 0; i < num_selectors; i ++) {
   2628         if (i == 0) {
   2629             attr = attr_selectors[i].attr;
   2630         } else if (attr != attr_selectors[i].attr) {
   2631             /* in current HR3 flowcnt, each mode has the same attribute */
   2632             return BCM_E_PARAM;
   2633         }
   2634     }
   2635 
   2636     if (flags & BCM_STAT_GROUP_MODE_INGRESS) {
   2637         direction = bcmStatFlexDirectionIngress;
   2638     } else {
   2639         direction = bcmStatFlexDirectionEgress;
   2640     }
   2641     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   2642 
   2643     _FLOWCNT_LOCK(fc);
   2644 
   2645     /* Checck for existing mode */
   2646     for (i = 0; i < fc->num_profiles; i ++) {
   2647         fc_profile = &fc->flowcnt_profile[i];
   2648         if ((fc_profile->direction == direction) &&
   2649             (fc_profile->attr == attr)) {
   2650             for (j = 0; j < fc_profile->num_groups; j++) {
   2651                 fc_pgroup = &fc_profile->flowcnt_group[j];
   2652                 if (fc_pgroup->available) {
   2653                     if (_bcm_esw_flowcnt_selectors_cmp (
   2654                         unit, fc_profile->profile_table,
   2655                         fc_profile->num_entries,
   2656                         fc_pgroup->num_selectors,
   2657                         num_selectors,
   2658                         fc_pgroup->attr_selectors,
   2659                         attr_selectors) == 0){
   2660                         LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
   2661                                     (BSL_META_U(unit,
   2662                                                 "Mode exist \n")));
   2663                         _bcm_esw_flowcnt_custom_mode_id_set(
   2664                             i, j, mode_id);
   2665                         _FLOWCNT_UNLOCK(fc);
   2666                         return BCM_E_EXISTS;
   2667                     }
   2668                 }
   2669             }
   2670         }
   2671     }
   2672     /* 
   2673      * Create and add the profile group
   2674      * profile table(HW)would be configured
   2675      */
   2676     rv = _bcm_esw_flowcnt_profile_group_create(unit,
   2677                                                direction,
   2678                                                0,
   2679                                                total_counters,
   2680                                                num_selectors,
   2681                                                attr_selectors,
   2682                                                &profile_index,
   2683                                                &profile_group);
   2684 
   2685     if (BCM_FAILURE(rv)){
   2686         _FLOWCNT_UNLOCK(fc);
   2687         return rv;
   2688     }
   2689 
   2690     fc_profile = &fc->flowcnt_profile[profile_index];
   2691     fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   2692     fc_pgroup->flags = flags;
   2693 
   2694     _bcm_esw_flowcnt_custom_mode_id_set(profile_index, profile_group, mode_id);
   2695 
   2696     _FLOWCNT_UNLOCK(fc);
   2697 
   2698     return BCM_E_NONE;
   2699 }
   2700 
   2701 /*
   2702  * Function:
   2703  *  _bcm_esw_flowcnt_custom_group_create
   2704  * Description:
   2705  *  Associate an accounting object to customized group mode 
   2706  *
   2707  * Parameters:
   2708  *  
   2709  *  unit                : (IN)  UNIT number
   2710  *  mode_id             : (IN) Created Mode Identifier for Stat Flex Group Mode
   2711  *  object              : (IN) Accounting object
   2712  *  Stat_counter_id     : (OUT) Stat Counter Id
   2713  *  num_entries         : (OUT) Number of Counter entries created
   2714  *
   2715  * Returns:
   2716  *  BCM_E_*
   2717  */
   2718 int _bcm_esw_flowcnt_custom_group_create(
   2719     int unit,
   2720     uint32 mode_id,
   2721     bcm_stat_object_t object,
   2722     uint32 *stat_counter_id,
   2723     uint32 *num_entries)
   2724 {
   2725     bcm_stat_group_mode_t group_mode= bcmStatGroupModeSingle;
   2726     uint32 total_counters=0;
   2727     _bcm_esw_flowcnt_control_t *fc = NULL;
   2728     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   2729     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   2730     int profile_id, profile_group_id; 
   2731     int pool_index, base_index;
   2732     int rv;
   2733 
   2734     BCM_IF_ERROR_RETURN(
   2735         _bcm_esw_flowcnt_stat_object_validate(unit, object));
   2736     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   2737     _bcm_esw_flowcnt_custom_mode_id_get(mode_id, &profile_id, &profile_group_id);
   2738 
   2739     _FLOWCNT_LOCK(fc);
   2740     if (profile_id >= fc->num_profiles) {
   2741         _FLOWCNT_UNLOCK(fc);
   2742         return BCM_E_PARAM;
   2743     }
   2744     fc_profile = &fc->flowcnt_profile[profile_id];
   2745     if (profile_group_id >= fc_profile->num_groups) {
   2746         _FLOWCNT_UNLOCK(fc);
   2747         return BCM_E_PARAM;
   2748     }    
   2749     fc_pgroup = &fc_profile->flowcnt_group[profile_group_id];
   2750     total_counters = fc_pgroup->total_counters;
   2751     group_mode = bcmFlowcntProfileGroup1 + profile_group_id;
   2752     fc_pgroup->group_mode = group_mode;
   2753     _FLOWCNT_UNLOCK(fc);
   2754 
   2755     /* Reserve the counter table */
   2756     rv = _bcm_esw_flowcnt_counter_create(unit, object, profile_group_id,
   2757                                          total_counters, 
   2758                                          &base_index, &pool_index);
   2759    if (BCM_FAILURE(rv)){
   2760         return rv;
   2761     }
   2762 
   2763    _bcm_esw_flowcnt_counter_id_set(
   2764                  group_mode, object,
   2765                  profile_group_id,
   2766                  pool_index,
   2767                  base_index,
   2768                  stat_counter_id);
   2769     *num_entries = total_counters;
   2770 
   2771     return BCM_E_NONE;
   2772 }
   2773 
   2774 /*
   2775  * Function:
   2776  *      _bcm_esw_flowcnt_group_create
   2777  * Description:
   2778  *      Reserve HW counter resources as per given group mode and acounting
   2779  *      object and make system ready for further stat collection action
   2780  *
   2781  * Parameters:
   2782  *    Unit            (IN)  Unit number
   2783  *    object          (IN)  Accounting Object
   2784  *    Group_mode      (IN)  Group Mode
   2785  *    Stat_counter_id (OUT) Stat Counter Id
   2786  *    num_entries     (OUT) Number of Counter entries created
   2787  * Return Value:
   2788  *      BCM_E_XXX
   2789  * Notes:
   2790  */
   2791 int _bcm_esw_flowcnt_group_create (
   2792             int                   unit,
   2793             bcm_stat_object_t     object,
   2794             bcm_stat_group_mode_t group_mode,
   2795             uint32                *stat_counter_id,
   2796             uint32                *num_entries)
   2797 {
   2798     int total_counters=0;
   2799     int num_selectors;
   2800     bcm_stat_group_mode_attr_selector_t *attr_selectors = NULL;
   2801     bcm_stat_group_mode_attr_t attr;
   2802     bcm_stat_flex_direction_t   direction = bcmStatFlexDirectionIngress;
   2803     int profile_group, profile_index;
   2804     _bcm_esw_flowcnt_control_t *fc = NULL;
   2805     int rv = BCM_E_NONE;
   2806     int base_index, pool_index;
   2807     uint32 default_attr_mode_id = 0;
   2808 
   2809 
   2810     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   2811 
   2812     BCM_IF_ERROR_RETURN(
   2813         _bcm_esw_flowcnt_stat_group_mode_validate(unit, group_mode));
   2814     BCM_IF_ERROR_RETURN(
   2815         _bcm_esw_flowcnt_stat_object_validate(unit, object));
   2816 
   2817     switch (group_mode) {
   2818         case bcmStatGroupModeSingle:
   2819             total_counters = 1;
   2820             break;
   2821         default:
   2822             return BCM_E_PARAM;
   2823     }
   2824     switch (object) {
   2825         case bcmStatObjectIngVlanXlate:
   2826         case bcmStatObjectIngFieldStageLookup:
   2827         case bcmStatObjectEgrVlanXlate:
   2828             num_selectors = 16;
   2829             attr = bcmStatGroupModeAttrPktCfiPri;
   2830             if ((int)object == bcmStatObjectEgrVlanXlate) {
   2831                 direction = bcmStatFlexDirectionEgress;
   2832             }
   2833             break;
   2834         default:
   2835             return BCM_E_PARAM;
   2836     }
   2837 
   2838     _FLOWCNT_LOCK(fc);
   2839     if (fc->default_attr_mode_id[attr] == 0) {
   2840         _FLOWCNT_ALLOC(unit, attr_selectors, bcm_stat_group_mode_attr_selector_t,
   2841                        num_selectors * 
   2842                        sizeof(bcm_stat_group_mode_attr_selector_t),
   2843                        "flowcnt default pkt attr", 0, rv);
   2844         if (BCM_FAILURE(rv)){
   2845             _FLOWCNT_UNLOCK(fc);
   2846             return rv;
   2847         }
   2848         /* setup the default attr_selectors based on the the attr */
   2849         rv = _bcm_esw_flowcnt_default_attr_config(unit, attr,
   2850                                                    num_selectors,
   2851                                                    attr_selectors);
   2852         if (BCM_FAILURE(rv)){
   2853             _FLOWCNT_UNLOCK(fc);
   2854             _FLOWCNT_FREE(unit, attr_selectors, 0);
   2855             return rv;
   2856         }    
   2857         /* 
   2858          * Create and add the profile group 
   2859          * profile table(HW)would be configured
   2860          */
   2861         rv = _bcm_esw_flowcnt_profile_group_create(unit,
   2862                                                    direction,
   2863                                                    group_mode,
   2864                                                    total_counters,
   2865                                                    num_selectors,
   2866                                                    attr_selectors,
   2867                                                    &profile_index,
   2868                                                    &profile_group);
   2869         if (BCM_FAILURE(rv)){
   2870             _FLOWCNT_UNLOCK(fc);
   2871             _FLOWCNT_FREE(unit, attr_selectors, 0);
   2872             return rv;
   2873         }
   2874 
   2875         _bcm_esw_flowcnt_custom_mode_id_set(profile_index, profile_group,
   2876                                             &fc->default_attr_mode_id[attr]);
   2877          fc->default_attr_mode_id[attr] |= _BCM_FLOWCNT_MODE_ID_VALID;
   2878         _FLOWCNT_FREE(unit, attr_selectors, 0);
   2879     } else {
   2880         default_attr_mode_id = fc->default_attr_mode_id[attr];
   2881         default_attr_mode_id &= ~(_BCM_FLOWCNT_MODE_ID_VALID);
   2882         _bcm_esw_flowcnt_custom_mode_id_get(default_attr_mode_id,
   2883                                             &profile_index, &profile_group);
   2884     }
   2885     /* Reserve the counter table */
   2886     rv = _bcm_esw_flowcnt_counter_create(unit, object, profile_group,
   2887                                          total_counters, 
   2888                                          &base_index, &pool_index);
   2889     
   2890     if (BCM_FAILURE(rv)){
   2891         _FLOWCNT_UNLOCK(fc);
   2892         return rv;
   2893     }
   2894 
   2895     _FLOWCNT_UNLOCK(fc);
   2896 
   2897     _bcm_esw_flowcnt_counter_id_set(
   2898                  group_mode, object,
   2899                  profile_group,
   2900                  pool_index,
   2901                  base_index,
   2902                  stat_counter_id);
   2903     *num_entries = total_counters;
   2904 
   2905     return BCM_E_NONE;
   2906 }
   2907 
   2908 /*
   2909  * Function:
   2910  *      _bcm_esw_flowcnt_counter_set
   2911  * Description:
   2912  *      Set Flex Counter Values
   2913  * Parameters:
   2914  *      unit                  - (IN) unit number
   2915  *      index                 - (IN) Flex Accounting Table Index
   2916  *      table                 - (IN) Flex Accounting Table
   2917  *      byte_flag             - (IN) Byte/Packet Flag
   2918  *      counter               - (IN) Counter Index
   2919  *      values                - (IN) Counter Value
   2920  * Return Value:
   2921  *      BCM_E_XXX
   2922  * Notes:
   2923  */
   2924 int _bcm_esw_flowcnt_counter_set(
   2925             int              unit,
   2926             uint32           index,
   2927             soc_mem_t        table,
   2928             uint32           byte_flag,
   2929             uint32           counter_index,
   2930             bcm_stat_value_t *value)
   2931 {
   2932     _bcm_esw_flowcnt_control_t *fc = NULL;
   2933     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   2934     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   2935     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   2936     int pool_index, offset_index, total_entries;
   2937     int profile_index, object_index;
   2938     uint32 base_index, profile_ptr;
   2939     int rv = BCM_E_NONE;
   2940     void *entry_data = NULL;
   2941     uint32 entry_data_size = 0;
   2942     soc_mem_info_t *memp = NULL; 
   2943     bcm_stat_object_t   object; 
   2944     soc_mem_t   counter_mem;
   2945     uint32 max_packet_mask=0;
   2946     uint64 max_byte_mask;
   2947     uint32 hw_val[2];
   2948     
   2949     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   2950 
   2951     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_accounting_object_info_get(
   2952                             unit, table, index,
   2953                             &profile_ptr, &base_index, &object_index));
   2954 
   2955     object = valid_stat_object_list[unit][object_index].object;
   2956     rv = _bcm_esw_flowcnt_object_table_map(unit, object,
   2957                                            &profile_index,
   2958                                            &pool_index);
   2959     if (BCM_FAILURE(rv)){
   2960         return rv;
   2961     }
   2962 
   2963     _FLOWCNT_LOCK(fc);
   2964     fc_pool = &fc->flowcnt_pool[pool_index];
   2965     fc_profile = &fc->flowcnt_profile[profile_index];
   2966     fc_pgroup = &fc_profile->flowcnt_group[profile_ptr];
   2967     counter_mem = fc_pool->mem;
   2968     total_entries = fc_pgroup->total_counters;
   2969     offset_index = counter_index;
   2970 
   2971     if (offset_index >= total_entries) {
   2972         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   2973                   (BSL_META_U(unit,
   2974                               "Wrong OFFSET_INDEX. Must be < Total Counters %d \n"),
   2975                    total_entries));
   2976         _FLOWCNT_UNLOCK(fc);
   2977         return BCM_E_PARAM;
   2978     }
   2979 
   2980     memp = &SOC_MEM_INFO(unit, counter_mem);
   2981     entry_data_size = WORDS2BYTES(BYTES2WORDS(memp->bytes));
   2982     _FLOWCNT_ALLOC(unit, entry_data, void, entry_data_size,
   2983                "counter table entry", 0, rv);
   2984     if (BCM_FAILURE(rv)){
   2985         _FLOWCNT_UNLOCK(fc);
   2986         return rv;
   2987     }
   2988     if (soc_mem_read(unit,
   2989                      counter_mem,
   2990                      MEM_BLOCK_ANY,
   2991                      base_index+offset_index,
   2992                      entry_data) != BCM_E_NONE){
   2993         _FLOWCNT_UNLOCK(fc);
   2994         _FLOWCNT_FREE(unit, entry_data, 0);
   2995         return BCM_E_INTERNAL;
   2996     }
   2997     COMPILER_64_ZERO(max_byte_mask);
   2998     if (byte_flag == 1) {
   2999         fc_pool->flow_stat_type[base_index+offset_index] =
   3000                     bcmFlowcntStatTypeByte;
   3001         
   3002         /* Mask to possible max values */
   3003         COMPILER_64_AND(value->bytes, max_byte_mask);
   3004         /* Update Soft Copy */
   3005         COMPILER_64_SET(fc_pool->flow_byte_counter[base_index+offset_index],
   3006                         COMPILER_64_HI(value->bytes),
   3007                         COMPILER_64_LO(value->bytes));
   3008         /* Change Read Hw Copy */
   3009         hw_val[0] = COMPILER_64_LO(value->bytes);
   3010         hw_val[1] = COMPILER_64_HI(value->bytes);
   3011         soc_mem_field_set(unit,
   3012                           counter_mem,
   3013                           (uint32 *)entry_data,
   3014                           BYTE_COUNTERf,
   3015                           hw_val);
   3016         soc_mem_field_set(unit,
   3017                           counter_mem,
   3018                           (uint32 *)entry_data,
   3019                           COUNT_BYTEf,
   3020                           &byte_flag);
   3021         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3022                   (BSL_META_U(unit,
   3023                               "Byte Count Value\t:TABLE:%sINDEX:%d "
   3024                                "(@Pool:%d ActualOffset%d) : %x:%x \n"),
   3025                    SOC_MEM_UFNAME(unit, counter_mem),
   3026                    index,
   3027                    pool_index,
   3028                    base_index+offset_index,
   3029                    COMPILER_64_HI(value->bytes),
   3030                    COMPILER_64_LO(value->bytes)));
   3031     } else {
   3032         fc_pool->flow_stat_type[base_index+offset_index] =
   3033                     bcmFlowcntStatTypePacket;
   3034 
   3035         value->packets &= max_packet_mask;
   3036         /* Update Soft Copy */
   3037         fc_pool->flow_packet_counter[base_index+offset_index] = value->packets;
   3038 
   3039         /* Update Soft Copy */
   3040         COMPILER_64_SET(fc_pool->flow_packet64_counter[base_index+offset_index],0,
   3041                          value->packets);
   3042         /* Change Read Hw Copy */
   3043         soc_mem_field_set(unit,
   3044                           counter_mem,
   3045                           (uint32 *)entry_data,
   3046                           PACKET_COUNTERf,
   3047                           &(value->packets));
   3048         soc_mem_field_set(unit,
   3049                           counter_mem,
   3050                           (uint32 *)entry_data,
   3051                           COUNT_BYTEf,
   3052                           &byte_flag);
   3053         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3054                   (BSL_META_U(unit,
   3055                               "Packet Count Value\t:TABLE:%sINDEX:%d "
   3056                               "(@Pool:%d ActualOffset%d) : %x \n"),
   3057                    SOC_MEM_UFNAME(unit, counter_mem),
   3058                    index,
   3059                    pool_index,
   3060                    base_index+offset_index,
   3061                    value->packets));
   3062     }
   3063     /* Update Hw Copy */
   3064     if (soc_mem_write(unit, counter_mem, MEM_BLOCK_ALL,
   3065                       base_index+offset_index,
   3066                       entry_data) != BCM_E_NONE){
   3067         _FLOWCNT_UNLOCK(fc);
   3068         _FLOWCNT_FREE(unit, entry_data, 0);
   3069         return BCM_E_INTERNAL;
   3070     }
   3071     _FLOWCNT_UNLOCK(fc);
   3072     _FLOWCNT_FREE(unit, entry_data, 0);
   3073     return BCM_E_NONE;
   3074 }
   3075 
   3076 /*
   3077  * Function:
   3078  *      _bcm_esw_flowcnt_counter_get
   3079  * Description:
   3080  *      Get Flex Counter Values
   3081  *      if sync_mode is set, sync the sw accumulated count
   3082  *      with hw count value first, else return sw count.
   3083  *
   3084  * Parameters:
   3085  *      unit                  - (IN) unit number
   3086  *      sync_mode             - (IN) hwcount is to be synced to sw count
   3087  *      index                 - (IN) Flex Accounting Table Index
   3088  *      table                 - (IN) Flex Accounting Table
   3089  *      byte_flag             - (IN) Byte/Packet Flag
   3090  *      counter               - (IN) Counter Index
   3091  *      values                - (OUT) Counter Value
   3092  *
   3093  * Return Value:
   3094  *      BCM_E_XXX
   3095  * Notes:
   3096  */
   3097 int _bcm_esw_flowcnt_counter_get(
   3098             int              unit,
   3099             int              sync_mode,
   3100             uint32           index,
   3101             soc_mem_t        table,
   3102             uint32           byte_flag,
   3103             uint32           counter_index,
   3104             bcm_stat_value_t *value)
   3105 {
   3106     _bcm_esw_flowcnt_control_t *fc = NULL;
   3107     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   3108     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   3109     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   3110     int object_index, pool_index, profile_index, offset_index, total_entries;
   3111     uint32 base_index, profile_ptr;
   3112     int rv = BCM_E_NONE;
   3113     bcm_stat_object_t   object;
   3114     soc_mem_t   counter_mem;
   3115 
   3116     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   3117 
   3118     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_accounting_object_info_get(
   3119                             unit, table, index,
   3120                             &profile_ptr, &base_index, &object_index));
   3121     
   3122     object = valid_stat_object_list[unit][object_index].object;
   3123     rv = _bcm_esw_flowcnt_object_table_map(unit, object,
   3124                                            &profile_index,
   3125                                            &pool_index);
   3126     if (BCM_FAILURE(rv)){
   3127         return rv;
   3128     }
   3129     
   3130     _FLOWCNT_LOCK(fc);
   3131     fc_pool = &fc->flowcnt_pool[pool_index];
   3132     fc_profile = &fc->flowcnt_profile[profile_index];
   3133     fc_pgroup = &fc_profile->flowcnt_group[profile_ptr];
   3134     counter_mem = fc_pool->mem; 
   3135     total_entries = fc_pgroup->total_counters;
   3136     offset_index = counter_index;
   3137     
   3138     if (offset_index >= total_entries) {
   3139         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   3140                   (BSL_META_U(unit,
   3141                               "Wrong OFFSET_INDEX. Must be < Total Counters %d \n"),
   3142                    total_entries));
   3143         _FLOWCNT_UNLOCK(fc);
   3144         return BCM_E_PARAM;
   3145     }
   3146 
   3147     if (byte_flag == 1) {
   3148         if (fc_pool->flow_stat_type[base_index+offset_index] !=
   3149             bcmFlowcntStatTypeByte) {
   3150             _FLOWCNT_UNLOCK(fc);
   3151             return BCM_E_PARAM;
   3152         }
   3153     } else {
   3154         if (fc_pool->flow_stat_type[base_index+offset_index] !=
   3155             bcmFlowcntStatTypePacket) {
   3156             _FLOWCNT_UNLOCK(fc);
   3157             return BCM_E_PARAM;
   3158         }
   3159     }
   3160 
   3161     /* sync the software counter with hardware counter */
   3162     if (sync_mode == 1) {
   3163         _bcm_esw_flowcnt_counter_collect(unit,
   3164                                         counter_mem,
   3165                                         base_index + offset_index);
   3166     }
   3167 
   3168     bcm_stat_value_t_init(value);
   3169     if (byte_flag == 1) {
   3170         COMPILER_64_SET(value->bytes,
   3171                         COMPILER_64_HI(fc_pool->
   3172                                        flow_byte_counter[base_index+offset_index]),
   3173                         COMPILER_64_LO(fc_pool->
   3174                                        flow_byte_counter[base_index+offset_index]));
   3175         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3176                   (BSL_META_U(unit,
   3177                               "Byte Count Value\t:TABLE:%sINDEX:%d"
   3178                               "(@Pool:%d ActualOffset%d) : %x:%x \n"),
   3179                   SOC_MEM_UFNAME(unit, counter_mem),
   3180                   index,
   3181                   pool_index,
   3182                   base_index+offset_index,
   3183                   COMPILER_64_HI(value->bytes),
   3184                   COMPILER_64_LO(value->bytes)));
   3185     } else {
   3186         value->packets= fc_pool->
   3187                         flow_packet_counter[base_index+offset_index];
   3188         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3189                   (BSL_META_U(unit,
   3190                               "Packet Count Value\t:TABLE:%sINDEX:%d "
   3191                               "(@Pool:%dActualOffset%d) : %x \n"),
   3192                   SOC_MEM_UFNAME(unit, counter_mem),
   3193                   index,
   3194                   pool_index,
   3195                   base_index+offset_index,
   3196                   value->packets));
   3197         COMPILER_64_SET(value->packets64,
   3198                         COMPILER_64_HI(fc_pool->
   3199                                        flow_packet64_counter
   3200                                        [base_index+offset_index]),
   3201                         COMPILER_64_LO(fc_pool->
   3202                                        flow_packet64_counter
   3203                                        [base_index+offset_index]));
   3204         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3205                   (BSL_META_U(unit,
   3206                               "Packet64 Count Value\t:TABLE:%sINDEX:%d "
   3207                                "(@Pool:%d ActualOffset%d) : %x:%x \n"),
   3208                   SOC_MEM_UFNAME(unit, counter_mem),
   3209                   index,
   3210                   pool_index,
   3211                   base_index+offset_index,
   3212                   COMPILER_64_HI(value->packets64),
   3213                   COMPILER_64_LO(value->packets64)));
   3214     }
   3215     _FLOWCNT_UNLOCK(fc);
   3216 
   3217      return BCM_E_NONE;
   3218 }
   3219 
   3220 
   3221 /*
   3222  * Function:
   3223  *      _bcm_esw_flowcnt_stat_id_get
   3224  * Description:
   3225  *      Get stat id of the accounting object
   3226  *
   3227  * Parameters:
   3228  *      unit                  - (IN) unit number
   3229  *      table                 - (IN) Accounting Table
   3230  *      index                 - (IN) Accounting Table Index
   3231  *      stat_counter_id       - (OUT) Stat Id
   3232  *
   3233  * Return Value:
   3234  *      BCM_E_XXX
   3235  * Notes:
   3236  */
   3237 int 
   3238 _bcm_esw_flowcnt_stat_id_get(
   3239             int         unit,
   3240             soc_mem_t   table,
   3241             int         index,
   3242             uint32      *stat_counter_id)
   3243 {
   3244     uint32 base_index, profile_ptr;
   3245     bcm_stat_object_t   object;
   3246     _bcm_esw_flowcnt_control_t *fc = NULL;
   3247     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   3248     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   3249     int object_index, pool_index, profile_index;
   3250     int rv;
   3251 
   3252     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_accounting_object_info_get(
   3253                             unit, table, index,
   3254                             &profile_ptr, &base_index, &object_index));
   3255                             
   3256     object = valid_stat_object_list[unit][object_index].object;
   3257 
   3258     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   3259     
   3260 
   3261     rv = _bcm_esw_flowcnt_object_table_map(unit, object,
   3262                                            &profile_index, &pool_index);
   3263     if (BCM_FAILURE(rv)) {
   3264         return rv;
   3265     }
   3266 
   3267     _FLOWCNT_LOCK(fc);
   3268 
   3269     fc_profile = &fc->flowcnt_profile[profile_index];
   3270     fc_pgroup = &fc_profile->flowcnt_group[profile_ptr];
   3271 
   3272     _FLOWCNT_UNLOCK(fc);
   3273 
   3274    _bcm_esw_flowcnt_counter_id_set(
   3275                  fc_pgroup->group_mode,
   3276                  object,
   3277                  profile_ptr,
   3278                  pool_index,
   3279                  base_index,
   3280                  stat_counter_id);
   3281 
   3282     return BCM_E_NONE;
   3283 }
   3284 
   3285 
   3286 
   3287 /*
   3288  * Function:
   3289  *      _bcm_esw_flowcnt_stat_type_validate
   3290  * Description:
   3291  *      Validate the stat type of the accounting table entry
   3292  *
   3293  * Parameters:
   3294  *      unit                  - (IN) unit number
   3295  *      table                 - (IN) Accounting Table
   3296  *      index                 - (IN) Accounting Table Index
   3297  *      flow_stat_type        - (IN) stat type (bcmFlowcntStatTypeByte/Packet)
   3298  *
   3299  * Return Value:
   3300  *      BCM_E_XXX
   3301  * Notes:
   3302  */
   3303 int 
   3304 _bcm_esw_flowcnt_stat_type_validate(
   3305             int         unit,
   3306             soc_mem_t   table,
   3307             int         index,
   3308             _bcm_flowcnt_stat_type_t flow_stat_type)
   3309 {
   3310     uint32 base_index, profile_ptr;
   3311     bcm_stat_object_t   object;
   3312     _bcm_esw_flowcnt_control_t *fc = NULL;
   3313     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   3314     int object_index, pool_index, profile_index;
   3315     int rv;
   3316 
   3317     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_accounting_object_info_get(
   3318                             unit, table, index,
   3319                             &profile_ptr, &base_index, &object_index));
   3320                             
   3321     object = valid_stat_object_list[unit][object_index].object;
   3322 
   3323     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   3324     
   3325     rv = _bcm_esw_flowcnt_object_table_map(unit, object,
   3326                                            &profile_index, &pool_index);
   3327     if (BCM_FAILURE(rv)) {
   3328         return rv;
   3329     }
   3330 
   3331     _FLOWCNT_LOCK(fc);
   3332     fc_pool = &fc->flowcnt_pool[pool_index];
   3333 
   3334     if (fc_pool->flow_stat_type[base_index] == 0) {
   3335         _FLOWCNT_UNLOCK(fc);
   3336         return BCM_E_NOT_FOUND;
   3337     }
   3338     if (fc_pool->flow_stat_type[base_index] != flow_stat_type) {
   3339         _FLOWCNT_UNLOCK(fc);
   3340         return BCM_E_PARAM;
   3341     }
   3342     _FLOWCNT_UNLOCK(fc);
   3343 
   3344     return BCM_E_NONE;
   3345 
   3346 }
   3347 
   3348 /*
   3349  * Function:
   3350  *      _bcm_esw_flowcnt_group_dump_info
   3351  * Description:
   3352  *      Dump Useful Info about configured group
   3353  * Parameters:
   3354  *      unit                  - (IN) unit number
   3355  *      all_flag              - (IN) If 1, object and group_mode are ignored
   3356  *      object                - (IN) Flex Accounting object
   3357  *      group                 - (IN) Flex Group Mode
   3358  * Return Value:
   3359  *      BCM_E_XXX
   3360  * Notes:
   3361  */
   3362 int _bcm_esw_flowcnt_group_dump_info(
   3363      int                   unit,
   3364      int                   all_flag,
   3365      bcm_stat_object_t     object,
   3366      bcm_stat_group_mode_t group)
   3367 {
   3368     int i;
   3369     uint32 index = 0, stat_counter_id;
   3370     bcm_stat_object_t l_object;
   3371     bcm_stat_group_mode_t group_mode;
   3372     _bcm_esw_flowcnt_control_t *fc = NULL;
   3373     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   3374     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   3375     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   3376     uint32  profile_group, pool_index, base_index;
   3377     int profile_index, pool_idx;
   3378     uint32 total_counters, num_ctr;
   3379     char *oname[] = BCM_STAT_OBJECT;
   3380     uint32 *ptr = (uint32 *)&local_scache_ptr[unit][0];
   3381 
   3382     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   3383     _FLOWCNT_LOCK(fc);
   3384     LOG_CLI((BSL_META_U(unit,
   3385                         "Not attached(MAX=%d) Stat counter Id info \n"),
   3386              MAX_FLOWCNT_SCACHE_SIZE));
   3387     for (index = 0; index < MAX_FLOWCNT_SCACHE_SIZE; index++) {
   3388         if (ptr[index] != 0) {
   3389             stat_counter_id = ptr[index];
   3390             _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode,
   3391                                             &l_object,&profile_group,
   3392                                             &pool_index, &base_index); 
   3393             if (_bcm_esw_flowcnt_object_table_map(
   3394                     unit, l_object, &profile_index, &pool_idx) != BCM_E_NONE){
   3395                 continue;
   3396             }
   3397             fc_profile = &fc->flowcnt_profile[profile_index];
   3398             fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   3399             fc_pool = &fc->flowcnt_pool[pool_idx];
   3400             total_counters = fc_pgroup->total_counters;
   3401             if (total_counters == 0) {
   3402                 continue;
   3403             }
   3404             if ((all_flag == TRUE) ||
   3405                 ((l_object == object) && (group_mode == group))) {
   3406                    LOG_CLI((BSL_META_U(unit,
   3407                                        "\tstat_counter_id = %d=0x%x \n"),
   3408                             stat_counter_id, stat_counter_id));
   3409                    LOG_CLI((BSL_META_U(unit,
   3410                                        "\t\t mode:%d profile_mem:%s"
   3411                                        "\n\t\tpool:%d object:%s base:%d"
   3412                                        " total_counters=%d\n"),
   3413                             profile_group,
   3414                             SOC_MEM_UFNAME(unit, fc_profile->profile_table),
   3415                             pool_idx, oname[l_object],
   3416                             base_index, total_counters));
   3417              }
   3418         }
   3419     }
   3420     LOG_CLI((BSL_META_U(unit,
   3421                         "Atached Stat counter Id info \n")));
   3422     for (l_object = 0; l_object < bcmStatObjectMaxValue; l_object++){
   3423         if (_bcm_esw_flowcnt_object_table_map(
   3424                 unit, l_object, &profile_index, &pool_idx) != BCM_E_NONE){
   3425             continue;
   3426         }
   3427         fc_profile = &fc->flowcnt_profile[profile_index];
   3428         fc_pool = &fc->flowcnt_pool[pool_idx];
   3429         num_ctr = soc_mem_index_count(unit, fc_pool->mem);
   3430         for (i = 0; i < num_ctr; i++) {
   3431             if (fc_pool->flow_base_index_reference_count[i] != 0){
   3432                 if (fc_pool->associate_profile_group[i] <
   3433                     _BCM_FLOWCNT_PGROUP_BIAS){
   3434                    continue;
   3435                 }
   3436                 if (fc_pool->object[i] != l_object) {
   3437                    continue;
   3438                 }
   3439                 profile_group = fc_pool->associate_profile_group[i] -
   3440                                 _BCM_FLOWCNT_PGROUP_BIAS;
   3441                 fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   3442                 group_mode = fc_pgroup->group_mode;
   3443                 _bcm_esw_flowcnt_counter_id_set(
   3444                              group_mode,
   3445                              l_object,
   3446                              profile_group,
   3447                              pool_idx,
   3448                              i,
   3449                              &stat_counter_id); 
   3450                 if ((all_flag == TRUE) ||
   3451                     ((l_object == object) && (group_mode == group))) {
   3452                     LOG_CLI((BSL_META_U(unit,
   3453                                         "\tstat counter id %d (0x%x) "
   3454                                         "object=%s base index=%d (0x%x)\n"),
   3455                             stat_counter_id,stat_counter_id,
   3456                             oname[l_object],
   3457                             i, i));
   3458                 }
   3459             }
   3460         }
   3461     }
   3462     _FLOWCNT_UNLOCK(fc);
   3463     return BCM_E_NONE;
   3464 }
   3465 
   3466 /*
   3467  * Function:
   3468  *      _bcm_esw_flowcnt_counter_raw_set
   3469  * Description:
   3470  *      Set Flex Counter Values
   3471  * Parameters:
   3472  *      unit                  - (IN) unit number
   3473  *      stat_counter_id       - (IN) Stat Counter Id
   3474  *      byte_flag             - (IN) Byte/Packet Flag
   3475  *      counter               - (IN) Counter Index
   3476  *      values                - (IN) Counter Value
   3477  *
   3478  * Return Value:
   3479  *      BCM_E_XXX
   3480  * Notes: Must be called carefully.
   3481  *        Preference should be given to _bcm_esw_flowcnt_counter_set()
   3482  */
   3483 int _bcm_esw_flowcnt_counter_raw_set(
   3484             int              unit,
   3485             uint32           stat_counter_id,
   3486             uint32           byte_flag,
   3487             uint32           counter_index,
   3488             bcm_stat_value_t *value)
   3489 {
   3490     _bcm_esw_flowcnt_control_t *fc = NULL;
   3491     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   3492     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   3493     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   3494     bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle;
   3495     bcm_stat_object_t object = bcmStatObjectIngPort;
   3496     uint32  profile_group, pool_index, base_index;
   3497     int profile_index, pool_idx, total_entries, offset_index;
   3498     soc_mem_t   counter_mem;
   3499     soc_mem_info_t *memp = NULL;
   3500     void *entry_data = NULL;
   3501     uint32 entry_data_size = 0;
   3502     int rv = BCM_E_NONE;
   3503     uint32 max_packet_mask=0;
   3504     uint64 max_byte_mask;
   3505     uint32 hw_val[2];
   3506 
   3507     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   3508 
   3509     _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode, &object,
   3510                                     &profile_group, &pool_index, &base_index);
   3511 
   3512     if (group_mode >= bcmStatGroupModeCount) {
   3513         /* custom group */
   3514         if ((group_mode - bcmStatGroupModeCount) != profile_group) {
   3515             return BCM_E_PARAM;
   3516         }
   3517     } else {
   3518         BCM_IF_ERROR_RETURN(
   3519             _bcm_esw_flowcnt_stat_group_mode_validate(unit, group_mode));
   3520     }
   3521     BCM_IF_ERROR_RETURN(
   3522         _bcm_esw_flowcnt_stat_object_validate(unit, object));
   3523 
   3524     BCM_IF_ERROR_RETURN(
   3525         _bcm_esw_flowcnt_object_table_map(unit, object, &profile_index,
   3526                                           &pool_idx));
   3527 
   3528     if (pool_idx != pool_index) {
   3529         return BCM_E_INTERNAL;
   3530     }
   3531     _FLOWCNT_LOCK(fc);
   3532     fc_pool = &fc->flowcnt_pool[pool_index];
   3533     fc_profile = &fc->flowcnt_profile[profile_index];
   3534     fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   3535     counter_mem = fc_pool->mem;
   3536     total_entries = fc_pgroup->total_counters;
   3537     offset_index = counter_index;
   3538 
   3539     if (offset_index >= total_entries) {
   3540         LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   3541                   (BSL_META_U(unit,
   3542                               "Wrong OFFSET_INDEX. Must be < Total Counters %d \n"),
   3543                    total_entries));
   3544         _FLOWCNT_UNLOCK(fc);
   3545         return BCM_E_PARAM;
   3546     }
   3547     memp = &SOC_MEM_INFO(unit, counter_mem);
   3548     entry_data_size = WORDS2BYTES(BYTES2WORDS(memp->bytes));
   3549     _FLOWCNT_ALLOC(unit, entry_data, void, entry_data_size,
   3550                "counter table entry", 0, rv);
   3551     if (BCM_FAILURE(rv)){
   3552         _FLOWCNT_UNLOCK(fc);
   3553         return rv;
   3554     }
   3555     if (soc_mem_read(unit,
   3556                      counter_mem,
   3557                      MEM_BLOCK_ANY,
   3558                      base_index+offset_index,
   3559                      entry_data) != BCM_E_NONE){
   3560         _FLOWCNT_UNLOCK(fc);
   3561         _FLOWCNT_FREE(unit, entry_data, 0);
   3562         return BCM_E_INTERNAL;
   3563     }
   3564     COMPILER_64_ZERO(max_byte_mask);
   3565     if (byte_flag == 1) {
   3566         fc_pool->flow_stat_type[base_index+offset_index] =
   3567                     bcmFlowcntStatTypeByte;
   3568 
   3569         /* Mask to possible max values */
   3570         COMPILER_64_AND(value->bytes, max_byte_mask);
   3571         /* Update Soft Copy */
   3572         COMPILER_64_SET(fc_pool->flow_byte_counter[base_index+offset_index],
   3573                         COMPILER_64_HI(value->bytes),
   3574                         COMPILER_64_LO(value->bytes));
   3575         /* Change Read Hw Copy */
   3576         hw_val[0] = COMPILER_64_LO(value->bytes);
   3577         hw_val[1] = COMPILER_64_HI(value->bytes);
   3578         soc_mem_field_set(unit,
   3579                           counter_mem,
   3580                           (uint32 *)entry_data,
   3581                           BYTE_COUNTERf,
   3582                           hw_val);
   3583         soc_mem_field_set(unit,
   3584                           counter_mem,
   3585                           (uint32 *)entry_data,
   3586                           COUNT_BYTEf,
   3587                           &byte_flag);
   3588         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3589                   (BSL_META_U(unit,
   3590                               "Byte Count Value\t:TABLE:%s"
   3591                                "(@Pool:%d ActualOffset%d) : %x:%x \n"),
   3592                    SOC_MEM_UFNAME(unit, counter_mem),
   3593                    pool_index,
   3594                    base_index+offset_index,
   3595                    COMPILER_64_HI(value->bytes),
   3596                    COMPILER_64_LO(value->bytes)));
   3597     } else {
   3598         fc_pool->flow_stat_type[base_index+offset_index] =
   3599                     bcmFlowcntStatTypePacket;
   3600 
   3601         value->packets &= max_packet_mask;
   3602         /* Update Soft Copy */
   3603         fc_pool->flow_packet_counter[base_index+offset_index] = value->packets;
   3604 
   3605         /* Update Soft Copy */
   3606         COMPILER_64_SET(fc_pool->flow_packet64_counter[base_index+offset_index],0,
   3607                          value->packets);
   3608         /* Change Read Hw Copy */
   3609         soc_mem_field_set(unit,
   3610                           counter_mem,
   3611                           (uint32 *)entry_data,
   3612                           PACKET_COUNTERf,
   3613                           &(value->packets));
   3614         soc_mem_field_set(unit,
   3615                           counter_mem,
   3616                           (uint32 *)entry_data,
   3617                           COUNT_BYTEf,
   3618                           &byte_flag);
   3619         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3620                   (BSL_META_U(unit,
   3621                               "Packet Count Value\t:TABLE:%s"
   3622                               "(@Pool:%d ActualOffset%d) : %x \n"),
   3623                    SOC_MEM_UFNAME(unit, counter_mem),
   3624                    pool_index,
   3625                    base_index+offset_index,
   3626                    value->packets));
   3627     }
   3628     /* Update Hw Copy */
   3629     if (soc_mem_write(unit, counter_mem, MEM_BLOCK_ALL,
   3630                       base_index+offset_index,
   3631                       entry_data) != BCM_E_NONE){
   3632         _FLOWCNT_UNLOCK(fc);
   3633         _FLOWCNT_FREE(unit, entry_data, 0);
   3634         return BCM_E_INTERNAL;
   3635     }
   3636     _FLOWCNT_UNLOCK(fc);
   3637     _FLOWCNT_FREE(unit, entry_data, 0);
   3638     return BCM_E_NONE;
   3639 }
   3640 
   3641 /*
   3642  * Function:
   3643  *      _bcm_esw_flowcnt_counter_raw_get
   3644  * Description:
   3645  *      Get Flex Counter Values
   3646  * Parameters:
   3647  *      unit                  - (IN) unit number
   3648  *      sync_mode             - (IN) hwcount is to be synced to sw count
   3649  *      stat_counter_id       - (IN) Stat Counter Id
   3650  *      byte_flag             - (IN) Byte/Packet Flag
   3651  *      counter               - (IN) Counter Index
   3652  *      values                - (OUT) Counter Value
   3653  *
   3654  * Return Value:
   3655  *      BCM_E_XXX
   3656  * Notes: Must be called carefully.
   3657  *        Preference should be given to _bcm_esw_flowcnt_counter_get()
   3658  */
   3659 int _bcm_esw_flowcnt_counter_raw_get(
   3660             int              unit,
   3661             int              sync_mode,
   3662             uint32           stat_counter_id,
   3663             uint32           byte_flag,
   3664             uint32           counter_index,
   3665             bcm_stat_value_t *value)
   3666 {
   3667     _bcm_esw_flowcnt_control_t *fc = NULL;
   3668     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   3669     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   3670     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   3671     bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle;
   3672     bcm_stat_object_t object = bcmStatObjectIngPort;
   3673     uint32  profile_group, pool_index, base_index;
   3674     int profile_index, pool_idx, total_entries, offset_index;
   3675     soc_mem_t   counter_mem;
   3676 
   3677     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   3678 
   3679     _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode, &object,
   3680                                     &profile_group, &pool_index, &base_index);
   3681 
   3682     if (group_mode >= bcmStatGroupModeCount) {
   3683         /* custom group */
   3684         if ((group_mode - bcmStatGroupModeCount) != profile_group) {
   3685             return BCM_E_PARAM;
   3686         }
   3687     } else {
   3688         BCM_IF_ERROR_RETURN(
   3689             _bcm_esw_flowcnt_stat_group_mode_validate(unit, group_mode));
   3690     }
   3691 
   3692     BCM_IF_ERROR_RETURN(
   3693         _bcm_esw_flowcnt_stat_object_validate(unit, object));
   3694 
   3695     BCM_IF_ERROR_RETURN(
   3696         _bcm_esw_flowcnt_object_table_map(unit, object, &profile_index,
   3697                                           &pool_idx));
   3698 
   3699     if (pool_idx != pool_index) {
   3700         return BCM_E_INTERNAL;
   3701     }
   3702 
   3703     _FLOWCNT_LOCK(fc);
   3704     fc_pool = &fc->flowcnt_pool[pool_index];
   3705     fc_profile = &fc->flowcnt_profile[profile_index];
   3706     fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   3707     counter_mem = fc_pool->mem;
   3708     total_entries = fc_pgroup->total_counters;
   3709     offset_index = counter_index;
   3710 
   3711     if (offset_index >= total_entries) {
   3712         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3713                  (BSL_META_U(unit,
   3714                               "Wrong OFFSET_INDEX. Must be < Total Counters %d \n"),
   3715                    total_entries));
   3716         _FLOWCNT_UNLOCK(fc);
   3717         return BCM_E_PARAM;
   3718     }
   3719     if (byte_flag == 1) {
   3720         if (fc_pool->flow_stat_type[base_index+offset_index] !=
   3721             bcmFlowcntStatTypeByte) {
   3722             _FLOWCNT_UNLOCK(fc);
   3723             return BCM_E_PARAM;
   3724         }
   3725     } else {
   3726         if (fc_pool->flow_stat_type[base_index+offset_index] !=
   3727             bcmFlowcntStatTypePacket) {
   3728             _FLOWCNT_UNLOCK(fc);
   3729             return BCM_E_PARAM;
   3730         }
   3731     }
   3732 
   3733     /* sync the software counter with hardware counter */
   3734     if (sync_mode == 1) {
   3735         _bcm_esw_flowcnt_counter_collect(unit,
   3736                                          counter_mem,
   3737                                          base_index + offset_index);
   3738     }
   3739 
   3740     bcm_stat_value_t_init(value);
   3741     if (byte_flag == 1) {
   3742         COMPILER_64_SET(value->bytes,
   3743                         COMPILER_64_HI(fc_pool->
   3744                                        flow_byte_counter
   3745                                        [base_index+offset_index]),
   3746                         COMPILER_64_LO(fc_pool->
   3747                                        flow_byte_counter
   3748                                        [base_index+offset_index]));
   3749         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3750                   (BSL_META_U(unit,
   3751                               "Byte Count Value\t:TABLE:%s "
   3752                               "(@Pool:%d ActualOffset%d) : %x:%x \n"),
   3753                    SOC_MEM_UFNAME(unit, counter_mem),
   3754                    pool_index,
   3755                    base_index+offset_index,
   3756                    COMPILER_64_HI(value->bytes),
   3757                    COMPILER_64_LO(value->bytes)));
   3758     } else {
   3759         value->packets= fc_pool->
   3760                         flow_packet_counter[base_index+offset_index];
   3761         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3762                   (BSL_META_U(unit,
   3763                               "Packet Count Value\t:TABLE:%s "
   3764                               "(@Pool:%dActualOffset%d) : %x \n"),
   3765                    SOC_MEM_UFNAME(unit, counter_mem),
   3766                    pool_index,
   3767                    base_index+offset_index,
   3768                    value->packets));
   3769         COMPILER_64_SET(value->packets64,
   3770                         COMPILER_64_HI(fc_pool->
   3771                                        flow_packet64_counter
   3772                                        [base_index+offset_index]),
   3773                         COMPILER_64_LO(fc_pool->
   3774                                        flow_packet64_counter
   3775                                        [base_index+offset_index]));
   3776         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3777                   (BSL_META_U(unit,
   3778                               "Packet64 Count Value\t:TABLE:%s"
   3779                               "(@Pool:%d ActualOffset%d) : %x:%x \n"),
   3780                    SOC_MEM_UFNAME(unit, counter_mem),
   3781                    pool_index,
   3782                    base_index+offset_index,
   3783                    COMPILER_64_HI(value->packets64),
   3784                    COMPILER_64_LO(value->packets64)));
   3785     }
   3786     _FLOWCNT_UNLOCK(fc);
   3787 
   3788      return BCM_E_NONE;
   3789 }
   3790 
   3791 /*
   3792  * Function:
   3793  *      _bcm_esw_flowcnt_total_counters_get
   3794  * Description:
   3795  *      Get the total counters per profile group (derived from stat_counter_id)
   3796  * Parameters:
   3797  *      unit                - (IN) unit number
   3798  *      stat_counter_id     - (IN) Stat Counter Id
   3799  *      total_counters      - (OUT) Total Counters allocated
   3800  *
   3801  * Return Value:
   3802  *      BCM_E_XXX
   3803  */
   3804 int
   3805 _bcm_esw_flowcnt_total_counters_get(
   3806     int                  unit,
   3807     uint32               stat_counter_id,
   3808     uint32               *total_counters)
   3809 {
   3810     _bcm_esw_flowcnt_control_t *fc = NULL;
   3811     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   3812     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   3813     bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle;
   3814     bcm_stat_object_t object = bcmStatObjectIngPort;
   3815     uint32  profile_group, pool_index, base_index;
   3816     int profile_index, pool_idx;
   3817     int rv = BCM_E_NONE;
   3818 
   3819     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   3820     _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode, &object,
   3821                                     &profile_group, &pool_index, &base_index);
   3822 
   3823     if (group_mode >= bcmStatGroupModeCount) {
   3824         /* custom group */
   3825         if ((group_mode - bcmStatGroupModeCount) != profile_group) {
   3826             return BCM_E_PARAM;
   3827         }
   3828     } else {
   3829         BCM_IF_ERROR_RETURN(
   3830             _bcm_esw_flowcnt_stat_group_mode_validate(unit, group_mode));
   3831     }
   3832 
   3833     BCM_IF_ERROR_RETURN(
   3834         _bcm_esw_flowcnt_object_table_map(unit, object, &profile_index,
   3835                                           &pool_idx));
   3836     if (pool_idx != pool_index) {
   3837         return BCM_E_INTERNAL;
   3838     }
   3839     _FLOWCNT_LOCK(fc);
   3840     fc_profile = &fc->flowcnt_profile[profile_index];
   3841     fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   3842     *total_counters = fc_pgroup->total_counters;
   3843     _FLOWCNT_UNLOCK(fc);
   3844 
   3845     return rv;
   3846 }
   3847 
   3848 #ifdef BCM_WARM_BOOT_SUPPORT
   3849 
   3850 /*
   3851  * Function:
   3852  *      _bcm_esw_flowcnt_sync
   3853  * Description:
   3854  *      Sync flex s/w copy to h/w copy
   3855  * Parameters:
   3856  *      unit                  - (IN) unit number
   3857  * Return Value:
   3858  *      BCM_E_XXX
   3859  * Notes:
   3860  */
   3861 int _bcm_esw_flowcnt_sync(int unit)
   3862 {
   3863     _bcm_flowcnt_warmboot_info_t *flowcnt_wb_info;
   3864     _bcm_flowcnt_warmboot_group_info_t *flowcnt_wb_group_info;
   3865     _bcm_esw_flowcnt_control_t *fc = NULL;
   3866     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   3867     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   3868     int i, j, sel;
   3869     int scache_size = 0;
   3870     int scache_group_mode_num_limit; /* the limit num of group_mode in scache */
   3871 
   3872     LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   3873               (BSL_META_U(unit,
   3874                           "_bcm_esw_flowcnt_sync \n")));
   3875     if ((handle == 0) ||
   3876         (flowcnt_scache_allocated_size[unit] == 0) ||
   3877         (flowcnt_scache_ptr[unit] == NULL)) {
   3878          LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   3879                    (BSL_META_U(unit,
   3880                                "Scache memory was not allocate in init!! \n")));
   3881          return BCM_E_CONFIG;
   3882     }
   3883 
   3884     scache_group_mode_num_limit = FLOWCNT_SCACHE_SIZE_2_RECOVER(unit) / sizeof(uint32);
   3885     if (scache_group_mode_num_limit < bcmStatGroupModeAttrMaxValue) {
   3886         /* in firmware upgrade, the number of group mode maybe increase
   3887          * so dafault_id of some group mode cannot be synced into scache
   3888          */
   3889         LOG_WARN(BSL_LS_BCM_FLEXCTR,
   3890                  (BSL_META_U(unit,
   3891                              "Cannot sync dafault_id after mode id %d\n"),
   3892                              scache_group_mode_num_limit));
   3893     }
   3894 
   3895     scache_size = FLOWCNT_SCACHE_SIZE_1;
   3896     sal_memcpy(&flowcnt_scache_ptr[unit][0], &local_scache_ptr[unit][0],
   3897                scache_size);
   3898 
   3899     flowcnt_wb_info = (_bcm_flowcnt_warmboot_info_t *)
   3900                       (&flowcnt_scache_ptr[unit][0] +
   3901                        scache_size);
   3902     scache_size += FLOWCNT_SCACHE_SIZE_2_LOCAL;
   3903     flowcnt_wb_group_info = (_bcm_flowcnt_warmboot_group_info_t *)
   3904                             (&flowcnt_scache_ptr[unit][0] +
   3905                              scache_size);
   3906 
   3907     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   3908 
   3909     _FLOWCNT_LOCK(fc);
   3910 
   3911     for (i = 0; i < bcmStatGroupModeAttrMaxValue; i ++) {
   3912         if (i >= scache_group_mode_num_limit) {
   3913             break;
   3914         }
   3915         sal_memcpy(&flowcnt_wb_info->default_attr_mode_id[i],
   3916                    &fc->default_attr_mode_id[i],
   3917                    sizeof(uint32));
   3918     }
   3919 
   3920     for (i = 0; i < fc->num_profiles; i++ ){
   3921         fc_profile = &fc->flowcnt_profile[i];
   3922         for (j = 0; j < fc_profile->num_groups; j ++) {
   3923             fc_pgroup = &fc_profile->flowcnt_group[j];
   3924             flowcnt_wb_group_info->group_mode = fc_pgroup->group_mode;
   3925             flowcnt_wb_group_info->flags = fc_pgroup->flags;
   3926             flowcnt_wb_group_info->total_counters = fc_pgroup->total_counters;
   3927             flowcnt_wb_group_info->num_selectors = fc_pgroup->num_selectors;
   3928             for (sel = 0; sel < fc_pgroup->num_selectors; sel ++) {
   3929                 sal_memcpy(&flowcnt_wb_group_info->attr_selectors[sel],
   3930                            &fc_pgroup->attr_selectors[sel],
   3931                            sizeof(_bcm_flowcnt_group_mode_attr_selector_t));
   3932             }
   3933             flowcnt_wb_group_info++;
   3934         }
   3935     }
   3936     _FLOWCNT_UNLOCK(fc);
   3937     return BCM_E_NONE;
   3938 }
   3939 /* 
   3940  * Retrive the total counters per profile group from HW(profile table)
   3941  * NOTE: warmboot purpose
   3942  */
   3943 STATIC int
   3944 _bcm_esw_flowcnt_profile_table_retrieve(
   3945     int unit,
   3946     int profile_index,
   3947     int profile_group)
   3948 {
   3949     soc_mem_t profile_table;
   3950     uint32 entry_data_size = 0;
   3951     uint32 *p_entries = NULL;
   3952     int num_entries, total_counters;
   3953     _bcm_esw_flowcnt_control_t *fc = NULL;
   3954     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   3955     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   3956     uint32 offset_valid, offset;
   3957     int i, rv;
   3958 
   3959     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   3960     _FLOWCNT_LOCK(fc);
   3961     fc_profile = &fc->flowcnt_profile[profile_index];
   3962     fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   3963     profile_table = fc_profile->profile_table;
   3964     num_entries = fc_profile->num_entries;
   3965 
   3966     entry_data_size = sizeof(uint32);
   3967     _FLOWCNT_ALLOC(unit, p_entries, uint32, entry_data_size * num_entries,
   3968                    "temp selectors table src", 1, rv);
   3969 
   3970     rv = soc_mem_read_range(unit, profile_table, MEM_BLOCK_ANY,
   3971                             profile_group * num_entries,
   3972                             (profile_group + 1) * num_entries,
   3973                             p_entries);
   3974     if (BCM_FAILURE(rv)){        
   3975         _FLOWCNT_FREE(unit, p_entries, 1);
   3976         _FLOWCNT_UNLOCK(fc);
   3977         return rv;
   3978     }
   3979     total_counters = 0;
   3980     for (i = 0; i < num_entries; i++ ){
   3981         soc_mem_field_get(unit, profile_table,
   3982                           (uint32 *)&p_entries[i],
   3983                           OFFSET_VALIDf, &offset_valid);
   3984         soc_mem_field_get(unit, profile_table,
   3985                           (uint32 *)&p_entries[i],
   3986                           OFFSETf, &offset);
   3987         if (offset_valid) {
   3988             /* find the max offset */
   3989             if (total_counters < offset) {
   3990                 total_counters = offset;
   3991             }
   3992         }
   3993     }
   3994     /* numbers of counters should be offset +1 */
   3995     fc_pgroup-> total_counters = total_counters + 1;
   3996     _FLOWCNT_FREE(unit, p_entries, 1);
   3997     _FLOWCNT_UNLOCK(fc);
   3998     return BCM_E_NONE;
   3999 }
   4000 
   4001 /* 
   4002  * Retrive the pool, profile_table info from HW(object table)
   4003  * NOTE: warmboot purpose
   4004  */
   4005 STATIC int
   4006 _bcm_esw_flowcnt_warmboot_object_table_retrieve(
   4007     int unit,
   4008     bcm_stat_object_t object,
   4009     soc_mem_t table,
   4010     int min_index,
   4011     int max_index)
   4012 {
   4013     uint32 profile_ptr, base_idx;
   4014     uint32 entry_data_size=0;
   4015     void *entry_data = NULL, *entry_full_data = NULL, *counter_entry_data = NULL;
   4016     uint32 byte_flag;
   4017     soc_mem_t counter_mem;
   4018     int index=0, profile_index, pool_idx;
   4019     int rv;
   4020     _bcm_esw_flowcnt_control_t *fc = NULL;
   4021     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   4022     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   4023     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   4024     
   4025     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc));
   4026 
   4027     rv = _bcm_esw_flowcnt_object_table_map(unit, object,
   4028                                            &profile_index,
   4029                                            &pool_idx);
   4030     if (BCM_FAILURE(rv)){
   4031         return rv;
   4032     }
   4033     _FLOWCNT_LOCK(fc);
   4034     fc_profile = &fc->flowcnt_profile[profile_index];
   4035     fc_pool = &fc->flowcnt_pool[pool_idx];
   4036 
   4037     entry_data_size = WORDS2BYTES(BYTES2WORDS(
   4038                       SOC_MEM_INFO(unit, table).bytes));
   4039     if (max_index > soc_mem_index_max(unit, table)) {
   4040         max_index = soc_mem_index_max(unit, table);
   4041     }
   4042     _FLOWCNT_ALLOC(unit, entry_full_data, void, 
   4043                    entry_data_size * (max_index - min_index + 1),
   4044                    "object table", 1, rv);
   4045     if (BCM_FAILURE(rv)){
   4046         _FLOWCNT_UNLOCK(fc);
   4047         return rv;
   4048     }
   4049 
   4050     rv = soc_mem_read_range(unit, table, MEM_BLOCK_ANY,
   4051                             min_index, max_index, entry_full_data);
   4052     if (BCM_FAILURE(rv)) {        
   4053         _FLOWCNT_FREE(unit, entry_full_data, 1);
   4054         _FLOWCNT_UNLOCK(fc);
   4055         return rv;
   4056     }
   4057 
   4058     for(index=0; index <= (max_index - min_index) ; index++) {
   4059         entry_data = soc_mem_table_idx_to_pointer(unit, table,
   4060                                                   void *, entry_full_data,
   4061                                                   index);
   4062         if (soc_mem_field_valid(unit, table, VALIDf)) {
   4063             if (soc_mem_field32_get(unit, table, entry_data,
   4064                 VALIDf) == 0) {
   4065                 continue;
   4066             }
   4067         }
   4068         rv = _bcm_esw_flowcnt_object_table_fields_values_get(
   4069             unit, index, table, entry_data,
   4070             &profile_ptr, &base_idx);
   4071         if (BCM_FAILURE(rv)) {
   4072             _FLOWCNT_FREE(unit, entry_full_data, 1);
   4073             _FLOWCNT_UNLOCK(fc);
   4074             return rv;
   4075         }
   4076         if ((profile_ptr == 0) && (base_idx == 0)) {
   4077              continue;
   4078         }
   4079         fc_pgroup = &fc_profile->flowcnt_group[profile_ptr];
   4080         if (fc_pgroup->available == 0) {
   4081             fc_pgroup->available = 1;
   4082         }
   4083         fc_pool->flow_base_index_reference_count[base_idx]++;
   4084         fc_pool->associate_profile_group[base_idx] = 
   4085                     profile_ptr + _BCM_FLOWCNT_PGROUP_BIAS;
   4086         fc_pool->object[base_idx] = object;
   4087         if (fc_pool->flow_base_index_reference_count[base_idx] == 1) {
   4088             fc_pgroup->reference_count++;
   4089         }
   4090         if (fc_pgroup-> total_counters == 0) {
   4091             /* total_counters should be able recovered by flowcnt_scache_ptr*/
   4092             rv = _bcm_esw_flowcnt_profile_table_retrieve(unit, profile_index, 
   4093                                                          profile_ptr);
   4094             if (BCM_FAILURE(rv)) {
   4095                 _FLOWCNT_UNLOCK(fc);
   4096                 _FLOWCNT_FREE(unit, entry_full_data, 1);
   4097                 return rv;
   4098             }
   4099         }
   4100         shr_aidxres_list_reserve_block(
   4101             fc_pool->flowcnt_aidxres_list_handle,
   4102             base_idx,
   4103             fc_pgroup->total_counters);
   4104         fc_pool->pool_stat.used_entries += fc_pgroup->total_counters;
   4105         fc_pool->pool_stat.attached_entries += fc_pgroup->total_counters;
   4106 
   4107         counter_mem = fc_pool->mem; 
   4108         entry_data_size = WORDS2BYTES(BYTES2WORDS(
   4109                           SOC_MEM_INFO(unit, counter_mem).bytes));
   4110         _FLOWCNT_ALLOC(unit, counter_entry_data, void, entry_data_size,
   4111                        "counter table entry", 0, rv);
   4112         if (BCM_FAILURE(rv)){
   4113             _FLOWCNT_UNLOCK(fc);
   4114             _FLOWCNT_FREE(unit, entry_full_data, 1);
   4115             return rv;
   4116         }
   4117 
   4118         if (soc_mem_read(unit,
   4119                          counter_mem,
   4120                          MEM_BLOCK_ANY,
   4121                          base_idx,
   4122                          counter_entry_data) != BCM_E_NONE){
   4123             _FLOWCNT_UNLOCK(fc);
   4124             _FLOWCNT_FREE(unit, entry_full_data, 1);
   4125             return BCM_E_INTERNAL;
   4126         }
   4127 
   4128         soc_mem_field_get(unit,
   4129                           counter_mem,
   4130                           (uint32 *)counter_entry_data,
   4131                           COUNT_BYTEf,
   4132                           &byte_flag);
   4133                 
   4134         if (byte_flag){
   4135             fc_pool->flow_stat_type[base_idx]= bcmFlowcntStatTypeByte;
   4136         } else {
   4137             fc_pool->flow_stat_type[base_idx] = bcmFlowcntStatTypePacket;
   4138         }
   4139         LOG_DEBUG(BSL_LS_BCM_FLEXCTR,
   4140                   (BSL_META_U(unit,
   4141                               "Table:%s index=%d mode:%d pool_number:%d "
   4142                               "base_idx:%d\n"),
   4143                    SOC_MEM_UFNAME(unit, table),
   4144                    index+min_index, profile_ptr, pool_idx, base_idx));
   4145     }
   4146     _FLOWCNT_UNLOCK(fc);
   4147     _FLOWCNT_FREE(unit, entry_full_data, 1);
   4148     _FLOWCNT_FREE(unit, counter_entry_data, 0);
   4149     return BCM_E_NONE;
   4150 }
   4151 #define _BCM_FLOWCNT_WARMBOOT_READ_CHUNK 256
   4152 STATIC int
   4153 _bcm_esw_flowcnt_warmboot_object_retrive(int unit)
   4154 {
   4155     int i, rv = BCM_E_NONE;
   4156     uint32 index = 0;
   4157     bcm_stat_object_t object;
   4158     soc_mem_t table;
   4159     for (i = 0; valid_stat_object_list[unit][i].object != -1; i++) {
   4160         table =  valid_stat_object_list[unit][i].object_mem;
   4161         object = valid_stat_object_list[unit][i].object;
   4162         index = 0;
   4163 
   4164         if (soc_mem_index_max(unit, table) < 0) {
   4165             continue;
   4166         }
   4167 
   4168         do {
   4169             rv = _bcm_esw_flowcnt_warmboot_object_table_retrieve(
   4170                     unit, object, table, index, 
   4171                     (index + _BCM_FLOWCNT_WARMBOOT_READ_CHUNK - 1));
   4172             if (BCM_FAILURE(rv)) {
   4173                 return rv;
   4174             }
   4175             index += _BCM_FLOWCNT_WARMBOOT_READ_CHUNK;
   4176         } while (index < soc_mem_index_count(unit,table));
   4177     }
   4178     return rv;
   4179 }
   4180 STATIC int 
   4181 _bcm_esw_flowcnt_warmboot_info_recover(int unit, uint8 *scache_ptr)
   4182 {
   4183     _bcm_esw_flowcnt_control_t *fc = NULL;
   4184     _bcm_esw_flowcnt_profile_t *fc_profile = NULL;
   4185     _bcm_esw_flowcnt_profile_group_t *fc_pgroup = NULL;
   4186     _bcm_esw_flowcnt_pool_t *fc_pool = NULL;
   4187     _bcm_flowcnt_warmboot_info_t *flowcnt_wb_info;
   4188     _bcm_flowcnt_warmboot_group_info_t *flowcnt_wb_group_info;
   4189     int i, j, sel;
   4190     uint32 stat_counter_id;
   4191     bcm_stat_group_mode_t group_mode = bcmStatGroupModeSingle;
   4192     bcm_stat_object_t object = bcmStatObjectIngPort;
   4193     uint32  profile_group, pool_index, base_index;
   4194     int profile_index, pool_idx;
   4195     uint32 total_counters;
   4196     int rv;
   4197     int scache_size = 0;
   4198     int scache_group_mode_num; /* the num of group_mode in scache */
   4199     uint32 *ptr = (uint32 *)scache_ptr;
   4200 
   4201     if (flowcnt_scache_allocated_size[unit] == 0) {
   4202          LOG_ERROR(BSL_LS_BCM_FLEXCTR,
   4203                    (BSL_META_U(unit,
   4204                                "allocated size error\n")));
   4205          return BCM_E_CONFIG;
   4206     }
   4207     
   4208     scache_size = FLOWCNT_SCACHE_SIZE_1;
   4209     flowcnt_wb_info = (_bcm_flowcnt_warmboot_info_t *)
   4210                        (scache_ptr + scache_size);
   4211     scache_group_mode_num = FLOWCNT_SCACHE_SIZE_2_RECOVER(unit) / sizeof(uint32);
   4212     scache_size += FLOWCNT_SCACHE_SIZE_2_RECOVER(unit);
   4213     flowcnt_wb_group_info = (_bcm_flowcnt_warmboot_group_info_t *)
   4214                              (scache_ptr + scache_size);
   4215 
   4216     BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_control_get(unit, &fc)); 
   4217     _FLOWCNT_LOCK(fc); 
   4218 
   4219     if (_bcm_esw_stat_sync_version_above_equal(unit,BCM_WB_VERSION_1_3)) {
   4220         LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
   4221                     (BSL_META_U(unit,
   4222                                 "NEW Version\n")));
   4223         for (i = 0; i < bcmStatGroupModeAttrMaxValue; i ++){
   4224             if (i >= scache_group_mode_num) {
   4225                 break;
   4226             }
   4227             sal_memcpy(&fc->default_attr_mode_id[i],
   4228                        &flowcnt_wb_info->default_attr_mode_id[i],
   4229                        sizeof(uint32));
   4230         }
   4231 
   4232         for (i = 0; i < fc->num_profiles; i++ ){
   4233             fc_profile = &fc->flowcnt_profile[i];
   4234             for (j = 0; j < fc_profile->num_groups; j ++) {
   4235                 fc_pgroup = &fc_profile->flowcnt_group[j];
   4236                 fc_pgroup->group_mode = flowcnt_wb_group_info->group_mode;
   4237                 fc_pgroup->flags = flowcnt_wb_group_info->flags;
   4238                 fc_pgroup->total_counters = flowcnt_wb_group_info->total_counters;
   4239                 fc_pgroup->num_selectors = flowcnt_wb_group_info->num_selectors;
   4240                 if (fc_pgroup->num_selectors) {
   4241                     fc_pgroup->available = 1;
   4242                     rv = soc_profile_mem_reference(unit,
   4243                                                    &fc_profile->profile_mem,
   4244                                                    j*fc_profile->num_entries,
   4245                                                    1);
   4246                     if (BCM_FAILURE(rv)){
   4247                         _FLOWCNT_UNLOCK(fc);
   4248                         return rv;
   4249                     }
   4250                     _FLOWCNT_ALLOC(unit, fc_pgroup->attr_selectors,
   4251                                    _bcm_flowcnt_group_mode_attr_selector_t,
   4252                                    fc_pgroup->num_selectors *
   4253                                    sizeof(_bcm_flowcnt_group_mode_attr_selector_t),
   4254                                    "flowcnt pkt attr per profile group", 0, rv);
   4255                     if (BCM_FAILURE(rv)){
   4256                         _FLOWCNT_UNLOCK(fc);
   4257                         return rv;
   4258                     }
   4259                     for (sel = 0; sel < fc_pgroup->num_selectors; sel ++) {
   4260                         sal_memcpy(&fc_pgroup->attr_selectors[sel],
   4261                                    &flowcnt_wb_group_info->attr_selectors[sel],
   4262                                    sizeof(_bcm_flowcnt_group_mode_attr_selector_t));
   4263                     }
   4264                 }
   4265                 flowcnt_wb_group_info++;
   4266             }
   4267         }
   4268     } else {
   4269         LOG_VERBOSE(BSL_LS_BCM_FLEXCTR,
   4270                     (BSL_META_U(unit,
   4271                                 "OLD Version so skipping NEW FLEX Layout..\n")));
   4272     }
   4273     for (i = 0; i < MAX_FLOWCNT_SCACHE_SIZE; i++) {
   4274         if (ptr[i] != 0) {
   4275             stat_counter_id = ptr[i];
   4276             _bcm_esw_flowcnt_counter_id_get(stat_counter_id, &group_mode,
   4277                                             &object,&profile_group, &pool_index,
   4278                                             &base_index);
   4279             if (_bcm_esw_flowcnt_object_table_map(
   4280                     unit, object, &profile_index, &pool_idx) != BCM_E_NONE){
   4281                 continue;
   4282             }
   4283             fc_profile = &fc->flowcnt_profile[profile_index];
   4284             fc_pgroup = &fc_profile->flowcnt_group[profile_group];
   4285             fc_pool = &fc->flowcnt_pool[pool_idx];
   4286             total_counters = fc_pgroup->total_counters;
   4287             if (total_counters == 0) {
   4288                 continue;
   4289             }
   4290             shr_aidxres_list_reserve_block(
   4291                 fc_pool->flowcnt_aidxres_list_handle,
   4292                 base_index,
   4293                 total_counters);
   4294             fc_pool->pool_stat.used_entries += total_counters;
   4295             fc_pgroup->reference_count++;
   4296         }
   4297     }
   4298     _FLOWCNT_UNLOCK(fc);
   4299     return BCM_E_NONE;
   4300 }
   4301 #endif
   4302