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

tsn_stat.c (97426B)


      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  * Purpose:
      8  * Manage chip specific functionality for TSN Statistics implementation on GH2.
      9  */
     10 
     11 #include <sal/core/libc.h>
     12 #include <soc/drv.h>
     13 #include <bcm/error.h>
     14 #include <bcm/types.h>
     15 #include <bcm/tsn.h>
     16 #include <bcm_int/esw/tsn_stat.h>
     17 #include <bcm_int/esw/tsn.h>
     18 #include <bcm_int/esw/tsn_taf.h>
     19 #include <soc/profile_mem.h>
     20 #include <shared/bsl.h>
     21 #include <shared/shr_res_bitmap.h>
     22 
     23 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(BCM_TSN_SUPPORT)
     24 /* TSN stat portcnt table contents for GH2 */
     25 STATIC const tsn_stat_portcnt_table_info_t portcnt_table[] =
     26 {
     27     {bcmTsnStatIngressSrTaggedPackets,
     28         SR_PORT_COUNT_RX_TAGGEDm, COUNTf},
     29     {bcmTsnStatIngressNonLinkLocalPackets,
     30         SR_PORT_COUNT_RXm, COUNTf},
     31     {bcmTsnStatIngressSrWrongLanPackets,
     32         SR_PORT_COUNT_RX_WRONG_LANm, COUNTf},
     33     {bcmTsnStatIngressSrRxErrorPackets,
     34         SR_PORT_COUNT_RX_ERRORm, COUNTf},
     35     {bcmTsnStatIngressSrTagErrorPackets,
     36         SR_PORT_COUNT_RX_TAG_ERRORm, COUNTf},
     37     {bcmTsnStatIngressSrDuplicatePackets,
     38         SR_PORT_COUNT_RX_DUPLICATESm, COUNTf},
     39     {bcmTsnStatIngressSrOutOfOrderSrPackets,
     40         SR_PORT_COUNT_RX_OUTOFORDERm, COUNTf},
     41     {bcmTsnStatIngressSrOwnRxPackets,
     42         SR_PORT_COUNT_OWN_RXm, COUNTf},
     43     {bcmTsnStatIngressSrUnexpectedPackets,
     44         SR_PORT_COUNT_UNEXPECTED_FRAMEm, COUNTf},
     45     {bcmTsnStatIngressMtuErrorPackets,
     46         SR_PORT_MTU_ERRORm, COUNTf},
     47     {bcmTsnStatIngressStuErrorPackets,
     48         SR_PORT_STU_ERRORm, COUNTf},
     49     {bcmTsnStatIngressSrAcceptedSrPackets,
     50         SR_PORT_COUNT_RX_PASSEDm, COUNTf},
     51     {bcmTsnStatIngressSrSaSrcFilteredPackets,
     52         SR_PORT_PROXY_MAC_ERRORm, COUNTf},
     53     {bcmTsnStatEgressSrTaggedPackets,
     54         SR_PORT_COUNT_TX_TAGGEDm, COUNTf},
     55     {bcmTsnStatEgressNonLinkLocalPackets,
     56         SR_PORT_COUNT_TXm, COUNTf},
     57     {bcmTsnStatEgressMtuErrorPackets,
     58         SR_PORT_TX_MTU_ERRORm, COUNTf},
     59     {bcmTsnStatEgressStuErrorPackets,
     60         SR_PORT_TX_STU_ERRORm, COUNTf}
     61 };
     62 
     63 #define GH2_TSN_STAT_PORTCNT_TABLE_SIZE  (COUNTOF(portcnt_table))
     64 
     65 /* TSN stat flowcnt table contents for GH2 */
     66 STATIC const soc_mem_t flowcnt_group_mem[bcmTsnStatGroupTypeCount] =
     67                            {SR_ING_COUNTER_PROFILEm,
     68                             SR_EGR_COUNTER_PROFILEm};
     69 STATIC const uint32 flowcnt_group_num[bcmTsnStatGroupTypeCount] = {8, 8};
     70 STATIC const soc_mem_t flowcnt_flow_mem[bcmTsnStatGroupTypeCount] =
     71                            {SR_FLOW_ING_COUNTER_CONTROLm,
     72                             SR_FLOW_EGR_COUNTER_CONTROLm};
     73 STATIC const uint32 flowcnt_flow_num[bcmTsnStatGroupTypeCount] = {8192, 8192};
     74 STATIC const soc_field_t flowcnt_flow_profile_field[bcmTsnStatGroupTypeCount] =
     75                              {SR_ING_COUNTER_PROFILEf,
     76                               SR_EGR_COUNTER_PROFILEf};
     77 STATIC const soc_mem_t flowcnt_pool_mem[bcmTsnStatGroupTypeCount]
     78                                        [bcmTsnStatCount] =
     79                            {{SR_FLOW_COUNT_POOL0m, SR_FLOW_COUNT_POOL1m,
     80                              SR_FLOW_COUNT_POOL2m, SR_FLOW_COUNT_POOL3m,
     81                              SR_FLOW_COUNT_POOL4m, SR_FLOW_COUNT_POOL5m,
     82                              SR_FLOW_COUNT_POOL6m, SR_FLOW_COUNT_POOL7m},
     83                             {EGR_SR_FLOW_COUNT_POOL0m,
     84                              EGR_SR_FLOW_COUNT_POOL1m}};
     85 
     86 STATIC const uint32 flowcnt_pool_num[bcmTsnStatGroupTypeCount] = {8, 2};
     87 STATIC uint32 flowcnt_enable_value_mapping_cnt[SOC_MAX_NUM_DEVICES]
     88                                               [bcmTsnStatGroupTypeCount];
     89 STATIC const bcm_tsn_stat_t flowcnt_enable_value_mapping
     90                                 [bcmTsnStatGroupTypeCount][bcmTsnStatCount] =
     91                                     {{bcmTsnStatIngressSrSaSrcFilteredPackets,
     92                                       bcmTsnStatIngressSrAcceptedSrPackets,
     93                                       bcmTsnStatCount /* bit 2: reserved  */ ,
     94                                       bcmTsnStatIngressStuErrorPackets,
     95                                       bcmTsnStatIngressMtuErrorPackets,
     96                                       bcmTsnStatIngressSrUnexpectedPackets,
     97                                       bcmTsnStatIngressSrOwnRxPackets,
     98                                       bcmTsnStatIngressSrOutOfOrderSrPackets,
     99                                       bcmTsnStatCount/* bit 8: reserved */,
    100                                       bcmTsnStatIngressSrDuplicatePackets,
    101                                       bcmTsnStatIngressSrTagErrorPackets,
    102                                       bcmTsnStatIngressSrRxErrorPackets,
    103                                       bcmTsnStatIngressSrWrongLanPackets,
    104                                       bcmTsnStatIngressNonLinkLocalPackets,
    105                                       bcmTsnStatIngressSrTaggedPackets,
    106                                       bcmTsnStatIngressTafMtuPass,
    107                                       bcmTsnStatIngressTafGatePass,
    108                                       bcmTsnStatIngressTafGateCloseDrop,
    109                                       bcmTsnStatIngressTafGateNoByteDrop,
    110                                       bcmTsnStatIngressTafMeterDrop},
    111                                      {bcmTsnStatEgressStuErrorPackets,
    112                                       bcmTsnStatEgressMtuErrorPackets,
    113                                       bcmTsnStatEgressNonLinkLocalPackets,
    114                                       bcmTsnStatEgressSrTaggedPackets}};
    115 /*
    116  * sw database for flowcnt : counter
    117  */
    118 STATIC uint64 *flowcnt_counter_sw[SOC_MAX_NUM_DEVICES]
    119                                  [bcmTsnStatGroupTypeCount][bcmTsnStatCount];
    120 STATIC uint64 *flowcnt_counter_hw[SOC_MAX_NUM_DEVICES]
    121                                  [bcmTsnStatGroupTypeCount][bcmTsnStatCount];
    122 
    123 STATIC uint8 *flowcnt_counter_dma_buffer[SOC_MAX_NUM_DEVICES]
    124                                         [bcmTsnStatGroupTypeCount];
    125 STATIC uint64 flowcnt_counter_max[SOC_MAX_NUM_DEVICES]
    126                                  [bcmTsnStatGroupTypeCount][bcmTsnStatCount];
    127 STATIC uint64 flowcnt_counter_mask[SOC_MAX_NUM_DEVICES]
    128                                   [bcmTsnStatGroupTypeCount][bcmTsnStatCount];
    129 
    130 /*
    131  * sw database for flowcnt : group
    132  */
    133 STATIC soc_profile_mem_t *flowcnt_group_mem_profile[SOC_MAX_NUM_DEVICES]
    134                                                    [bcmTsnStatGroupTypeCount];
    135 /* for each group, mapping between statType and pool_id */
    136 STATIC int32 **flowcnt_group_stat2pool[SOC_MAX_NUM_DEVICES]
    137                                       [bcmTsnStatGroupTypeCount];
    138 
    139 /* the relationship between "statType" and "flow_id bitmap"
    140  *  ex. Given a specific statType,
    141  *      1. we can traverse and find which groupId contains this statType
    142  *      2. Then we can get flow_id bitmap attached to this groupId
    143  *        (1. is impacted when the group's enable_value changes)
    144  *        (2. is impacted when flow attach/detach the group)
    145  *
    146  *  If we want to keep the cache between "statType" and "flow_id bitmap"
    147  *  we need to update the cache value when event 1 or 2 occurs.
    148  *  However before the user wants to change group's enable_value,
    149  *  he/she needs to detach all flows that attached to this group first.
    150  *  According to this assumption, we only need to care about event 2.
    151  */
    152 STATIC SHR_BITDCL *flowcnt_stat_fbmp_cache[SOC_MAX_NUM_DEVICES]
    153                                           [bcmTsnStatGroupTypeCount]
    154                                           [bcmTsnStatCount];
    155 
    156 /*
    157  * sw database for flowcnt : pool
    158  */
    159 STATIC int32 flowcnt_pool_bitmap_alloc_min[SOC_MAX_NUM_DEVICES]
    160                                           [bcmTsnStatGroupTypeCount];
    161 STATIC int32 flowcnt_pool_bitmap_alloc_max[SOC_MAX_NUM_DEVICES]
    162                                           [bcmTsnStatGroupTypeCount];
    163 STATIC shr_res_bitmap_handle_t flowcnt_pool_bitmap[SOC_MAX_NUM_DEVICES]
    164                                                   [bcmTsnStatGroupTypeCount];
    165 STATIC uint8 *flowcnt_mem_entry_buf[SOC_MAX_NUM_DEVICES];
    166 
    167 
    168 typedef int (*bcmi_gh2_tsn_stat_flowcnt_group_traverse_cb)(
    169     int unit,
    170     bcm_tsn_stat_group_type_t group_type,
    171     uint32 group_id,
    172     void *user_data);
    173 
    174 typedef struct bcmi_gh2_tsn_stat_flowcnt_group_traverse_userdata_s {
    175     bcm_tsn_stat_group_traverse_cb cb;
    176     void *cb_user_data;
    177 } bcmi_gh2_tsn_stat_flowcnt_group_traverse_userdata_t;
    178 
    179 /* helper macro */
    180 #define BCMI_TSN_FLOWCNT_MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
    181 #define BCMI_TSN_FLOWCNT_STAT_ID_EGRESS_BIT (20)
    182 #define ERROR_RETURN_WITH_EXTRA_CLEAN(_op_, _extra_clean_) \
    183         do {                                               \
    184             int _rv_ = (_op_);                             \
    185             if (BCM_FAILURE(_rv_)) {                       \
    186                 (_extra_clean_);                           \
    187                 return (_rv_);                             \
    188             }                                              \
    189         } while (0)
    190 
    191 #define INIT_ERROR_RETURN_WITH_CLEAN(_op_)              \
    192         do {                                            \
    193             int _rv_ = (_op_);                          \
    194             if (BCM_FAILURE(_rv_)) {                    \
    195                 bcmi_gh2_tsn_stat_flowcnt_cleanup(unit);\
    196                 return (_rv_);                          \
    197             }                                           \
    198         } while (0)
    199 
    200 #define INIT_ERROR_RETURN_WITH_EXTRA_CLEAN(_op_, _extra_clean_)  \
    201         do {                                                     \
    202             int _rv_ = (_op_);                                   \
    203             if (BCM_FAILURE(_rv_)) {                             \
    204                 (_extra_clean_);                                 \
    205                 bcmi_gh2_tsn_stat_flowcnt_cleanup(unit);         \
    206                 return (_rv_);                                   \
    207             }                                                    \
    208         } while (0)
    209 
    210 #define WRITE_PTR(__ptr__, __type__, __data__)    \
    211         do {                                      \
    212           *((__type__*)(__ptr__)) = (__data__);   \
    213           (__ptr__) += sizeof(__type__);          \
    214         } while (0)
    215 
    216 #define READ_PTR(__ptr__, __type__, __dest__)     \
    217         do {                                      \
    218           (__dest__) = *((__type__*)(__ptr__));   \
    219           (__ptr__) += sizeof(__type__);          \
    220         } while (0)
    221 
    222 
    223 /**************** TSN Stat Threshold ****************/
    224 
    225 /*
    226  * TSN Stat Threshold Select Structure on GH2
    227  */
    228 typedef struct bcmi_gh2_tsn_stat_threshold_select_s {
    229     bcm_tsn_stat_t stat_type;      /* TSN Statistics type */
    230     soc_reg_t reg;                 /* Counter Threshold register */
    231     soc_field_t threshold_field;   /* Counter threshold field */
    232     soc_field_t interrupt_field;   /* Interrupt field */
    233     soc_field_t copy_to_cpu_field; /* Copy to cpu field */
    234 } bcmi_gh2_tsn_stat_threshold_select_t;
    235 
    236 /*
    237  * TSN Stat Threshold Select info structure for Source Port on GH2
    238  */
    239 STATIC const bcmi_gh2_tsn_stat_threshold_select_t
    240     gh2_port_count_threshold_info[] =
    241 {
    242     {bcmTsnStatIngressSrTaggedPackets,
    243         SR_PORT_COUNT_THRESHOLD_RX_TAGGEDr, COUNTER_THRESHOLDf,
    244         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    245     {bcmTsnStatIngressNonLinkLocalPackets,
    246         SR_PORT_COUNT_THRESHOLD_RXr, COUNTER_THRESHOLDf,
    247         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    248     {bcmTsnStatIngressSrWrongLanPackets,
    249         SR_PORT_COUNT_THRESHOLD_RX_WRONG_LANr, COUNTER_THRESHOLDf,
    250         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    251     {bcmTsnStatIngressSrRxErrorPackets,
    252         SR_PORT_COUNT_THRESHOLD_RX_ERRORr, COUNTER_THRESHOLDf,
    253         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    254     {bcmTsnStatIngressSrTagErrorPackets,
    255         SR_PORT_COUNT_THRESHOLD_RX_TAG_ERRORr, COUNTER_THRESHOLDf,
    256         INTERRUPT_ENABLEf, INVALIDf},
    257     {bcmTsnStatIngressSrDuplicatePackets,
    258         SR_PORT_COUNT_THRESHOLD_RX_DUPLICATESr, COUNTER_THRESHOLDf,
    259         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    260     {bcmTsnStatIngressSrOutOfOrderSrPackets,
    261         SR_PORT_COUNT_THRESHOLD_RX_OUTOFORDERr, COUNTER_THRESHOLDf,
    262         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    263     {bcmTsnStatIngressSrOwnRxPackets,
    264         SR_PORT_COUNT_THRESHOLD_OWN_RXr, COUNTER_THRESHOLDf,
    265         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    266     {bcmTsnStatIngressSrUnexpectedPackets,
    267         SR_PORT_COUNT_THRESHOLD_UNEXPECTED_FRAMEr, COUNTER_THRESHOLDf,
    268         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    269     {bcmTsnStatIngressMtuErrorPackets,
    270         SR_PORT_THRESHOLD_MTU_ERRORr, COUNTER_THRESHOLDf,
    271         INTERRUPT_ENABLEf, INVALIDf},
    272     {bcmTsnStatIngressStuErrorPackets,
    273         SR_PORT_THRESHOLD_STU_ERRORr, COUNTER_THRESHOLDf,
    274         INTERRUPT_ENABLEf, INVALIDf},
    275     {bcmTsnStatIngressSrAcceptedSrPackets,
    276         SR_PORT_COUNT_THRESHOLD_RX_PASSEDr, COUNTER_THRESHOLDf,
    277         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    278     {bcmTsnStatIngressSrSaSrcFilteredPackets,
    279         SR_PORT_COUNT_THRESHOLD_PROXY_MAC_ERRORr, COUNTER_THRESHOLDf,
    280         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    281     {bcmTsnStatEgressSrTaggedPackets,
    282         SR_PORT_COUNT_THRESHOLD_TX_TAGGEDr, COUNTER_THRESHOLDf,
    283         INTERRUPT_ENABLEf, INVALIDf},
    284     {bcmTsnStatEgressNonLinkLocalPackets,
    285         SR_PORT_COUNT_THRESHOLD_TXr, COUNTER_THRESHOLDf,
    286         INTERRUPT_ENABLEf, INVALIDf},
    287     {bcmTsnStatEgressMtuErrorPackets,
    288         SR_PORT_THRESHOLD_TX_MTU_ERRORr, COUNTER_THRESHOLDf,
    289         INTERRUPT_ENABLEf, INVALIDf},
    290     {bcmTsnStatEgressStuErrorPackets,
    291         SR_PORT_THRESHOLD_TX_STU_ERRORr, COUNTER_THRESHOLDf,
    292         INTERRUPT_ENABLEf, INVALIDf}
    293 };
    294 
    295 /*
    296  * TSN Stat Threshold Select info structure for Source SR Flow on GH2
    297  */
    298 STATIC const bcmi_gh2_tsn_stat_threshold_select_t
    299     gh2_flow_count_threshold_info[] =
    300 {
    301     {bcmTsnStatIngressSrTaggedPackets,
    302         SR_FLOW_COUNT_THRESHOLD_RX_TAGGEDr, COUNTER_THRESHOLDf,
    303         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    304     {bcmTsnStatIngressNonLinkLocalPackets,
    305         SR_FLOW_COUNT_THRESHOLD_RXr, COUNTER_THRESHOLDf,
    306         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    307     {bcmTsnStatIngressSrWrongLanPackets,
    308         SR_FLOW_COUNT_THRESHOLD_RX_WRONG_LANr, COUNTER_THRESHOLDf,
    309         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    310     {bcmTsnStatIngressSrRxErrorPackets,
    311         SR_FLOW_COUNT_THRESHOLD_RX_ERRORr, COUNTER_THRESHOLDf,
    312         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    313     {bcmTsnStatIngressSrTagErrorPackets,
    314         SR_FLOW_COUNT_THRESHOLD_RX_TAG_ERRORr, COUNTER_THRESHOLDf,
    315         INTERRUPT_ENABLEf, INVALIDf},
    316     {bcmTsnStatIngressSrDuplicatePackets,
    317         SR_FLOW_COUNT_THRESHOLD_RX_DUPLICATESr, COUNTER_THRESHOLDf,
    318         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    319     {bcmTsnStatIngressSrOutOfOrderSrPackets,
    320         SR_FLOW_COUNT_THRESHOLD_RX_OUTOFORDERr, COUNTER_THRESHOLDf,
    321         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    322     {bcmTsnStatIngressSrOwnRxPackets,
    323         SR_FLOW_COUNT_THRESHOLD_OWN_RXr, COUNTER_THRESHOLDf,
    324         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    325     {bcmTsnStatIngressSrUnexpectedPackets,
    326         SR_FLOW_COUNT_THRESHOLD_UNEXPECTED_FRAMEr, COUNTER_THRESHOLDf,
    327         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    328     {bcmTsnStatIngressMtuErrorPackets,
    329         SR_FLOW_THRESHOLD_MTU_ERRORr, COUNTER_THRESHOLDf,
    330         INTERRUPT_ENABLEf, INVALIDf},
    331     {bcmTsnStatIngressStuErrorPackets,
    332         SR_FLOW_THRESHOLD_STU_ERRORr, COUNTER_THRESHOLDf,
    333         INTERRUPT_ENABLEf, INVALIDf},
    334     {bcmTsnStatIngressSrAcceptedSrPackets,
    335         SR_FLOW_COUNT_THRESHOLD_RX_PASSEDr, COUNTER_THRESHOLDf,
    336         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    337     {bcmTsnStatIngressSrSaSrcFilteredPackets,
    338         SR_FLOW_THRESHOLD_PROXY_MAC_ERRORr, COUNTER_THRESHOLDf,
    339         INTERRUPT_ENABLEf, COPY_TO_CPUf},
    340     {bcmTsnStatEgressSrTaggedPackets,
    341         SR_FLOW_COUNT_THRESHOLD_TX_TAGGEDr, COUNTER_THRESHOLDf,
    342         INTERRUPT_ENABLEf, INVALIDf},
    343     {bcmTsnStatEgressNonLinkLocalPackets,
    344         SR_FLOW_COUNT_THRESHOLD_TXr, COUNTER_THRESHOLDf,
    345         INTERRUPT_ENABLEf, INVALIDf},
    346     {bcmTsnStatEgressMtuErrorPackets,
    347         SR_FLOW_THRESHOLD_TX_MTU_ERRORr, COUNTER_THRESHOLDf,
    348         INTERRUPT_ENABLEf, INVALIDf},
    349     {bcmTsnStatEgressStuErrorPackets,
    350         SR_FLOW_THRESHOLD_TX_STU_ERRORr, COUNTER_THRESHOLDf,
    351         INTERRUPT_ENABLEf, INVALIDf}
    352 };
    353 
    354 /* TSN Stat threshold default value for initialization */
    355 #define GH2_TSN_STAT_THRESHOLD_DEFAULT_VALUE  0xffffffff
    356 
    357 /* TSN Stat threshold valid check for SR */
    358 #define GH2_TSN_STAT_THRESHOLD_SR_IS_VALID(unit, type)      \
    359     (soc_feature(unit, soc_feature_tsn_sr) &&               \
    360     ((type >= bcmTsnStatIngressSrTaggedPackets &&           \
    361     type <= bcmTsnStatIngressSrUnexpectedPackets) ||        \
    362     (type >= bcmTsnStatIngressSrAcceptedSrPackets &&        \
    363     type <= bcmTsnStatEgressNonLinkLocalPackets)))
    364 
    365 /* TSN Stat threshold valid check for MTU/STU */
    366 #define GH2_TSN_STAT_THRESHOLD_MTU_STU_IS_VALID(unit, type) \
    367     (soc_feature(unit, soc_feature_tsn_mtu_stu) &&          \
    368     ((type >= bcmTsnStatIngressMtuErrorPackets &&           \
    369     type <= bcmTsnStatIngressStuErrorPackets) ||            \
    370     (type >= bcmTsnStatEgressMtuErrorPackets &&             \
    371     type <= bcmTsnStatEgressStuErrorPackets)))
    372 
    373 /* TSN Stat threshold valid check */
    374 #define GH2_TSN_STAT_THRESHOLD_IS_VALID(unit, type)         \
    375     (GH2_TSN_STAT_THRESHOLD_SR_IS_VALID(unit, type) ||      \
    376     GH2_TSN_STAT_THRESHOLD_MTU_STU_IS_VALID(unit, type))
    377 
    378 /************** End of TSN Stat Threshold **************/
    379 
    380 /* check parameter valid or not */
    381 STATIC int
    382 bcmi_gh2_tsn_stat_flowcnt_group_valid_check(
    383     int unit,
    384     bcm_tsn_stat_group_type_t group_type,
    385     const uint32 *group_id,
    386     const uint32 *group_enable_values)
    387 {
    388     soc_mem_t mem;
    389 
    390     if (group_type < 0 || group_type >= bcmTsnStatGroupTypeCount) {
    391         return BCM_E_PARAM;
    392     }
    393 
    394     mem = flowcnt_group_mem[group_type];
    395     /* check group_id valid */
    396     if (NULL != group_id) {
    397         if (!soc_mem_index_valid(unit, mem, *group_id)) {
    398             return BCM_E_PARAM;
    399         }
    400     }
    401 
    402     /* check group_enable_values valid */
    403     if (NULL != group_enable_values) {
    404         if (0 == *group_enable_values) {
    405             return BCM_E_PARAM;
    406         }
    407         BCM_IF_ERROR_RETURN(soc_mem_field32_fit(unit, mem,
    408                                                 SR_COUNTER_ENABLESf,
    409                                                 *group_enable_values));
    410     }
    411     return BCM_E_NONE;
    412 }
    413 
    414 /* update sw cache : mapping statType to poolId in for some specific group */
    415 STATIC int
    416 bcmi_gh2_tsn_stat_flowcnt_group_update_stat2pool(
    417     int unit,
    418     bcm_tsn_stat_group_type_t group_type,
    419     uint32 group_id,
    420     uint32 group_enable_values)
    421 {
    422     int i, pool_index, enable_values_count_max;
    423     const bcm_tsn_stat_t *enable_values_mapping;
    424 
    425     assert(group_type >= 0 && group_type < bcmTsnStatGroupTypeCount);
    426     assert(group_id < flowcnt_group_num[group_type]);
    427 
    428     /* init flowcnt_group_stat2pool as all invalid first */
    429     for (i = 0; i < bcmTsnStatCount; i++) {
    430         flowcnt_group_stat2pool[unit][group_type][group_id][i] = -1;
    431     }
    432 
    433     enable_values_mapping = flowcnt_enable_value_mapping[group_type];
    434     enable_values_count_max = flowcnt_enable_value_mapping_cnt[unit]
    435                                                               [group_type];
    436 
    437     /* starting from MSB, the first bit that is set to 1 corresponds
    438      * to pool 0, the next bit set to 1 corresponds to pool 1, etc
    439      */
    440     pool_index = 0;
    441     for (i = enable_values_count_max - 1; i >= 0; i--) {
    442         if (group_enable_values & (1 << i)) {
    443             if (bcmTsnStatCount == enable_values_mapping[i]) {
    444                 /* should not happen */
    445                 return BCM_E_INTERNAL;
    446             }
    447             flowcnt_group_stat2pool
    448                 [unit][group_type][group_id]
    449                 [enable_values_mapping[i]] = pool_index;
    450             pool_index++;
    451         }
    452     }
    453 
    454     return BCM_E_NONE;
    455 }
    456 
    457 /* get enable value for a given (group_type+group_id) */
    458 STATIC int
    459 bcmi_gh2_tsn_stat_flowcnt_group_enable_value_get(
    460     int unit,
    461     bcm_tsn_stat_group_type_t group_type,
    462     uint32 group_id,
    463     uint32 *ret_enable_values)
    464 {
    465     soc_mem_t mem;
    466     soc_profile_mem_t *profile_mem;
    467     void *profile_mem_ptr;
    468 
    469     if (NULL == ret_enable_values) {
    470         return BCM_E_PARAM;
    471     }
    472     if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == group_id) {
    473         /* should not query reserved group's enable value */
    474         return BCM_E_PARAM;
    475     }
    476 
    477     BCM_IF_ERROR_RETURN(
    478         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
    479                                                     &group_id, NULL));
    480 
    481     profile_mem = flowcnt_group_mem_profile[unit][group_type];
    482     mem = flowcnt_group_mem[group_type];
    483 
    484     profile_mem_ptr = SOC_PROFILE_MEM_ENTRY(unit, profile_mem,
    485                                             void *, group_id);
    486     *ret_enable_values = soc_mem_field32_get(unit, mem, profile_mem_ptr,
    487                                              SR_COUNTER_ENABLESf);
    488 
    489     return BCM_E_NONE;
    490 }
    491 
    492 /* set enable value for a given (group_type+group_id) */
    493 STATIC int
    494 bcmi_gh2_tsn_stat_flowcnt_group_enable_value_set(
    495     int unit,
    496     bcm_tsn_stat_group_type_t group_type,
    497     uint32 group_id,
    498     uint32 group_enable_values)
    499 {
    500     soc_mem_t mem;
    501     soc_profile_mem_t *profile_mem;
    502     void *entry_buf = flowcnt_mem_entry_buf[unit];
    503     void *entries[1];
    504     int rv = BCM_E_NONE;
    505 
    506     if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == group_id) {
    507         /* should not set reserved group's enable value */
    508         return BCM_E_PARAM;
    509     }
    510 
    511     BCM_IF_ERROR_RETURN(
    512         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type, &group_id,
    513                                                     &group_enable_values));
    514     profile_mem = flowcnt_group_mem_profile[unit][group_type];
    515     mem = flowcnt_group_mem[group_type];
    516 
    517     sal_memset(entry_buf, 0, WORDS2BYTES(soc_mem_entry_words(unit, mem)));
    518     soc_mem_field32_set(unit, mem, entry_buf,
    519                         SR_COUNTER_ENABLESf, group_enable_values);
    520 
    521     entries[0] = entry_buf;
    522     rv = soc_profile_mem_set(unit, profile_mem, entries, group_id);
    523     BCM_IF_ERROR_RETURN(rv);
    524 
    525     BCM_IF_ERROR_RETURN(
    526         bcmi_gh2_tsn_stat_flowcnt_group_update_stat2pool(
    527             unit, group_type, group_id, group_enable_values));
    528 
    529     return BCM_E_NONE;
    530 }
    531 
    532 /* find enable value in one specific group
    533  * return BCM_E_NONE : not exited
    534  * return BCM_E_EXISTS : has already exited
    535  */
    536 STATIC int
    537 bcmi_gh2_tsn_stat_flowcnt_group_enable_value_exist_check(
    538     int unit,
    539     bcm_tsn_stat_group_type_t group_type,
    540     uint32 find_enable_values)
    541 {
    542     soc_mem_t mem;
    543     soc_profile_mem_t *profile_mem;
    544     int idx;
    545 
    546     BCM_IF_ERROR_RETURN(
    547         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
    548                                                     NULL, NULL));
    549     profile_mem = flowcnt_group_mem_profile[unit][group_type];
    550     mem = flowcnt_group_mem[group_type];
    551 
    552     for (idx = 0; idx < flowcnt_group_num[group_type]; idx++) {
    553         void *profile_mem_ptr;
    554         uint32 enable_values;
    555         int ref_count;
    556 
    557         if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == idx) {
    558             continue;
    559         }
    560         BCM_IF_ERROR_RETURN(
    561             soc_profile_mem_ref_count_get(unit, profile_mem, idx, &ref_count));
    562         if (0 == ref_count) {
    563             /* just need to find the enable value "in use",
    564              * so skip the entry with ref_cnt = 0
    565              */
    566             continue;
    567         }
    568         profile_mem_ptr = SOC_PROFILE_MEM_ENTRY(unit, profile_mem, void *, idx);
    569         enable_values = soc_mem_field32_get(unit, mem, profile_mem_ptr,
    570                                             SR_COUNTER_ENABLESf);
    571         if (enable_values == find_enable_values) {
    572             return BCM_E_EXISTS;
    573         }
    574     }
    575     return BCM_E_NONE;
    576 }
    577 
    578 /* add a enable value into the given group, and return the new added group_id */
    579 STATIC int
    580 bcmi_gh2_tsn_stat_flowcnt_group_enable_value_insert(
    581     int unit,
    582     bcm_tsn_stat_group_type_t group_type,
    583     uint32 insert_enable_values,
    584     uint32 *ret_group_id)
    585 {
    586     soc_mem_t mem;
    587     soc_profile_mem_t *profile_mem;
    588     void *entry_buf = flowcnt_mem_entry_buf[unit];
    589     int group_id;
    590 
    591     if (NULL == ret_group_id) {
    592         return BCM_E_PARAM;
    593     }
    594 
    595     BCM_IF_ERROR_RETURN(
    596         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type, NULL,
    597                                                     &insert_enable_values));
    598     profile_mem = flowcnt_group_mem_profile[unit][group_type];
    599     mem = flowcnt_group_mem[group_type];
    600     /* check the new value not duplicate  */
    601     BCM_IF_ERROR_RETURN(
    602         bcmi_gh2_tsn_stat_flowcnt_group_enable_value_exist_check(
    603             unit, group_type, insert_enable_values));
    604 
    605     /* insert */
    606     sal_memset(entry_buf, 0, WORDS2BYTES(soc_mem_entry_words(unit, mem)));
    607     soc_mem_field32_set(unit, mem, entry_buf,
    608                         SR_COUNTER_ENABLESf, insert_enable_values);
    609 
    610     BCM_IF_ERROR_RETURN(
    611         soc_profile_mem_single_table_add(unit, profile_mem, entry_buf,
    612                                          1, &group_id));
    613     BCM_IF_ERROR_RETURN(
    614         bcmi_gh2_tsn_stat_flowcnt_group_update_stat2pool(
    615             unit, group_type, group_id, insert_enable_values));
    616 
    617     *ret_group_id = (uint32)group_id;
    618 
    619     return BCM_E_NONE;
    620 }
    621 
    622 /* delete a enable value from the given group */
    623 STATIC int
    624 bcmi_gh2_tsn_stat_flowcnt_group_enable_value_delete(
    625     int unit,
    626     bcm_tsn_stat_group_type_t group_type,
    627     uint32 group_id)
    628 {
    629     soc_profile_mem_t *profile_mem;
    630     if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == group_id) {
    631         /* should not delete reserved group's enable value */
    632         return BCM_E_PARAM;
    633     }
    634 
    635     BCM_IF_ERROR_RETURN(
    636         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
    637                                                     &group_id, NULL));
    638     profile_mem = flowcnt_group_mem_profile[unit][group_type];
    639 
    640     BCM_IF_ERROR_RETURN(
    641         soc_profile_mem_delete(unit, profile_mem, group_id));
    642 
    643     BCM_IF_ERROR_RETURN(
    644         bcmi_gh2_tsn_stat_flowcnt_group_update_stat2pool(
    645             unit, group_type, group_id, 0));
    646 
    647     return BCM_E_NONE;
    648 }
    649 
    650 /* encode multiple stat types to a enable_values */
    651 STATIC int
    652 bcmi_gh2_tsn_stat_flowcnt_group_enable_value_encode(
    653     int unit,
    654     bcm_tsn_stat_group_type_t group_type,
    655     bcm_tsn_stat_t *stat_arr,
    656     uint32 stat_arr_cnt,
    657     uint32 *ret_enable_values)
    658 {
    659     int i, j, enable_values_count_limit, enable_values_count_max;
    660     const bcm_tsn_stat_t *enable_values_mapping;
    661 
    662     if (NULL == ret_enable_values || NULL == stat_arr) {
    663         return BCM_E_PARAM;
    664     }
    665 
    666     BCM_IF_ERROR_RETURN(
    667         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
    668                                                     NULL, NULL));
    669 
    670     enable_values_count_limit = flowcnt_pool_num[group_type];
    671     enable_values_count_max = flowcnt_enable_value_mapping_cnt[unit]
    672                                                               [group_type];
    673     enable_values_mapping = flowcnt_enable_value_mapping[group_type];
    674 
    675     if (stat_arr_cnt <= 0 || stat_arr_cnt > enable_values_count_limit) {
    676         return BCM_E_PARAM;
    677     }
    678 
    679     *ret_enable_values = 0;
    680     for (i = 0; i < stat_arr_cnt; i++) {
    681         int found_out = 0;
    682 
    683         if (bcmTsnStatCount == stat_arr[i]) {
    684             return BCM_E_PARAM;
    685         }
    686         for (j = 0; j < enable_values_count_max; j++) {
    687             if (stat_arr[i] == enable_values_mapping[j]) {
    688                 *ret_enable_values |= (1 << j);
    689                 found_out = 1;
    690                 break;
    691             }
    692         }
    693         if (0 == found_out) {
    694             return BCM_E_PARAM;
    695         }
    696     }
    697     if (0 == *ret_enable_values) {
    698         return BCM_E_PARAM;
    699     }
    700 
    701     return BCM_E_NONE;
    702 }
    703 
    704 /* decode enable_values to multiple stat types */
    705 STATIC int
    706 bcmi_gh2_tsn_stat_flowcnt_group_enable_value_decode(
    707     int unit,
    708     bcm_tsn_stat_group_type_t group_type,
    709     uint32 enable_values,
    710     bcm_tsn_stat_t *stat_arr,
    711     uint32 stat_arr_len,
    712     int *ret_stat_arr_cnt)
    713 {
    714     int write_ptr, i, enable_values_count_max, actual_count;
    715     const bcm_tsn_stat_t *enable_values_mapping;
    716 
    717     if (0 == enable_values || NULL == ret_stat_arr_cnt) {
    718         return BCM_E_PARAM;
    719     }
    720 
    721     if (0 == stat_arr_len) {
    722         /* user just want to get the "needed count"
    723          * for returned ret_stat_arr_cnt
    724          * so need not check stat_arr here
    725          */
    726     } else {
    727         /* user want we write the result into stat_arr
    728          * and get "written count" for returned ret_stat_arr_cnt
    729          */
    730         if (NULL == stat_arr) {
    731             return BCM_E_PARAM;
    732         }
    733     }
    734 
    735     BCM_IF_ERROR_RETURN(
    736         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
    737                                                     NULL, NULL));
    738 
    739     enable_values_mapping = flowcnt_enable_value_mapping[group_type];
    740     enable_values_count_max = flowcnt_enable_value_mapping_cnt[unit]
    741                                                               [group_type];
    742 
    743     write_ptr = 0;
    744     actual_count = 0;
    745     for (i = 0; i < enable_values_count_max; i++) {
    746         if (enable_values & (1 << i)) {
    747             if (write_ptr < stat_arr_len) {
    748                 stat_arr[write_ptr] = enable_values_mapping[i];
    749                 write_ptr++;
    750             }
    751             actual_count++;
    752         }
    753     }
    754     if (0 == stat_arr_len) {
    755         *ret_stat_arr_cnt = actual_count;
    756     } else {
    757         *ret_stat_arr_cnt = write_ptr;
    758     }
    759     return BCM_E_NONE;
    760 }
    761 
    762 /* set the reference count for the given group_id in one group */
    763 STATIC int
    764 bcmi_gh2_tsn_stat_flowcnt_group_refcnt_set(
    765     int unit,
    766     bcm_tsn_stat_group_type_t group_type,
    767     uint32 group_id,
    768     int refcnt_diff)
    769 {
    770     soc_profile_mem_t *profile_mem;
    771     if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == group_id) {
    772         /* should not modify reserved group's ref count */
    773         return BCM_E_PARAM;
    774     }
    775 
    776     BCM_IF_ERROR_RETURN(
    777         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
    778                                                     &group_id, NULL));
    779     profile_mem = flowcnt_group_mem_profile[unit][group_type];
    780     SOC_PROFILE_MEM_REFERENCE(unit, profile_mem, group_id, refcnt_diff);
    781     return BCM_E_NONE;
    782 }
    783 
    784 /* get the reference count for the given group_id in one group */
    785 STATIC int
    786 bcmi_gh2_tsn_stat_flowcnt_group_refcnt_get(
    787     int unit,
    788     bcm_tsn_stat_group_type_t group_type,
    789     uint32 group_id,
    790     int *ret_refcnt)
    791 {
    792     soc_profile_mem_t *profile_mem;
    793     if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == group_id) {
    794         /* should not modify reserved group's ref count */
    795         return BCM_E_PARAM;
    796     }
    797 
    798     BCM_IF_ERROR_RETURN(
    799         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
    800                                                     &group_id, NULL));
    801     profile_mem = flowcnt_group_mem_profile[unit][group_type];
    802     return soc_profile_mem_ref_count_get(unit, profile_mem, group_id,
    803                                          ret_refcnt);
    804 }
    805 
    806 /* encode "group_type, group_id" to "stat_id" */
    807 STATIC int
    808 bcmi_gh2_tsn_stat_flowcnt_group_id_encode(
    809     int unit,
    810     bcm_tsn_stat_group_type_t group_type,
    811     uint32 group_id,
    812     bcm_tsn_stat_group_t *ret_stat_id)
    813 {
    814     if (NULL == ret_stat_id) {
    815         return BCM_E_PARAM;
    816     }
    817     if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == group_id) {
    818         /* should not encode reserved group's to stat_id */
    819         return BCM_E_PARAM;
    820     }
    821 
    822     BCM_IF_ERROR_RETURN(
    823         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
    824                                                     &group_id, NULL));
    825 
    826     *ret_stat_id = group_id;
    827     if (bcmTsnStatGroupTypeEgress == group_type) {
    828         *ret_stat_id |= (1 << BCMI_TSN_FLOWCNT_STAT_ID_EGRESS_BIT);
    829     }
    830 
    831     return BCM_E_NONE;
    832 }
    833 
    834 /* decode "stat_id" to "group_type, group_id" */
    835 STATIC int
    836 bcmi_gh2_tsn_stat_flowcnt_group_id_decode(
    837     int unit,
    838     bcm_tsn_stat_group_t stat_id,
    839     bcm_tsn_stat_group_type_t *ret_group_type,
    840     uint32 *ret_group_id)
    841 {
    842     if (NULL == ret_group_id || NULL == ret_group_type) {
    843         return BCM_E_PARAM;
    844     }
    845     if (stat_id < 0) {
    846         return BCM_E_PARAM;
    847     }
    848 
    849     if (stat_id & (1 << BCMI_TSN_FLOWCNT_STAT_ID_EGRESS_BIT)) {
    850         *ret_group_type = bcmTsnStatGroupTypeEgress;
    851     } else {
    852         *ret_group_type = bcmTsnStatGroupTypeIngress;
    853     }
    854 
    855     *ret_group_id = stat_id & ((1 << BCMI_TSN_FLOWCNT_STAT_ID_EGRESS_BIT) - 1);
    856 
    857     BCM_IF_ERROR_RETURN(
    858         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, *ret_group_type,
    859                                                     ret_group_id, NULL));
    860     if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == *ret_group_id) {
    861         /* should not decode reserved stat_id */
    862         return BCM_E_PARAM;
    863     }
    864 
    865     return BCM_E_NONE;
    866 }
    867 
    868 /*  for each valid "group_type, group_id", invoke cb with userdata */
    869 STATIC int
    870 bcmi_gh2_tsn_stat_flowcnt_group_internal_traverse(
    871     int unit,
    872     bcmi_gh2_tsn_stat_flowcnt_group_traverse_cb cb,
    873     void *user_data)
    874 {
    875     bcm_tsn_stat_group_type_t group_type;
    876 
    877     if (NULL == cb) {
    878         return BCM_E_PARAM;
    879     }
    880 
    881     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
    882         soc_mem_t mem;
    883         int group_id;
    884 
    885         BCM_IF_ERROR_RETURN(
    886             bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
    887                                                         NULL, NULL));
    888         mem = flowcnt_group_mem[group_type];
    889 
    890         for (group_id = 0; group_id < flowcnt_group_num[group_type];
    891              group_id++) {
    892             uint32 enable_values;
    893             void *entry_buf = flowcnt_mem_entry_buf[unit];
    894 
    895             if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == group_id) {
    896                 continue;
    897             }
    898 
    899             BCM_IF_ERROR_RETURN(
    900                 soc_mem_read(unit, mem, MEM_BLOCK_ANY, group_id, entry_buf));
    901             enable_values = soc_mem_field32_get(unit, mem, entry_buf,
    902                                                 SR_COUNTER_ENABLESf);
    903             if (0 == enable_values) {
    904                 continue;
    905             }
    906             BCM_IF_ERROR_RETURN(cb(unit, group_type, group_id, user_data));
    907         }
    908     }
    909     return BCM_E_NONE;
    910 }
    911 
    912 /* helper function for bcmi_gh2_tsn_stat_flowcnt_group_traverse() */
    913 STATIC int
    914 bcmi_gh2_tsn_stat_flowcnt_group_traverse_cb_user(
    915     int unit,
    916     bcm_tsn_stat_group_type_t group_type,
    917     uint32 group_id,
    918     void *user_data)
    919 {
    920     bcmi_gh2_tsn_stat_flowcnt_group_traverse_userdata_t *ori_user_data;
    921     bcm_tsn_stat_group_t stat_id;
    922 
    923     if (NULL == user_data) {
    924         return BCM_E_PARAM;
    925     }
    926 
    927     ori_user_data =
    928         (bcmi_gh2_tsn_stat_flowcnt_group_traverse_userdata_t *)user_data;
    929     if (NULL == ori_user_data->cb) {
    930         return BCM_E_PARAM;
    931     }
    932 
    933     BCM_IF_ERROR_RETURN(
    934         bcmi_gh2_tsn_stat_flowcnt_group_id_encode(
    935             unit, group_type, group_id, &stat_id));
    936     return ori_user_data->cb(unit, stat_id, ori_user_data->cb_user_data);
    937 }
    938 
    939 #if defined(BCM_WARM_BOOT_SUPPORT)
    940 /* recover mem profile when warm boot */
    941 STATIC int
    942 bcmi_gh2_tsn_stat_flowcnt_group_traverse_cb_recover(
    943     int unit,
    944     bcm_tsn_stat_group_type_t group_type,
    945     uint32 group_id,
    946     void *user_data)
    947 {
    948     soc_profile_mem_t *profile_mem =
    949         flowcnt_group_mem_profile[unit][group_type];
    950     void *buf = SOC_PROFILE_MEM_ENTRY(unit, profile_mem, void *, group_id);
    951     uint32 enable_values;
    952 
    953     BCM_IF_ERROR_RETURN(
    954         soc_profile_mem_sw_state_set(
    955             unit, profile_mem, &buf, 1, group_id));
    956 
    957     enable_values = soc_mem_field32_get(unit, flowcnt_group_mem[group_type],
    958                                         buf, SR_COUNTER_ENABLESf);
    959     BCM_IF_ERROR_RETURN(
    960         bcmi_gh2_tsn_stat_flowcnt_group_update_stat2pool(
    961             unit, group_type, group_id, enable_values));
    962 
    963     return BCM_E_NONE;
    964 }
    965 
    966 STATIC int
    967 bcmi_gh2_tsn_stat_flowcnt_get_scache_size(
    968     int unit, int *size)
    969 {
    970     bcm_tsn_stat_group_type_t group_type;
    971 
    972     if (NULL == size) {
    973         return BCM_E_PARAM;
    974     }
    975     *size = 0;
    976 
    977     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
    978         uint32 pool_index;
    979 
    980         for (pool_index = 0; pool_index < flowcnt_pool_num[group_type];
    981              pool_index++) {
    982 
    983             soc_mem_t mem = flowcnt_pool_mem[group_type][pool_index];
    984             *size += sizeof(uint32) * 2 * soc_mem_index_count(unit, mem);
    985         }
    986     }
    987     return BCM_E_NONE;
    988 }
    989 
    990 /* sync data to scache */
    991 STATIC int
    992 bcmi_gh2_tsn_stat_flowcnt_sync(
    993     int unit, uint8 *scache_ptr)
    994 {
    995     bcm_tsn_stat_group_type_t group_type;
    996 
    997     if (NULL == scache_ptr) {
    998         return BCM_E_PARAM;
    999     }
   1000 
   1001     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1002         uint32 pool_index;
   1003 
   1004         for (pool_index = 0; pool_index < flowcnt_pool_num[group_type];
   1005              pool_index++) {
   1006 
   1007             uint32 entry_index;
   1008             soc_mem_t mem = flowcnt_pool_mem[group_type][pool_index];
   1009 
   1010             for (entry_index = 0;
   1011                  entry_index < soc_mem_index_count(unit, mem);
   1012                  entry_index++) {
   1013 
   1014                 WRITE_PTR(scache_ptr, uint32,
   1015                           COMPILER_64_LO(flowcnt_counter_sw[unit][group_type]
   1016                                                            [pool_index]
   1017                                                            [entry_index]));
   1018                 WRITE_PTR(scache_ptr, uint32,
   1019                           COMPILER_64_HI(flowcnt_counter_sw[unit][group_type]
   1020                                                            [pool_index]
   1021                                                            [entry_index]));
   1022             }
   1023         }
   1024     }
   1025     return BCM_E_NONE;
   1026 }
   1027 
   1028 /* layer-1 warmboot : reload data from hw */
   1029 STATIC int
   1030 bcmi_gh2_tsn_stat_flowcnt_reload_l1(int unit)
   1031 {
   1032     /* if there is no scache, just copy hw counter to sw counter */
   1033     bcm_tsn_stat_group_type_t group_type;
   1034 
   1035     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1036         uint32 pool_index;
   1037 
   1038         for (pool_index = 0; pool_index < flowcnt_pool_num[group_type];
   1039              pool_index++) {
   1040 
   1041             uint32 entry_index;
   1042             soc_mem_t mem = flowcnt_pool_mem[group_type][pool_index];
   1043 
   1044             for (entry_index = 0;
   1045                  entry_index < soc_mem_index_count(unit, mem);
   1046                  entry_index++) {
   1047 
   1048                 COMPILER_64_COPY(flowcnt_counter_sw[unit][group_type]
   1049                                                   [pool_index][entry_index],
   1050                                  flowcnt_counter_hw[unit][group_type]
   1051                                                   [pool_index][entry_index]);
   1052             }
   1053         }
   1054     }
   1055     return BCM_E_NONE;
   1056 }
   1057 
   1058 /* layer-2 warmboot : reload data from scache */
   1059 STATIC int
   1060 bcmi_gh2_tsn_stat_flowcnt_reload_l2(
   1061     int unit, uint8 *scache_ptr)
   1062 {
   1063     bcm_tsn_stat_group_type_t group_type;
   1064 
   1065     if (NULL == scache_ptr) {
   1066         return BCM_E_PARAM;
   1067     }
   1068 
   1069     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1070         uint32 pool_index;
   1071 
   1072         for (pool_index = 0; pool_index < flowcnt_pool_num[group_type];
   1073              pool_index++) {
   1074 
   1075             uint32 entry_index;
   1076             soc_mem_t mem = flowcnt_pool_mem[group_type][pool_index];
   1077 
   1078             for (entry_index = 0;
   1079                  entry_index < soc_mem_index_count(unit, mem);
   1080                  entry_index++) {
   1081 
   1082                 uint32 sec_lo, sec_hi;
   1083 
   1084                 READ_PTR(scache_ptr, uint32, sec_lo);
   1085                 READ_PTR(scache_ptr, uint32, sec_hi);
   1086                 COMPILER_64_SET(flowcnt_counter_sw[unit][group_type]
   1087                                                   [pool_index][entry_index],
   1088                                 sec_hi, sec_lo);
   1089             }
   1090         }
   1091     }
   1092     return BCM_E_NONE;
   1093 }
   1094 
   1095 #endif /* BCM_WARM_BOOT_SUPPORT */
   1096 
   1097 /* traverse TSN stat groups */
   1098 STATIC int
   1099 bcmi_gh2_tsn_stat_flowcnt_group_traverse(
   1100     int unit,
   1101     bcm_tsn_stat_group_traverse_cb cb,
   1102     void *user_data)
   1103 {
   1104     bcmi_gh2_tsn_stat_flowcnt_group_traverse_userdata_t ori_user_data;
   1105     ori_user_data.cb = cb;
   1106     ori_user_data.cb_user_data = user_data;
   1107 
   1108     BCM_IF_ERROR_RETURN(
   1109         bcmi_gh2_tsn_stat_flowcnt_group_internal_traverse(
   1110             unit, bcmi_gh2_tsn_stat_flowcnt_group_traverse_cb_user,
   1111             &ori_user_data));
   1112     return BCM_E_NONE;
   1113 }
   1114 
   1115 /* alloc a index of counter pool
   1116  * if is_index_assign = 0 : parameter "index" is for output a available index
   1117  * if is_index_assign = 1 : parameter "index" is for input, warmboot usage
   1118  */
   1119 STATIC int
   1120 bcmi_gh2_tsn_stat_flowcnt_pool_counter_alloc(
   1121     int unit,
   1122     bcm_tsn_stat_group_type_t group_type,
   1123     int *index,
   1124     int is_index_assign)
   1125 {
   1126     shr_res_bitmap_handle_t pool_bitmap;
   1127     int new_index;
   1128 
   1129     if (index == NULL) {
   1130         return BCM_E_PARAM;
   1131     }
   1132 
   1133     BCM_IF_ERROR_RETURN(
   1134         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
   1135                                                     NULL, NULL));
   1136 
   1137     pool_bitmap = flowcnt_pool_bitmap[unit][group_type];
   1138     if (0 == is_index_assign) {
   1139         /* allocate a new available index */
   1140         BCM_IF_ERROR_RETURN(
   1141             shr_res_bitmap_alloc(pool_bitmap, 0, 1, &new_index));
   1142         *index = new_index;
   1143     } else {
   1144         /* for warm boot, alloc a specified index */
   1145         BCM_IF_ERROR_RETURN(
   1146             shr_res_bitmap_alloc(pool_bitmap,
   1147                                  SHR_RES_BITMAP_ALLOC_WITH_ID, 1,
   1148                                  index));
   1149     }
   1150 
   1151     /* update min/max */
   1152     if (-1 == flowcnt_pool_bitmap_alloc_min[unit][group_type]) {
   1153         flowcnt_pool_bitmap_alloc_min[unit][group_type] = *index;
   1154         flowcnt_pool_bitmap_alloc_max[unit][group_type] = *index;
   1155     } else if (*index < flowcnt_pool_bitmap_alloc_min[unit][group_type]) {
   1156         flowcnt_pool_bitmap_alloc_min[unit][group_type] = *index;
   1157     } else if (*index > flowcnt_pool_bitmap_alloc_max[unit][group_type]) {
   1158         flowcnt_pool_bitmap_alloc_max[unit][group_type] = *index;
   1159     }
   1160 
   1161     return BCM_E_NONE;
   1162 }
   1163 
   1164 /* free the index in counter pool */
   1165 STATIC int
   1166 bcmi_gh2_tsn_stat_flowcnt_pool_counter_free(
   1167     int unit,
   1168     bcm_tsn_stat_group_type_t group_type,
   1169     int index)
   1170 {
   1171     shr_res_bitmap_handle_t pool_bitmap;
   1172 
   1173     BCM_IF_ERROR_RETURN(
   1174         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
   1175                                                     NULL, NULL));
   1176 
   1177     pool_bitmap = flowcnt_pool_bitmap[unit][group_type];
   1178     BCM_IF_ERROR_RETURN(shr_res_bitmap_free(pool_bitmap, 1, index));
   1179 
   1180     /* update min/max */
   1181     if (index == flowcnt_pool_bitmap_alloc_min[unit][group_type] &&
   1182         index == flowcnt_pool_bitmap_alloc_max[unit][group_type]) {
   1183         /* if there is only one index has been allocated
   1184          * (and it is the index that user want to free)
   1185          * let the min/max value back to initial value
   1186          */
   1187         flowcnt_pool_bitmap_alloc_min[unit][group_type] = -1;
   1188         flowcnt_pool_bitmap_alloc_max[unit][group_type] = -1;
   1189     } else if (index == flowcnt_pool_bitmap_alloc_min[unit][group_type]) {
   1190         int new_min;
   1191         int found = 0;
   1192 
   1193         /* ex. the min of allocated index is 3
   1194          *     the max of allocated index is 10
   1195          *     when the user want to free index 3 (which is the min)
   1196          *     we need to find the new min from bitmap
   1197          */
   1198         for (new_min = index + 1;
   1199              new_min <= flowcnt_pool_bitmap_alloc_max[unit][group_type];
   1200              new_min++) {
   1201             int rv;
   1202 
   1203             rv = shr_res_bitmap_check(
   1204                      flowcnt_pool_bitmap[unit][group_type],
   1205                      1, new_min);
   1206             if (BCM_E_EXISTS == rv) {
   1207                 flowcnt_pool_bitmap_alloc_min[unit][group_type] = new_min;
   1208                 found = 1;
   1209                 break;
   1210             }
   1211         }
   1212         if (0 == found) {
   1213             return BCM_E_INTERNAL; /* should not happen */
   1214         }
   1215     } else if (index == flowcnt_pool_bitmap_alloc_max[unit][group_type]) {
   1216         int new_max;
   1217         int found = 0;
   1218 
   1219         /* ex. the min of allocated index is 3
   1220          *     the max of allocated index is 10
   1221          *     when the user want to free index 10 (which is the max)
   1222          *     we need to find the new max from bitmap
   1223          */
   1224         for (new_max = index - 1;
   1225              new_max >= flowcnt_pool_bitmap_alloc_min[unit][group_type];
   1226              new_max--) {
   1227             int rv;
   1228 
   1229             rv = shr_res_bitmap_check(
   1230                      flowcnt_pool_bitmap[unit][group_type],
   1231                      1, new_max);
   1232             if (BCM_E_EXISTS == rv) {
   1233                 flowcnt_pool_bitmap_alloc_max[unit][group_type] = new_max;
   1234                 found = 1;
   1235                 break;
   1236             }
   1237         }
   1238         if (0 == found) {
   1239             return BCM_E_INTERNAL; /* should not happen */
   1240         }
   1241     }
   1242     return BCM_E_NONE;
   1243 }
   1244 
   1245 /* update sw cache : hw flow_id(s) bitmap attached to some specific statType
   1246  *    is_attached - (IN) 1: hw_flow_id attach on this group_id
   1247  *                       0: hw_flow_id deattach from this group_id
   1248  */
   1249 STATIC int
   1250 bcmi_gh2_tsn_stat_flowcnt_group_update_attached_flow(
   1251     int unit,
   1252     bcm_tsn_stat_group_type_t group_type,
   1253     uint32 group_id,
   1254     uint32 hw_flow_id,
   1255     uint32 is_attached)
   1256 {
   1257     uint32 enable_values;
   1258     bcm_tsn_stat_t stat_array[bcmTsnStatCount];
   1259     int stat_count, i;
   1260 
   1261     BCM_IF_ERROR_RETURN(
   1262         bcmi_gh2_tsn_stat_flowcnt_group_enable_value_get(
   1263             unit, group_type, group_id, &enable_values));
   1264 
   1265     BCM_IF_ERROR_RETURN(
   1266         bcmi_gh2_tsn_stat_flowcnt_group_enable_value_decode(
   1267             unit, group_type, enable_values,
   1268             stat_array, bcmTsnStatCount, &stat_count));
   1269 
   1270     assert(stat_count < bcmTsnStatCount);
   1271     for (i = 0; i < stat_count; i++) {
   1272         if (is_attached) {
   1273             SHR_BITSET(
   1274                 flowcnt_stat_fbmp_cache[unit][group_type][stat_array[i]],
   1275                 hw_flow_id);
   1276         } else {
   1277             SHR_BITCLR(
   1278                 flowcnt_stat_fbmp_cache[unit][group_type][stat_array[i]],
   1279                 hw_flow_id);
   1280         }
   1281     }
   1282     return BCM_E_NONE;
   1283 }
   1284 
   1285 /* get the group id that attached on the given flow_id */
   1286 STATIC int
   1287 bcmi_gh2_tsn_stat_flowcnt_flow_get(
   1288     int unit,
   1289     bcm_tsn_sr_flow_t flow_id,
   1290     bcm_tsn_stat_group_type_t group_type,
   1291     uint32 *ret_group_id)
   1292 {
   1293     soc_mem_t mem;
   1294     uint32 hw_flow_id;
   1295     void *buff;
   1296 
   1297     if (NULL == ret_group_id) {
   1298         return BCM_E_PARAM;
   1299     }
   1300     BCM_IF_ERROR_RETURN(
   1301         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(
   1302             unit, group_type, NULL, NULL));
   1303     BCM_IF_ERROR_RETURN(
   1304         bcmi_esw_tsn_sr_hw_flow_id_get(
   1305             unit, flow_id, &hw_flow_id));
   1306 
   1307     mem = flowcnt_flow_mem[group_type];
   1308     buff = flowcnt_mem_entry_buf[unit];
   1309 
   1310     BCM_IF_ERROR_RETURN(
   1311         soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_flow_id, buff));
   1312 
   1313     *ret_group_id = soc_mem_field32_get(unit, mem, buff,
   1314                                         flowcnt_flow_profile_field[group_type]);
   1315     return BCM_E_NONE;
   1316 }
   1317 
   1318 /* attach the specified group_id to given flow_id */
   1319 STATIC int
   1320 bcmi_gh2_tsn_stat_flowcnt_flow_set(
   1321     int unit,
   1322     bcm_tsn_sr_flow_t flow_id,
   1323     bcm_tsn_stat_group_type_t group_type,
   1324     uint32 group_id)
   1325 {
   1326     soc_mem_t mem;
   1327     uint32 hw_flow_id;
   1328     uint32 pre_group_id, pre_counter_idx;
   1329     void *buff;
   1330 
   1331     BCM_IF_ERROR_RETURN(
   1332         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(
   1333             unit, group_type, &group_id, NULL));
   1334     BCM_IF_ERROR_RETURN(
   1335         bcmi_esw_tsn_sr_hw_flow_id_get(
   1336             unit, flow_id, &hw_flow_id));
   1337 
   1338     mem = flowcnt_flow_mem[group_type];
   1339     buff = flowcnt_mem_entry_buf[unit];
   1340 
   1341     /* get the previous attached group_id and counter_idx */
   1342     BCM_IF_ERROR_RETURN(
   1343         soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_flow_id, buff));
   1344 
   1345     pre_group_id = soc_mem_field32_get(unit, mem, buff,
   1346                                        flowcnt_flow_profile_field[group_type]);
   1347     pre_counter_idx = soc_mem_field32_get(unit, mem, buff,
   1348                                           SR_COUNTER_INDEXf);
   1349 
   1350     /* switch to new group id */
   1351     if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED != group_id) {
   1352         int alloc_new_counter_idx;
   1353 
   1354         if (group_id == pre_group_id) {
   1355             /* return success directly if group_id does not change */
   1356             return BCM_E_NONE;
   1357         }
   1358 
   1359         /* alloc new pool index */
   1360         BCM_IF_ERROR_RETURN(
   1361             bcmi_gh2_tsn_stat_flowcnt_pool_counter_alloc(
   1362                 unit, group_type, &alloc_new_counter_idx, 0));
   1363 
   1364         /* increase ref count for this group id */
   1365         ERROR_RETURN_WITH_EXTRA_CLEAN(
   1366             bcmi_gh2_tsn_stat_flowcnt_group_refcnt_set(
   1367                 unit, group_type, group_id, 1),
   1368             bcmi_gh2_tsn_stat_flowcnt_pool_counter_free(
   1369                 unit, group_type, alloc_new_counter_idx));
   1370 
   1371         soc_mem_field32_set(unit, mem, buff, SR_COUNTER_INDEXf,
   1372                             alloc_new_counter_idx);
   1373         soc_mem_field32_set(unit, mem, buff,
   1374                             flowcnt_flow_profile_field[group_type],
   1375                             group_id);
   1376 
   1377         ERROR_RETURN_WITH_EXTRA_CLEAN(
   1378             soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_flow_id, buff),
   1379             bcmi_gh2_tsn_stat_flowcnt_pool_counter_free(
   1380                 unit, group_type, alloc_new_counter_idx));
   1381 
   1382         ERROR_RETURN_WITH_EXTRA_CLEAN(
   1383             bcmi_gh2_tsn_stat_flowcnt_group_update_attached_flow(
   1384                 unit, group_type, group_id, hw_flow_id, 1),
   1385             bcmi_gh2_tsn_stat_flowcnt_pool_counter_free(
   1386                 unit, group_type, alloc_new_counter_idx));
   1387     } else {
   1388         /* detach */
   1389         soc_mem_field32_set(unit, mem, buff,
   1390                             flowcnt_flow_profile_field[group_type],
   1391                             BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED);
   1392         BCM_IF_ERROR_RETURN
   1393             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_flow_id, buff));
   1394     }
   1395 
   1396     /* de-refer previous group and pool index  */
   1397     if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED != pre_group_id) {
   1398         BCM_IF_ERROR_RETURN(
   1399             bcmi_gh2_tsn_stat_flowcnt_pool_counter_free(
   1400                 unit, group_type, pre_counter_idx));
   1401 
   1402         BCM_IF_ERROR_RETURN(
   1403             bcmi_gh2_tsn_stat_flowcnt_group_refcnt_set(
   1404                 unit, group_type, pre_group_id, -1));
   1405 
   1406         BCM_IF_ERROR_RETURN(
   1407             bcmi_gh2_tsn_stat_flowcnt_group_update_attached_flow(
   1408                 unit, group_type, pre_group_id, hw_flow_id, 0));
   1409     }
   1410     return BCM_E_NONE;
   1411 }
   1412 
   1413 /* given a stat type, return all hw flow_id(s) been attached on it */
   1414 STATIC int
   1415 bcmi_gh2_tsn_stat_flowcnt_flow_get_fbmp(
   1416     int unit,
   1417     bcm_tsn_stat_t stat,
   1418     SHR_BITDCL  *fbmp,
   1419     uint32 fbmp_size)
   1420 {
   1421     bcm_tsn_stat_group_type_t group_type;
   1422 
   1423     if (stat < 0 || stat >= bcmTsnStatCount || NULL == fbmp) {
   1424         return BCM_E_PARAM;
   1425     }
   1426 
   1427     SHR_BITCLR_RANGE(fbmp, 0, fbmp_size * SHR_BITWID);
   1428 
   1429     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1430 
   1431         if (fbmp_size < _SHR_BITDCLSIZE(flowcnt_flow_num[group_type])) {
   1432             return BCM_E_PARAM;
   1433         }
   1434 
   1435         SHR_BITOR_RANGE(fbmp,
   1436                         flowcnt_stat_fbmp_cache[unit][group_type][stat],
   1437                         0, flowcnt_flow_num[group_type], fbmp);
   1438     }
   1439     return BCM_E_NONE;
   1440 }
   1441 
   1442 /*
   1443  * sync flow counter from chip to sw database (flowcnt_counter_hw/sw)
   1444  *    1. read chip actual value from chip, and write it to flowcnt_counter_hw
   1445  *    2. according to the difference with previous value in flowcnt_counter_hw,
   1446  *       increase this difference to flowcnt_counter_sw
   1447  *
   1448  *    ex. flowcnt_counter_hw = 100, flowcnt_counter_sw = 300
   1449  *         if chip actual counter is 102
   1450  *          ==> flowcnt_counter_hw = 102, flowcnt_counter_sw = 302
   1451  *
   1452  * pool_index_min/max : the range of counter pool
   1453  * index_index_min/max : the range of counter index
   1454  */
   1455 STATIC int
   1456 bcmi_gh2_tsn_stat_flowcnt_counter_sync(
   1457     int unit,
   1458     bcm_tsn_stat_group_type_t group_type,
   1459     uint32 pool_index_min,
   1460     uint32 pool_index_max,
   1461     uint32 entry_index_min,
   1462     uint32 entry_index_max)
   1463 {
   1464     uint32 pool_index;
   1465 
   1466     BCM_IF_ERROR_RETURN(
   1467         bcmi_gh2_tsn_stat_flowcnt_group_valid_check(unit, group_type,
   1468                                                     NULL, NULL));
   1469 
   1470     if (pool_index_min >= flowcnt_pool_num[group_type] ||
   1471         pool_index_max >= flowcnt_pool_num[group_type]) {
   1472         return BCM_E_PARAM;
   1473     }
   1474 
   1475     for (pool_index = pool_index_min; pool_index <= pool_index_max;
   1476          pool_index++) {
   1477         soc_mem_t mem = flowcnt_pool_mem[group_type][pool_index];
   1478         soc_memacc_t memacc_count;
   1479         uint32 entry_byte;
   1480         uint8 *buffer_ptr;
   1481         uint32 entry_index;
   1482 
   1483         if (!soc_mem_index_valid(unit, mem, entry_index_min) ||
   1484             !soc_mem_index_valid(unit, mem, entry_index_max)) {
   1485             return BCM_E_PARAM;
   1486         }
   1487 
   1488         BCM_IF_ERROR_RETURN(soc_memacc_init(unit, mem, COUNTf, &memacc_count));
   1489         entry_byte = WORDS2BYTES(soc_mem_entry_words(unit, mem));
   1490         buffer_ptr = &(flowcnt_counter_dma_buffer[unit][group_type]
   1491                        [entry_index_min * entry_byte]);
   1492         BCM_IF_ERROR_RETURN(
   1493             soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   1494                                entry_index_min, entry_index_max,
   1495                                buffer_ptr));
   1496 
   1497         /* update sw counter for each entry */
   1498         for (entry_index = entry_index_min; entry_index <= entry_index_max;
   1499              entry_index++) {
   1500 
   1501             uint64 last_count, diff_count, new_count;
   1502             uint64 *array_ptr_sw =
   1503                 flowcnt_counter_sw[unit][group_type][pool_index];
   1504             uint64 *array_ptr_hw =
   1505                 flowcnt_counter_hw[unit][group_type][pool_index];
   1506 
   1507             if (NULL == array_ptr_sw || NULL == array_ptr_hw) {
   1508                 return BCM_E_INIT;
   1509             }
   1510 
   1511             /* update sw counter from buffer */
   1512             buffer_ptr = &(flowcnt_counter_dma_buffer[unit][group_type]
   1513                            [entry_index * entry_byte]);
   1514             COMPILER_64_COPY(last_count, array_ptr_hw[entry_index]);
   1515             soc_memacc_field64_get(&memacc_count, buffer_ptr, &new_count);
   1516             if (COMPILER_64_GT(last_count, new_count)) {
   1517                 /* diff_count = new_count + count_max - last_count */
   1518                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   1519                             (BSL_META_U(unit,
   1520                                         "Roll over happened\n")));
   1521                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   1522                             (BSL_META_U(unit,
   1523                                         ".Read Packet64 Count: %x:%x\n"),
   1524                              COMPILER_64_HI(new_count),
   1525                              COMPILER_64_LO(new_count)));
   1526                 COMPILER_64_COPY(diff_count, new_count);
   1527                 COMPILER_64_ADD_64(diff_count, flowcnt_counter_max[unit]
   1528                                                                   [group_type]
   1529                                                                   [pool_index]);
   1530                 COMPILER_64_SUB_64(diff_count, last_count);
   1531                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   1532                             (BSL_META_U(unit,
   1533                                         ".Diffed 64-Packet Count: %x:%x\n"),
   1534                              COMPILER_64_HI(diff_count),
   1535                              COMPILER_64_LO(diff_count)));
   1536             } else {
   1537                 /* diff_count = new_count - last_count */
   1538                 COMPILER_64_COPY(diff_count, new_count);
   1539                 COMPILER_64_SUB_64(diff_count, last_count);
   1540             }
   1541 
   1542             /* update flowcnt_counter_hw */
   1543             COMPILER_64_COPY(array_ptr_hw[entry_index], new_count);
   1544 
   1545             /* Add difference (if it is) */
   1546             if (!COMPILER_64_IS_ZERO(diff_count)) {
   1547                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   1548                             (BSL_META_U(unit,
   1549                                         "port:%d==>"
   1550                                         "Old 64-Packet Count Value%x:%x\t"),
   1551                              entry_index,
   1552                              COMPILER_64_HI(
   1553                                  array_ptr_sw[entry_index]),
   1554                              COMPILER_64_LO(
   1555                                  array_ptr_sw[entry_index])));
   1556                 COMPILER_64_ADD_64(array_ptr_sw[entry_index],
   1557                                    diff_count);
   1558                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   1559                             (BSL_META_U(unit,
   1560                                        "New 64-Packet Value : %x:%x\n"),
   1561                              COMPILER_64_HI(
   1562                                  array_ptr_sw[entry_index]),
   1563                              COMPILER_64_LO(
   1564                                  array_ptr_sw[entry_index])));
   1565             }
   1566         }
   1567     }
   1568     return BCM_E_NONE;
   1569 }
   1570 
   1571 /* helper function for flow counter update */
   1572 STATIC int
   1573 bcmi_gh2_tsn_stat_flowcnt_counter_update(
   1574     int unit,
   1575     soc_mem_t mem,
   1576     int mem_idx,
   1577     uint64 new_count)
   1578 {
   1579     bcm_tsn_stat_group_type_t group_type;
   1580     bcm_tsn_stat_t stat_type;
   1581 
   1582     /* search the memory and set counter */
   1583     for (stat_type = 0; stat_type < bcmTsnStatCount; stat_type++) {
   1584         uint64 *array_ptr_sw, *array_ptr_hw;
   1585 
   1586         for (group_type = 0; group_type < bcmTsnStatGroupTypeCount;
   1587              group_type++) {
   1588             soc_mem_t flowcnt_mem = flowcnt_pool_mem[group_type]
   1589                                                     [stat_type];
   1590             if (mem != flowcnt_mem) {
   1591                 continue;
   1592             }
   1593             array_ptr_sw = flowcnt_counter_sw[unit][group_type]
   1594                                              [stat_type];
   1595             array_ptr_hw = flowcnt_counter_hw[unit][group_type]
   1596                                              [stat_type];
   1597             COMPILER_64_COPY(
   1598                 array_ptr_sw[mem_idx],
   1599                 new_count);
   1600             COMPILER_64_COPY(
   1601                 array_ptr_hw[mem_idx],
   1602                 new_count);
   1603             return BCM_E_NONE;
   1604         }
   1605     }
   1606     return BCM_E_NOT_FOUND;
   1607 }
   1608 
   1609 /* helper function for flow counter access */
   1610 STATIC int
   1611 bcmi_gh2_tsn_stat_flowcnt_counter_access(
   1612     int unit,
   1613     bcm_tsn_sr_flow_t flow_id,
   1614     bcmi_tsn_stat_counter_action_t action,
   1615     uint32 arr_cnt,
   1616     bcm_tsn_stat_t *stat_type_arr,
   1617     uint64 *stat_sw_value_arr,
   1618     uint64 *stat_hw_value_arr)
   1619 {
   1620     int arr_idx;
   1621     bcm_tsn_stat_group_type_t group_type;
   1622     uint32 group_id[bcmTsnStatGroupTypeCount];
   1623     uint32 counter_idx[bcmTsnStatGroupTypeCount];
   1624     uint32 hw_flow_id;
   1625 
   1626     BCM_IF_ERROR_RETURN(
   1627         bcmi_esw_tsn_sr_hw_flow_id_get(
   1628             unit, flow_id, &hw_flow_id));
   1629 
   1630     if (NULL == stat_type_arr) {
   1631         return BCM_E_PARAM;
   1632     }
   1633     for (arr_idx = 0; arr_idx < arr_cnt; arr_idx++) {
   1634         if (stat_type_arr[arr_idx] >= bcmTsnStatCount) {
   1635             return BCM_E_PARAM;
   1636         }
   1637     }
   1638 
   1639     /* get group_id and counter_idx */
   1640     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1641         soc_mem_t mem = flowcnt_flow_mem[group_type];
   1642         void *buff = flowcnt_mem_entry_buf[unit];
   1643 
   1644         BCM_IF_ERROR_RETURN(
   1645             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_flow_id, buff));
   1646 
   1647         group_id[group_type] = soc_mem_field32_get(
   1648                                    unit, mem, buff,
   1649                                    flowcnt_flow_profile_field[group_type]);
   1650         counter_idx[group_type] = soc_mem_field32_get(unit, mem, buff,
   1651                                                       SR_COUNTER_INDEXf);
   1652     }
   1653 
   1654     /* for each stat type that user specify, set/get counter */
   1655     for (arr_idx = 0; arr_idx < arr_cnt; arr_idx++) {
   1656         int found = 0;
   1657         int select_pool_index;
   1658         int select_counter_index;
   1659         bcm_tsn_stat_group_type_t select_group_type = bcmTsnStatGroupTypeCount;
   1660         uint64 *array_ptr_sw, *array_ptr_hw;
   1661 
   1662         for (group_type = 0; group_type < bcmTsnStatGroupTypeCount;
   1663              group_type++) {
   1664 
   1665             if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == group_id[group_type]) {
   1666                 continue;
   1667             }
   1668             select_pool_index =
   1669                 flowcnt_group_stat2pool[unit][group_type]
   1670                                        [group_id[group_type]]
   1671                                        [stat_type_arr[arr_idx]];
   1672             if (-1 != select_pool_index) {
   1673                 select_group_type = group_type;
   1674                 found = 1;
   1675                 break;
   1676             }
   1677         }
   1678 
   1679         if (0 == found) {
   1680             /* the user has not install this stat type before */
   1681             BCM_IF_ERROR_RETURN(BCM_E_NOT_FOUND);
   1682         }
   1683 
   1684         assert(select_group_type >= 0 &&
   1685                select_group_type < bcmTsnStatGroupTypeCount);
   1686         assert(select_pool_index >= 0 &&
   1687                select_pool_index < flowcnt_pool_num[select_group_type]);
   1688         array_ptr_sw = flowcnt_counter_sw[unit][select_group_type]
   1689                                          [select_pool_index];
   1690         array_ptr_hw = flowcnt_counter_hw[unit][select_group_type]
   1691                                          [select_pool_index];
   1692         select_counter_index = counter_idx[select_group_type];
   1693         /* get flow counter */
   1694         switch (action) {
   1695             case bcmiTsnStatCounterActionReadSync:
   1696                 BCM_IF_ERROR_RETURN(
   1697                     bcmi_gh2_tsn_stat_flowcnt_counter_sync(
   1698                         unit, select_group_type,
   1699                         select_pool_index, select_pool_index,
   1700                         select_counter_index,
   1701                         select_counter_index));
   1702                 /* fall through */
   1703            case bcmiTsnStatCounterActionRead:
   1704                 if (NULL != stat_sw_value_arr) {
   1705                     COMPILER_64_COPY(
   1706                         stat_sw_value_arr[arr_idx],
   1707                         array_ptr_sw[select_counter_index]);
   1708                 }
   1709                 if (NULL != stat_hw_value_arr) {
   1710                     COMPILER_64_COPY(
   1711                         stat_hw_value_arr[arr_idx],
   1712                         array_ptr_hw[select_counter_index]);
   1713                 }
   1714                 break;
   1715            case bcmiTsnStatCounterActionWrite:
   1716                 if (NULL != stat_sw_value_arr) {
   1717                     COMPILER_64_COPY(
   1718                         array_ptr_sw[select_counter_index],
   1719                         stat_sw_value_arr[arr_idx]);
   1720                 }
   1721                 if (NULL != stat_hw_value_arr) {
   1722                     uint8 *buffer_ptr;
   1723                     uint64 new_count;
   1724                     soc_mem_t mem = flowcnt_pool_mem[select_group_type]
   1725                                                     [select_pool_index];
   1726 
   1727                     COMPILER_64_COPY(new_count, stat_hw_value_arr[arr_idx]);
   1728                     COMPILER_64_AND(new_count,
   1729                                     flowcnt_counter_mask[unit]
   1730                                                         [select_group_type]
   1731                                                         [select_pool_index]);
   1732 
   1733                     /* write masked value into chip actual data and
   1734                      * update flowcnt_counter_hw
   1735                      */
   1736                     COMPILER_64_COPY(
   1737                         array_ptr_hw[select_counter_index],
   1738                         new_count);
   1739                     buffer_ptr = &(flowcnt_counter_dma_buffer
   1740                                    [unit][select_group_type][0]);
   1741                     BCM_IF_ERROR_RETURN(
   1742                         soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   1743                                      select_counter_index, buffer_ptr));
   1744                     soc_mem_field64_set(
   1745                         unit, mem, buffer_ptr, COUNTf, new_count);
   1746                     BCM_IF_ERROR_RETURN(
   1747                         soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   1748                                       select_counter_index, buffer_ptr));
   1749                 }
   1750                 break;
   1751            default:
   1752                 return BCM_E_PARAM;
   1753         }
   1754     }
   1755 
   1756     return BCM_E_NONE;
   1757 }
   1758 
   1759 /* callback for flow counter, sync all stat types
   1760  * (just need to update the counter index has been in use)
   1761  */
   1762 STATIC int
   1763 bcmi_gh2_tsn_stat_flowcnt_counter_sync_all(int unit)
   1764 {
   1765     bcm_tsn_stat_group_type_t group_type;
   1766 
   1767     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1768         if (-1 == flowcnt_pool_bitmap_alloc_min[unit][group_type]) {
   1769             continue;
   1770         }
   1771         bcmi_gh2_tsn_stat_flowcnt_counter_sync(
   1772             unit, group_type,
   1773             0, flowcnt_pool_num[group_type] - 1,
   1774             flowcnt_pool_bitmap_alloc_min[unit][group_type],
   1775             flowcnt_pool_bitmap_alloc_max[unit][group_type]);
   1776     }
   1777 
   1778     return BCM_E_NONE;
   1779 }
   1780 
   1781 /* callback for flow counter, sync one specific stat type
   1782  * (just need to update the counter index has been in use)
   1783  */
   1784 STATIC int
   1785 bcmi_gh2_tsn_stat_flowcnt_counter_sync_stat(int unit, bcm_tsn_stat_t stat)
   1786 {
   1787     bcm_tsn_stat_group_type_t group_type;
   1788     int pool_idx;
   1789 
   1790     if (stat < 0 || stat >= bcmTsnStatCount) {
   1791         return BCM_E_PARAM;
   1792     }
   1793 
   1794     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1795         SHR_BITDCL select_pool[1];
   1796         int pool_num = flowcnt_pool_num[group_type];
   1797         int group_id;
   1798 
   1799         if (-1 == flowcnt_pool_bitmap_alloc_min[unit][group_type]) {
   1800             continue;
   1801         }
   1802         assert(pool_num <= SHR_BITWID);
   1803         SHR_BITCLR_RANGE(&(select_pool[0]), 0, pool_num);
   1804         for (group_id = 0; group_id < flowcnt_group_num[group_type];
   1805              group_id++) {
   1806             pool_idx = flowcnt_group_stat2pool[unit][group_type]
   1807                                               [group_id][stat];
   1808             if (-1 == pool_idx) {
   1809                 continue;
   1810             }
   1811             assert(pool_idx >= 0 && pool_idx < pool_num);
   1812             SHR_BITSET(&(select_pool[0]), pool_idx);
   1813         }
   1814 
   1815         SHR_BIT_ITER(&(select_pool[0]), pool_num, pool_idx) {
   1816             bcmi_gh2_tsn_stat_flowcnt_counter_sync(
   1817                 unit, group_type, pool_idx, pool_idx,
   1818                 flowcnt_pool_bitmap_alloc_min[unit][group_type],
   1819                 flowcnt_pool_bitmap_alloc_max[unit][group_type]);
   1820         }
   1821     }
   1822 
   1823     return BCM_E_NONE;
   1824 }
   1825 
   1826 /* clean the resource for tsn flow counter */
   1827 STATIC int
   1828 bcmi_gh2_tsn_stat_flowcnt_cleanup(int unit)
   1829 {
   1830     bcm_tsn_stat_group_type_t group_type;
   1831 
   1832     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1833         int i;
   1834 
   1835         if (NULL != flowcnt_group_mem_profile[unit][group_type]) {
   1836             soc_profile_mem_destroy(
   1837                 unit, flowcnt_group_mem_profile[unit][group_type]);
   1838             sal_free(flowcnt_group_mem_profile[unit][group_type]);
   1839             flowcnt_group_mem_profile[unit][group_type] = NULL;
   1840         }
   1841         if (NULL != flowcnt_group_stat2pool[unit][group_type]) {
   1842             for (i = 0; i < flowcnt_group_num[group_type]; i++) {
   1843                 if (NULL != flowcnt_group_stat2pool[unit][group_type][i]) {
   1844                     sal_free(flowcnt_group_stat2pool[unit][group_type][i]);
   1845                     flowcnt_group_stat2pool[unit][group_type][i] = NULL;
   1846                 }
   1847             }
   1848             sal_free(flowcnt_group_stat2pool[unit][group_type]);
   1849             flowcnt_group_stat2pool[unit][group_type] = NULL;
   1850         }
   1851         if (NULL != flowcnt_pool_bitmap[unit][group_type]) {
   1852             shr_res_bitmap_destroy(flowcnt_pool_bitmap[unit][group_type]);
   1853             flowcnt_pool_bitmap[unit][group_type] = NULL;
   1854         }
   1855         if (NULL != flowcnt_counter_dma_buffer[unit][group_type]) {
   1856             soc_cm_sfree(unit, flowcnt_counter_dma_buffer[unit][group_type]);
   1857             flowcnt_counter_dma_buffer[unit][group_type] = NULL;
   1858         }
   1859         for (i = 0;
   1860              i < flowcnt_pool_num[group_type];
   1861              i++) {
   1862 
   1863             if (NULL != flowcnt_counter_sw[unit][group_type][i]) {
   1864                 sal_free(flowcnt_counter_sw[unit][group_type][i]);
   1865                 flowcnt_counter_sw[unit][group_type][i] = NULL;
   1866             }
   1867             if (NULL != flowcnt_counter_hw[unit][group_type][i]) {
   1868                 sal_free(flowcnt_counter_hw[unit][group_type][i]);
   1869                 flowcnt_counter_hw[unit][group_type][i] = NULL;
   1870             }
   1871         }
   1872         for (i = 0; i < bcmTsnStatCount; i++) {
   1873             if (NULL != flowcnt_stat_fbmp_cache[unit][group_type][i]) {
   1874                 sal_free(flowcnt_stat_fbmp_cache[unit][group_type][i]);
   1875                 flowcnt_stat_fbmp_cache[unit][group_type][i] = NULL;
   1876             }
   1877         }
   1878         flowcnt_pool_bitmap_alloc_min[unit][group_type] = -1;
   1879         flowcnt_pool_bitmap_alloc_max[unit][group_type] = -1;
   1880     }
   1881 
   1882     if (NULL != flowcnt_mem_entry_buf[unit]) {
   1883         sal_free(flowcnt_mem_entry_buf[unit]);
   1884         flowcnt_mem_entry_buf[unit] = NULL;
   1885     }
   1886     return BCM_E_NONE;
   1887 }
   1888 
   1889 /* init the resource for tsn flow counter */
   1890 STATIC int
   1891 bcmi_gh2_tsn_stat_flowcnt_init(int unit)
   1892 {
   1893     bcm_tsn_stat_group_type_t group_type;
   1894     uint32 max_entry_size = 0;
   1895     void *entry_buf;
   1896 
   1897     /* parameter setup */
   1898     if (soc_feature(unit, soc_feature_tsn_taf)) {
   1899         flowcnt_enable_value_mapping_cnt[unit][bcmTsnStatGroupTypeIngress] = 20;
   1900         flowcnt_enable_value_mapping_cnt[unit][bcmTsnStatGroupTypeEgress]  = 4;
   1901     } else {
   1902         flowcnt_enable_value_mapping_cnt[unit][bcmTsnStatGroupTypeIngress] = 15;
   1903         flowcnt_enable_value_mapping_cnt[unit][bcmTsnStatGroupTypeEgress]  = 4;
   1904     }
   1905 
   1906     /* handle flow mem */
   1907     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1908         soc_mem_t mem = flowcnt_flow_mem[group_type];
   1909 
   1910         max_entry_size =
   1911             BCMI_TSN_FLOWCNT_MAX(max_entry_size,
   1912                                  WORDS2BYTES(soc_mem_entry_words(unit, mem)));
   1913 
   1914         /* verify flowcnt_flow_num */
   1915         if (flowcnt_flow_num[group_type] !=
   1916             soc_mem_index_count(unit, mem)) {
   1917             INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL);
   1918         }
   1919     }
   1920 
   1921     /* handle group mem */
   1922     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1923         soc_mem_t group_mem = flowcnt_group_mem[group_type];
   1924         soc_profile_mem_t *profile_mem;
   1925         int mem_word, group_id;
   1926 
   1927          /* verify flowcnt_group_num */
   1928         if (flowcnt_group_num[group_type] !=
   1929             soc_mem_index_count(unit, group_mem)) {
   1930             INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL);
   1931         }
   1932 
   1933         /* because we use bit 20 for egress bit in encoding stat id
   1934          * , so the number of entries cannot excess 1 << 20
   1935          */
   1936         if (flowcnt_group_num[group_type] >=
   1937             (1 << BCMI_TSN_FLOWCNT_STAT_ID_EGRESS_BIT)) {
   1938             INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL);
   1939         }
   1940 
   1941         max_entry_size =
   1942             BCMI_TSN_FLOWCNT_MAX(max_entry_size,
   1943                                  WORDS2BYTES(soc_mem_entry_words(unit,
   1944                                                                  group_mem)));
   1945 
   1946         /* profile mem */
   1947         mem_word = soc_mem_entry_words(unit, group_mem);
   1948         flowcnt_group_mem_profile[unit][group_type] =
   1949             sal_alloc(sizeof(soc_profile_mem_t), "TSN Group Profile Mem");
   1950         profile_mem = flowcnt_group_mem_profile[unit][group_type];
   1951         if (NULL == profile_mem) {
   1952             INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   1953         }
   1954         soc_profile_mem_t_init(profile_mem);
   1955         INIT_ERROR_RETURN_WITH_CLEAN(
   1956             soc_profile_mem_create(unit, &group_mem, &mem_word,
   1957                                    1, profile_mem));
   1958 
   1959         /* for each gorup_id
   1960          *   alloc flowcnt_group_stat2pool
   1961          */
   1962         flowcnt_group_stat2pool[unit][group_type] =
   1963             sal_alloc(flowcnt_group_num[group_type] * sizeof(int32 *),
   1964                       "flowcnt_group_stat2pool");
   1965         if (NULL == flowcnt_group_stat2pool[unit][group_type]) {
   1966             INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   1967         }
   1968 
   1969         for (group_id = 0; group_id < flowcnt_group_num[group_type];
   1970              group_id++) {
   1971 
   1972             int stat_id;
   1973 
   1974             flowcnt_group_stat2pool[unit][group_type][group_id] =
   1975                 sal_alloc(bcmTsnStatCount * sizeof(int32),
   1976                           "flowcnt_group_stat2pool");
   1977             if (NULL == flowcnt_group_stat2pool[unit][group_type][group_id]) {
   1978                 INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   1979             }
   1980             for (stat_id = 0; stat_id < bcmTsnStatCount; stat_id++) {
   1981                 flowcnt_group_stat2pool[unit][group_type]
   1982                                        [group_id][stat_id] = -1;
   1983             }
   1984         }
   1985     }
   1986 
   1987     /* handle pool mem */
   1988     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   1989         int index, pool_entry_count;
   1990         soc_mem_t mem;
   1991 
   1992 
   1993         for (index = 0;
   1994              index < flowcnt_pool_num[group_type];
   1995              index++) {
   1996 
   1997             mem = flowcnt_pool_mem[group_type][index];
   1998             max_entry_size =
   1999                 BCMI_TSN_FLOWCNT_MAX(max_entry_size,
   2000                                      WORDS2BYTES(
   2001                                          soc_mem_entry_words(unit, mem)));
   2002         }
   2003 
   2004         /* allocate bitmap */
   2005         mem = flowcnt_pool_mem[group_type][0];
   2006         pool_entry_count = soc_mem_index_count(unit, mem);
   2007         INIT_ERROR_RETURN_WITH_CLEAN(
   2008             shr_res_bitmap_create(&flowcnt_pool_bitmap[unit][group_type],
   2009                                   0, pool_entry_count));
   2010         flowcnt_pool_bitmap_alloc_min[unit][group_type] = -1;
   2011         flowcnt_pool_bitmap_alloc_max[unit][group_type] = -1;
   2012 
   2013         /* allocate counter sw database */
   2014         for (index = 0;
   2015              index < flowcnt_pool_num[group_type]; index++) {
   2016 
   2017             flowcnt_counter_sw[unit][group_type][index] =
   2018                 sal_alloc(pool_entry_count * sizeof(uint64),
   2019                           "tsn flow sw counter");
   2020             if (NULL == flowcnt_counter_sw[unit][group_type][index]) {
   2021                 INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   2022             }
   2023             sal_memset(flowcnt_counter_sw[unit][group_type][index],
   2024                        0, pool_entry_count * sizeof(uint64));
   2025 
   2026             flowcnt_counter_hw[unit][group_type][index] =
   2027                 sal_alloc(pool_entry_count * sizeof(uint64),
   2028                           "tsn flow hw counter");
   2029             if (NULL == flowcnt_counter_hw[unit][group_type][index]) {
   2030                 INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   2031             }
   2032             sal_memset(flowcnt_counter_hw[unit][group_type][index],
   2033                        0, pool_entry_count * sizeof(uint64));
   2034 
   2035             /* setup max/mask for counter */
   2036             COMPILER_64_SET(flowcnt_counter_max[unit][group_type][index], 0, 1);
   2037             COMPILER_64_SHL(flowcnt_counter_max[unit][group_type][index],
   2038                             soc_mem_field_length(
   2039                                 unit, flowcnt_pool_mem[group_type][index],
   2040                                 COUNTf));
   2041             COMPILER_64_COPY(flowcnt_counter_mask[unit][group_type][index],
   2042                              flowcnt_counter_max[unit][group_type][index]);
   2043             COMPILER_64_SUB_32(flowcnt_counter_mask[unit][group_type][index],
   2044                                1);
   2045         }
   2046 
   2047         /* allocate dma buffer */
   2048         flowcnt_counter_dma_buffer[unit][group_type] =
   2049             soc_cm_salloc(unit, pool_entry_count *
   2050                           WORDS2BYTES(soc_mem_entry_words(unit, mem)),
   2051                           "tsn flowctr counter buffer");
   2052         if (NULL == flowcnt_counter_dma_buffer[unit][group_type]) {
   2053              INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   2054         }
   2055 
   2056         /* setup cache for statType and fbmp */
   2057         for (index = 0; index < bcmTsnStatCount; index++) {
   2058             flowcnt_stat_fbmp_cache[unit][group_type][index] =
   2059                     sal_alloc(SHR_BITALLOCSIZE(flowcnt_flow_num[group_type]),
   2060                               "flowcnt_stat_fbmp_cache");
   2061             if (NULL == flowcnt_stat_fbmp_cache[unit][group_type][index]) {
   2062                 INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   2063             }
   2064             SHR_BITCLR_RANGE(
   2065                 flowcnt_stat_fbmp_cache[unit][group_type][index],
   2066                 0, flowcnt_flow_num[group_type]);
   2067         }
   2068     }
   2069 
   2070     /* allocate mem entry buf */
   2071     flowcnt_mem_entry_buf[unit] = sal_alloc(max_entry_size, "tsn mem buf");
   2072     entry_buf = flowcnt_mem_entry_buf[unit];
   2073     if (NULL == entry_buf) {
   2074         INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   2075     }
   2076 
   2077     /* reserve profile entry 0 for invalid usage */
   2078     for (group_type = 0; group_type < bcmTsnStatGroupTypeCount; group_type++) {
   2079         soc_mem_t mem = flowcnt_group_mem[group_type];
   2080         int group_id;
   2081 
   2082         soc_mem_field32_set(unit, mem, entry_buf, SR_COUNTER_ENABLESf, 0);
   2083         INIT_ERROR_RETURN_WITH_CLEAN(
   2084             soc_profile_mem_single_table_add(
   2085                 unit, flowcnt_group_mem_profile[unit][group_type],
   2086                 entry_buf, 1, &group_id));
   2087         if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED != group_id) {
   2088             INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_INTERNAL);
   2089         }
   2090     }
   2091 
   2092 #if defined(BCM_WARM_BOOT_SUPPORT)
   2093     if (SOC_WARM_BOOT(unit)) {
   2094         /* warmboot : recover group profile,
   2095          * traverse each valid "group_type, group_id", recover its refcnt
   2096          * back to 1
   2097          */
   2098         INIT_ERROR_RETURN_WITH_CLEAN(
   2099             bcmi_gh2_tsn_stat_flowcnt_group_internal_traverse(
   2100                 unit, bcmi_gh2_tsn_stat_flowcnt_group_traverse_cb_recover,
   2101                 NULL));
   2102 
   2103         /* warmboot : recover reference count and pool alloc bitmap,
   2104          * traverse each flow, if it attached to some group
   2105          * ==> group's refcnt++ , setup alloc bitmap
   2106          */
   2107         for (group_type = 0; group_type < bcmTsnStatGroupTypeCount;
   2108              group_type++) {
   2109             int entry_byte, alloc_size, index;
   2110             soc_mem_t mem = flowcnt_flow_mem[group_type];
   2111             int entry_num = flowcnt_flow_num[group_type];
   2112             uint8 *dma_entry_buf;
   2113 
   2114             entry_byte = WORDS2BYTES(soc_mem_entry_words(unit, mem));
   2115             alloc_size = entry_num * entry_byte;
   2116             dma_entry_buf = soc_cm_salloc(unit, alloc_size,
   2117                                           "tsn counter dmabuf");
   2118             if (NULL == dma_entry_buf) {
   2119                 INIT_ERROR_RETURN_WITH_CLEAN(BCM_E_MEMORY);
   2120             }
   2121 
   2122             INIT_ERROR_RETURN_WITH_EXTRA_CLEAN(
   2123                 soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   2124                                    0, entry_num -1, dma_entry_buf),
   2125                 soc_cm_sfree(unit, dma_entry_buf));
   2126 
   2127             for (index = 0; index < entry_num; index++) {
   2128                 uint32 group_id;
   2129                 int counter_idx;
   2130 
   2131                 group_id =
   2132                     soc_mem_field32_get(unit, mem,
   2133                                         &dma_entry_buf[index * entry_byte],
   2134                                         flowcnt_flow_profile_field[group_type]);
   2135                 counter_idx =
   2136                     soc_mem_field32_get(unit, mem,
   2137                                         &dma_entry_buf[index * entry_byte],
   2138                                         SR_COUNTER_INDEXf);
   2139 
   2140                 if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED != group_id) {
   2141                     SOC_PROFILE_MEM_REFERENCE(
   2142                         unit, flowcnt_group_mem_profile[unit][group_type],
   2143                         group_id, 1);
   2144 
   2145                     INIT_ERROR_RETURN_WITH_EXTRA_CLEAN(
   2146                         bcmi_gh2_tsn_stat_flowcnt_pool_counter_alloc(
   2147                             unit, group_type, &counter_idx, 1),
   2148                         soc_cm_sfree(unit, dma_entry_buf));
   2149 
   2150                     INIT_ERROR_RETURN_WITH_EXTRA_CLEAN(
   2151                         bcmi_gh2_tsn_stat_flowcnt_group_update_attached_flow(
   2152                             unit, group_type, group_id, index, 1),
   2153                         soc_cm_sfree(unit, dma_entry_buf));
   2154                 }
   2155             }
   2156             soc_cm_sfree(unit, dma_entry_buf);
   2157         }
   2158 
   2159         /* warmboot : recover counter
   2160          *    recover flowcnt_counter_hw by hw data
   2161          *    (flowcnt_counter_sw will be recoved in reload)
   2162          */
   2163         for (group_type = 0; group_type < bcmTsnStatGroupTypeCount;
   2164              group_type++) {
   2165 
   2166             uint32 pool_index;
   2167             for (pool_index = 0; pool_index < flowcnt_pool_num[group_type];
   2168                  pool_index++) {
   2169 
   2170                 soc_mem_t mem = flowcnt_pool_mem[group_type][pool_index];
   2171                 soc_memacc_t memacc_count;
   2172                 int entry_byte, entry_index;
   2173                 uint8 *buffer_ptr;
   2174 
   2175                 INIT_ERROR_RETURN_WITH_CLEAN(
   2176                     soc_memacc_init(unit, mem, COUNTf, &memacc_count));
   2177 
   2178                 entry_byte = WORDS2BYTES(soc_mem_entry_words(unit, mem));
   2179                 buffer_ptr = flowcnt_counter_dma_buffer[unit][group_type];
   2180 
   2181                 INIT_ERROR_RETURN_WITH_CLEAN(
   2182                     soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   2183                                        0, soc_mem_index_count(unit, mem) - 1,
   2184                                        buffer_ptr));
   2185 
   2186                 for (entry_index = 0;
   2187                      entry_index < soc_mem_index_count(unit, mem);
   2188                      entry_index++) {
   2189                     uint64 new_count;
   2190                     uint64 *array_ptr_hw =
   2191                         flowcnt_counter_hw[unit][group_type][pool_index];
   2192 
   2193                     buffer_ptr =
   2194                         &(flowcnt_counter_dma_buffer[unit][group_type]
   2195                                                     [entry_index * entry_byte]);
   2196                     soc_memacc_field64_get(&memacc_count, buffer_ptr,
   2197                                            &new_count);
   2198                     COMPILER_64_COPY(array_ptr_hw[entry_index], new_count);
   2199                 }
   2200             }
   2201         }
   2202     }
   2203 #endif /* BCM_WARM_BOOT_SUPPORT */
   2204     return BCM_E_NONE;
   2205 }
   2206 
   2207 /*
   2208  * Function:
   2209  *    bcmi_gh2_tsn_stat_threshold_select_set
   2210  * Purpose:
   2211  *    Configure threshold for a specific stat type based on source
   2212  * Parameters:
   2213  *    unit         - (IN) Unit number
   2214  *    select_info  - (IN) TSN stat threshold selected source
   2215  *    count        - (IN) count of TSN stat threshold selected source
   2216  *    stat         - (IN) TSN statistic type (see tsn.h)
   2217  *    config       - (IN) TSN stat threshold configuration structure
   2218  * Returns:
   2219  *    BCM_E_XXX
   2220  */
   2221 STATIC int
   2222 bcmi_gh2_tsn_stat_threshold_select_set(
   2223     int unit,
   2224     const bcmi_gh2_tsn_stat_threshold_select_t *select_info,
   2225     int count,
   2226     bcm_tsn_stat_t stat,
   2227     bcm_tsn_stat_threshold_config_t *config)
   2228 {
   2229     const bcmi_gh2_tsn_stat_threshold_select_t *info;
   2230     int interrupt_enable = 0, copy_to_cpu = 0;
   2231     int idx;
   2232     uint32 threshold_value;
   2233     uint32 field_value = 0;
   2234     uint64 reg_val64;
   2235     int is_changed = 0;
   2236 
   2237     /* Input parameter check */
   2238     if ((NULL == config) || (NULL == select_info)) {
   2239         return BCM_E_PARAM;
   2240     }
   2241 
   2242     threshold_value = config->threshold;
   2243     if (config->flags) {
   2244         if (!(config->flags & BCM_TSN_STAT_THRESHOLD_EVENT_NOTIFICATION) &&
   2245             !(config->flags & BCM_TSN_STAT_THRESHOLD_COPY_TO_CPU)) {
   2246             return BCM_E_UNAVAIL;
   2247         }
   2248 
   2249         /*
   2250          * For MTU/STU, should write value (N) to HW register.
   2251          * For other counters, should write value (N-1) to HW register.
   2252          */
   2253         if (!GH2_TSN_STAT_THRESHOLD_MTU_STU_IS_VALID(unit, stat)) {
   2254             if (threshold_value > 0) {
   2255                 threshold_value -= 1;
   2256             } else {
   2257                 /* Can't write value (0-1=-1) to HW register */
   2258                 return BCM_E_CONFIG;
   2259             }
   2260         }
   2261     } else {
   2262         /*
   2263          * If flags = 0 (threshold disabled),
   2264          * ignore the counter value and write maximum to the register
   2265          */
   2266         threshold_value = GH2_TSN_STAT_THRESHOLD_DEFAULT_VALUE;
   2267     }
   2268 
   2269     /* Event notification */
   2270     if (config->flags & BCM_TSN_STAT_THRESHOLD_EVENT_NOTIFICATION) {
   2271         interrupt_enable = 0x1;
   2272     }
   2273 
   2274     /* Copy the packet to CPU */
   2275     if (config->flags & BCM_TSN_STAT_THRESHOLD_COPY_TO_CPU) {
   2276         copy_to_cpu = 0x1;
   2277     }
   2278 
   2279     /* Select the TSN stat type */
   2280     for (idx = 0; idx < count; idx++) {
   2281         info = select_info + idx;
   2282         if (info->stat_type != stat) {
   2283             continue;
   2284         }
   2285 
   2286         COMPILER_64_ZERO(reg_val64);
   2287         /* Read the specified threshold register */
   2288         BCM_IF_ERROR_RETURN(
   2289             soc_reg64_get(unit, info->reg, REG_PORT_ANY, 0, &reg_val64));
   2290 
   2291         /* COUNTER_THRESHOLDf */
   2292         field_value = soc_reg64_field32_get(unit, info->reg,
   2293                                             reg_val64, info->threshold_field);
   2294         if (threshold_value != field_value) {
   2295             is_changed = 1;
   2296             soc_reg64_field32_set(unit, info->reg, &reg_val64,
   2297                                   info->threshold_field, threshold_value);
   2298         }
   2299 
   2300         /* INTERRUPT_ENABLEf */
   2301         field_value = soc_reg64_field32_get(unit, info->reg,
   2302                                             reg_val64, info->interrupt_field);
   2303         if (interrupt_enable != field_value) {
   2304             is_changed = 1;
   2305             soc_reg64_field32_set(unit, info->reg, &reg_val64,
   2306                                   info->interrupt_field, interrupt_enable);
   2307         }
   2308 
   2309         /* COPY_TO_CPUf */
   2310         if (info->copy_to_cpu_field != INVALIDf) {
   2311             field_value = soc_reg64_field32_get(unit, info->reg,
   2312                                                 reg_val64,
   2313                                                 info->copy_to_cpu_field);
   2314             if (copy_to_cpu != field_value) {
   2315                 is_changed = 1;
   2316                 soc_reg64_field32_set(unit, info->reg, &reg_val64,
   2317                                       info->copy_to_cpu_field, copy_to_cpu);
   2318             }
   2319         } else {
   2320             if (copy_to_cpu) {
   2321                 return BCM_E_PARAM;
   2322             }
   2323         }
   2324 
   2325         if (is_changed) {
   2326             /* Write the specified threshold register if any changes */
   2327             BCM_IF_ERROR_RETURN(
   2328                 soc_reg64_set(unit, info->reg, REG_PORT_ANY, 0, reg_val64));
   2329         }
   2330 
   2331         break;
   2332     }
   2333 
   2334     if (idx == count) {
   2335         return BCM_E_PARAM;
   2336     }
   2337 
   2338     return BCM_E_NONE;
   2339 }
   2340 
   2341 /*
   2342  * Function:
   2343  *    bcmi_gh2_tsn_stat_threshold_select_get
   2344  * Purpose:
   2345  *    Get the threshold configuration for a specific stat type based on source
   2346  * Parameters:
   2347  *    unit         - (IN) Unit number
   2348  *    select_info  - (IN) TSN stat threshold selected source
   2349  *    count        - (IN) count of TSN stat threshold selected source
   2350  *    stat         - (IN) TSN statistics type (see tsn.h)
   2351  *    config       - (OUT) TSN stat threshold configuration structure
   2352  * Returns:
   2353  *    BCM_E_XXX
   2354  */
   2355 STATIC int
   2356 bcmi_gh2_tsn_stat_threshold_select_get(
   2357     int unit,
   2358     const bcmi_gh2_tsn_stat_threshold_select_t *select_info,
   2359     int count,
   2360     bcm_tsn_stat_t stat,
   2361     bcm_tsn_stat_threshold_config_t *config)
   2362 {
   2363     const bcmi_gh2_tsn_stat_threshold_select_t *info;
   2364     int interrupt_enable = 0, copy_to_cpu = 0;
   2365     int idx;
   2366     uint64 reg_val64;
   2367 
   2368     /* Input parameter check */
   2369     if ((NULL == config) || (NULL == select_info)) {
   2370         return BCM_E_PARAM;
   2371     }
   2372 
   2373     /* Clear buffer to zero */
   2374     bcm_tsn_stat_threshold_config_t_init(config);
   2375 
   2376     /* Select the TSN stat type */
   2377     for (idx = 0; idx < count; idx++) {
   2378         info = select_info + idx;
   2379         if (info->stat_type != stat) {
   2380             continue;
   2381         }
   2382 
   2383         COMPILER_64_ZERO(reg_val64);
   2384         /* Read the specified threshold register */
   2385         BCM_IF_ERROR_RETURN(
   2386             soc_reg64_get(unit, info->reg, REG_PORT_ANY, 0, &reg_val64));
   2387 
   2388         /* COUNTER_THRESHOLDf */
   2389         config->threshold = soc_reg64_field32_get(unit, info->reg,
   2390                                                   reg_val64,
   2391                                                   info->threshold_field);
   2392         /* INTERRUPT_ENABLEf */
   2393         interrupt_enable = soc_reg64_field32_get(unit, info->reg,
   2394                                                  reg_val64,
   2395                                                  info->interrupt_field);
   2396         /* Event notification */
   2397         if (interrupt_enable) {
   2398             config->flags |= BCM_TSN_STAT_THRESHOLD_EVENT_NOTIFICATION;
   2399         }
   2400 
   2401         /* COPY_TO_CPUf */
   2402         if (info->copy_to_cpu_field != INVALIDf) {
   2403             copy_to_cpu = soc_reg64_field32_get(unit, info->reg,
   2404                                                 reg_val64,
   2405                                                 info->copy_to_cpu_field);
   2406             /* Copy the packet to CPU */
   2407             if (copy_to_cpu) {
   2408                 config->flags |= BCM_TSN_STAT_THRESHOLD_COPY_TO_CPU;
   2409             }
   2410         }
   2411 
   2412         break;
   2413     }
   2414 
   2415     if (idx == count) {
   2416         return BCM_E_PARAM;
   2417     }
   2418 
   2419     /*
   2420      * For MTU/STU, read value N from HW register should return (N).
   2421      * For other counters, read value N from HW register should return (N+1).
   2422      */
   2423     if (!GH2_TSN_STAT_THRESHOLD_MTU_STU_IS_VALID(unit, stat)) {
   2424         if (config->threshold < GH2_TSN_STAT_THRESHOLD_DEFAULT_VALUE) {
   2425             config->threshold += 1;
   2426         }
   2427     }
   2428 
   2429     return BCM_E_NONE;
   2430 }
   2431 
   2432 /*
   2433  * Function:
   2434  *    bcmi_gh2_tsn_stat_threshold_set
   2435  * Purpose:
   2436  *    Configure threshold for a specific stat type on
   2437  *    a specific source
   2438  * Parameters:
   2439  *    unit   - (IN) Unit number
   2440  *    source - (IN) Stat source for TSN stat threshold check
   2441  *    stat   - (IN) TSN statistics type (see tsn.h)
   2442  *    config - (IN) TSN stat threshold configuration structure
   2443  * Returns:
   2444  *    BCM_E_XXX
   2445  */
   2446 STATIC int
   2447 bcmi_gh2_tsn_stat_threshold_set(
   2448     int unit,
   2449     bcm_tsn_stat_threshold_source_t source,
   2450     bcm_tsn_stat_t stat,
   2451     bcm_tsn_stat_threshold_config_t *config)
   2452 {
   2453     int rv = BCM_E_UNAVAIL;
   2454     int count = 0;
   2455     const bcmi_gh2_tsn_stat_threshold_select_t *select_info;
   2456 
   2457     /* Input parameter check */
   2458     if (NULL == config) {
   2459         return BCM_E_PARAM;
   2460     }
   2461 
   2462     if (soc_feature(unit, soc_feature_tsn)) {
   2463         /* Valid check for stat type */
   2464         if (!GH2_TSN_STAT_THRESHOLD_IS_VALID(unit, stat)) {
   2465             return BCM_E_PARAM;
   2466         }
   2467 
   2468         /* Select the source type: Port or SR Flow */
   2469         switch (source) {
   2470             case bcmTsnStatThresholdSourcePort:
   2471                 /*
   2472                  * Set the threshold for a specific TSN stat
   2473                  * on source port
   2474                  */
   2475                 select_info = gh2_port_count_threshold_info;
   2476                 count = COUNTOF(gh2_port_count_threshold_info);
   2477                 break;
   2478             case bcmTsnStatThresholdSourceSRFlow:
   2479                 /*
   2480                  * Set the threshold for a specific TSN stat
   2481                  * on source SR flow
   2482                  */
   2483                 select_info = gh2_flow_count_threshold_info;
   2484                 count = COUNTOF(gh2_flow_count_threshold_info);
   2485                 break;
   2486             default:
   2487                 return BCM_E_PARAM;
   2488         }
   2489 
   2490         rv = bcmi_gh2_tsn_stat_threshold_select_set(unit, select_info,
   2491                                                     count, stat, config);
   2492     }
   2493 
   2494     return rv;
   2495 }
   2496 
   2497 /*
   2498  * Function:
   2499  *    bcmi_gh2_tsn_stat_threshold_get
   2500  * Purpose:
   2501  *    Get the threshold configuration for a specific stat type on
   2502  *    a specific source
   2503  * Parameters:
   2504  *    unit   - (IN) Unit number
   2505  *    source - (IN) Stat source for TSN stat threshold check
   2506  *    stat   - (IN) TSN statistics type (see tsn.h)
   2507  *    config - (OUT) TSN stat threshold configuration structure
   2508  * Returns:
   2509  *    BCM_E_XXX
   2510  */
   2511 STATIC int
   2512 bcmi_gh2_tsn_stat_threshold_get(
   2513     int unit,
   2514     bcm_tsn_stat_threshold_source_t source,
   2515     bcm_tsn_stat_t stat,
   2516     bcm_tsn_stat_threshold_config_t *config)
   2517 {
   2518     int rv = BCM_E_UNAVAIL;
   2519     int count = 0;
   2520     const bcmi_gh2_tsn_stat_threshold_select_t *select_info;
   2521 
   2522     /* Input parameter check */
   2523     if (NULL == config) {
   2524         return BCM_E_PARAM;
   2525     }
   2526 
   2527     if (soc_feature(unit, soc_feature_tsn)) {
   2528         /* Valid check for stat type */
   2529         if (!GH2_TSN_STAT_THRESHOLD_IS_VALID(unit, stat)) {
   2530             return BCM_E_PARAM;
   2531         }
   2532 
   2533         /* Select the source type: Port or SR Flow */
   2534         switch (source) {
   2535             case bcmTsnStatThresholdSourcePort:
   2536                 /*
   2537                  * Get the threshold config for a specific TSN stat
   2538                  * on source port
   2539                  */
   2540                 select_info = gh2_port_count_threshold_info;
   2541                 count = COUNTOF(gh2_port_count_threshold_info);
   2542                 break;
   2543             case bcmTsnStatThresholdSourceSRFlow:
   2544                 /*
   2545                  * Get the threshold config for a specific TSN stat
   2546                  * on source SR flow
   2547                  */
   2548                 select_info = gh2_flow_count_threshold_info;
   2549                 count = COUNTOF(gh2_flow_count_threshold_info);
   2550                 break;
   2551             default:
   2552                 return BCM_E_PARAM;
   2553         }
   2554 
   2555         rv = bcmi_gh2_tsn_stat_threshold_select_get(unit, select_info,
   2556                                                     count, stat, config);
   2557     }
   2558 
   2559     return rv;
   2560 }
   2561 
   2562 /*
   2563  * Function:
   2564  *    bcmi_gh2_tsn_stat_threshold_init
   2565  * Purpose:
   2566  *    Helper function to initialize all TSN counter thresholds
   2567  * Parameters:
   2568  *    unit   - (IN) Unit number
   2569  * Returns:
   2570  *    BCM_E_XXX
   2571  */
   2572 STATIC int
   2573 bcmi_gh2_tsn_stat_threshold_init(int unit)
   2574 {
   2575     int rv = BCM_E_UNAVAIL;
   2576     const bcmi_gh2_tsn_stat_threshold_select_t *info, *select_info;
   2577     bcm_tsn_stat_threshold_config_t config;
   2578     int idx = 0, count = 0;
   2579 
   2580     bcm_tsn_stat_threshold_config_t_init(&config);
   2581     config.threshold = GH2_TSN_STAT_THRESHOLD_DEFAULT_VALUE;
   2582 
   2583     if (soc_feature(unit, soc_feature_tsn)) {
   2584         /* TSN Stat threshold for source Port */
   2585         select_info = gh2_port_count_threshold_info;
   2586         count = COUNTOF(gh2_port_count_threshold_info);
   2587         for (idx = 0; idx < count; idx++) {
   2588             info = select_info + idx;
   2589             rv = bcmi_gh2_tsn_stat_threshold_select_set(unit, select_info,
   2590                                                         count,
   2591                                                         info->stat_type,
   2592                                                         &config);
   2593         }
   2594 
   2595         /* TSN Stat threshold for source SR Flow */
   2596         select_info = gh2_flow_count_threshold_info;
   2597         count = COUNTOF(gh2_flow_count_threshold_info);
   2598         for (idx = 0; idx < count; idx++) {
   2599             info = select_info + idx;
   2600             rv = bcmi_gh2_tsn_stat_threshold_select_set(unit, select_info,
   2601                                                         count,
   2602                                                         info->stat_type,
   2603                                                         &config);
   2604         }
   2605     }
   2606 
   2607     return rv;
   2608 }
   2609 
   2610 /* Per-chip TSN stat portcnt device info */
   2611 STATIC const tsn_stat_portcnt_dev_info_t gh2_tsn_stat_portcnt_dev_info = {
   2612     portcnt_table,
   2613     GH2_TSN_STAT_PORTCNT_TABLE_SIZE
   2614 };
   2615 
   2616 /* Per-chip TSN stat flowcnt device info */
   2617 STATIC const
   2618 tsn_stat_flowcnt_dev_info_t gh2_tsn_stat_flowcnt_dev_info = {
   2619     /* per-chip control drivers */
   2620     bcmi_gh2_tsn_stat_flowcnt_init,
   2621 #if defined(BCM_WARM_BOOT_SUPPORT)
   2622     bcmi_gh2_tsn_stat_flowcnt_get_scache_size,
   2623     bcmi_gh2_tsn_stat_flowcnt_sync,
   2624     bcmi_gh2_tsn_stat_flowcnt_reload_l1,
   2625     bcmi_gh2_tsn_stat_flowcnt_reload_l2,
   2626 #endif /* BCM_WARM_BOOT_SUPPORT */
   2627     bcmi_gh2_tsn_stat_flowcnt_cleanup,
   2628     bcmi_gh2_tsn_stat_flowcnt_counter_sync_all,
   2629     bcmi_gh2_tsn_stat_flowcnt_counter_sync_stat,
   2630     bcmi_gh2_tsn_stat_flowcnt_group_id_encode,
   2631     bcmi_gh2_tsn_stat_flowcnt_group_id_decode,
   2632     bcmi_gh2_tsn_stat_flowcnt_group_refcnt_get,
   2633     bcmi_gh2_tsn_stat_flowcnt_group_enable_value_set,
   2634     bcmi_gh2_tsn_stat_flowcnt_group_enable_value_get,
   2635     bcmi_gh2_tsn_stat_flowcnt_group_enable_value_exist_check,
   2636     bcmi_gh2_tsn_stat_flowcnt_group_enable_value_insert,
   2637     bcmi_gh2_tsn_stat_flowcnt_group_enable_value_delete,
   2638     bcmi_gh2_tsn_stat_flowcnt_group_enable_value_encode,
   2639     bcmi_gh2_tsn_stat_flowcnt_group_enable_value_decode,
   2640     bcmi_gh2_tsn_stat_flowcnt_group_traverse,
   2641     bcmi_gh2_tsn_stat_flowcnt_counter_access,
   2642     bcmi_gh2_tsn_stat_flowcnt_counter_update,
   2643     bcmi_gh2_tsn_stat_flowcnt_flow_set,
   2644     bcmi_gh2_tsn_stat_flowcnt_flow_get,
   2645     bcmi_gh2_tsn_stat_flowcnt_flow_get_fbmp
   2646 };
   2647 
   2648 /* Per-chip TSN stat threshold control drivers */
   2649 STATIC const tsn_stat_threshold_ctrl_info_t gh2_tsn_stat_threshold_ctrl_info =
   2650 {
   2651     bcmi_gh2_tsn_stat_threshold_init,
   2652     bcmi_gh2_tsn_stat_threshold_set,
   2653     bcmi_gh2_tsn_stat_threshold_get
   2654 };
   2655 
   2656 /* Per-chip TSN stat device info */
   2657 STATIC const bcmi_esw_tsn_stat_dev_info_t gh2_tsn_stat_devinfo = {
   2658     &gh2_tsn_stat_portcnt_dev_info,
   2659     &gh2_tsn_stat_flowcnt_dev_info,
   2660     &gh2_tsn_stat_threshold_ctrl_info
   2661 };
   2662 
   2663 /*
   2664  * Function:
   2665  *    bcmi_gh2_tsn_stat_info_init
   2666  * Description:
   2667  *    Setup the chip specific info for TSN stat.
   2668  * Parameters:
   2669  *    unit - (IN) Unit number
   2670  *    devinfo - (OUT) device info structure.
   2671  * Returns:
   2672  *    BCM_E_XXX
   2673  */
   2674 int
   2675 bcmi_gh2_tsn_stat_info_init(
   2676     int unit,
   2677     const bcmi_esw_tsn_stat_dev_info_t **devinfo)
   2678 {
   2679     int rv = BCM_E_NONE;
   2680 
   2681     if (devinfo == NULL) {
   2682         return BCM_E_PARAM;
   2683     }
   2684 
   2685     /* Return the chip info structure for TSN stat */
   2686     *devinfo = &gh2_tsn_stat_devinfo;
   2687 
   2688     return rv;
   2689 }
   2690 
   2691 #endif  /* BCM_GREYHOUND2_SUPPORT && BCM_TSN_SUPPORT */
   2692