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


      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 common functionality for TSN Statistics counter implementation.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 #include <soc/drv.h>
     13 #include <soc/scache.h>
     14 #include <bcm/port.h>
     15 #include <bcm/error.h>
     16 #include <bcm/types.h>
     17 #include <bcm/tsn.h>
     18 #include <bcm_int/esw/tsn.h>
     19 #include <bcm_int/esw/tsn_stat.h>
     20 #include <bcm_int/esw_dispatch.h>
     21 #if defined(BCM_GREYHOUND2_SUPPORT)
     22 #include <bcm_int/esw/greyhound2.h>
     23 #endif /* BCM_GREYHOUND2_SUPPORT */
     24 #include <bcm_int/esw/switch.h>
     25 
     26 #if defined(BCM_TSN_SUPPORT)
     27 /*
     28  * TSN stat type feature mapping
     29  */
     30 STATIC const soc_feature_t tsn_stat_type_feature[bcmTsnStatCount] =
     31 {
     32     soc_feature_tsn_sr, /* bcmTsnStatIngressSrTaggedPackets */
     33     soc_feature_tsn_sr, /* bcmTsnStatIngressNonLinkLocalPackets */
     34     soc_feature_tsn_sr, /* bcmTsnStatIngressSrWrongLanPackets */
     35     soc_feature_tsn_sr, /* bcmTsnStatIngressSrRxErrorPackets */
     36     soc_feature_tsn_sr, /* bcmTsnStatIngressSrTagErrorPackets */
     37     soc_feature_tsn_sr, /* bcmTsnStatIngressSrDuplicatePackets */
     38     soc_feature_tsn_sr, /* bcmTsnStatIngressSrOutOfOrderSrPackets */
     39     soc_feature_tsn_sr, /* bcmTsnStatIngressSrOwnRxPackets */
     40     soc_feature_tsn_sr, /* bcmTsnStatIngressSrUnexpectedPackets */
     41     soc_feature_tsn_mtu_stu, /* bcmTsnStatIngressMtuErrorPackets */
     42     soc_feature_tsn_mtu_stu, /* bcmTsnStatIngressStuErrorPackets */
     43     soc_feature_tsn_sr, /* bcmTsnStatIngressSrAcceptedSrPackets */
     44     soc_feature_tsn_sr, /* bcmTsnStatIngressSrSaSrcFilteredPackets */
     45     soc_feature_tsn_taf, /* bcmTsnStatIngressTafMeterDrop */
     46     soc_feature_tsn_taf, /* bcmTsnStatIngressTafGatePass */
     47     soc_feature_tsn_taf, /* bcmTsnStatIngressTafGateCloseDrop */
     48     soc_feature_tsn_taf, /* bcmTsnStatIngressTafGateNoByteDrop */
     49     soc_feature_tsn_taf, /* bcmTsnStatIngressTafMtuPass */
     50     soc_feature_tsn_sr, /* bcmTsnStatEgressSrTaggedPackets */
     51     soc_feature_tsn_sr, /* bcmTsnStatEgressNonLinkLocalPackets */
     52     soc_feature_tsn_mtu_stu, /* bcmTsnStatEgressMtuErrorPackets */
     53     soc_feature_tsn_mtu_stu /* bcmTsnStatEgressStuErrorPackets */
     54 };
     55 
     56 /*
     57  * TSN stat portcnt member list data structure
     58  */
     59 typedef struct bcmi_tsn_stat_portcnt_member_s {
     60     soc_mem_t mem;
     61     soc_field_t field;
     62     uint64 *port_counter_hw;
     63     uint64 *port_counter_sw;
     64 } bcmi_tsn_stat_portcnt_member_t;
     65 
     66 /*
     67  * TSN stat portcnt table entry data structure for temporary access
     68  */
     69 typedef struct bcmi_tsn_stat_portcnt_table_entry_s {
     70     uint32 entry_data[SOC_MAX_MEM_WORDS];
     71 } bcmi_tsn_stat_portcnt_table_entry_t;
     72 
     73 /*
     74  * Software book keeping for TSN stat portcnt related information:
     75  * - enabled matrix for extra counter callback(thread)
     76  */
     77 typedef struct bcmi_tsn_stat_portcnt_bk_info_s {
     78     SHR_BITDCL *stat_bitmap;      /* TSN Portcnt Stat bitmap [stats] */
     79     SHR_BITDCL *stat_port_bitmap; /* TSN Portcnt Port bitmap [stats * ports] */
     80     int num_port;
     81 } bcmi_tsn_stat_portcnt_bk_info_t;
     82 
     83 /*
     84  * TSN stat portcnt control data structure
     85  */
     86 typedef struct bcmi_tsn_stat_portcnt_control_s {
     87     sal_mutex_t portcnt_mutex;
     88     bcmi_tsn_stat_portcnt_member_t *stats;
     89     bcmi_tsn_stat_portcnt_table_entry_t *portcnt_entry_temp;
     90     bcmi_tsn_stat_portcnt_bk_info_t *portcnt_bk_info;
     91 } bcmi_tsn_stat_portcnt_control_t;
     92 
     93 /*
     94  * TSN stat flowcnt control data structure
     95  */
     96 typedef struct bcmi_tsn_stat_flowcnt_control_s {
     97     sal_mutex_t flowcnt_mutex;
     98 } bcmi_tsn_stat_flowcnt_control_t;
     99 
    100 /*
    101  * TSN stat control data structure
    102  */
    103 typedef struct bcmi_tsn_stat_control_s {
    104     /* TSN stat related control structures defined below */
    105     bcmi_tsn_stat_portcnt_control_t *portcnt_control;
    106     bcmi_tsn_stat_flowcnt_control_t *flowcnt_control;
    107     /* TSN stat device info for chip specific */
    108     const bcmi_esw_tsn_stat_dev_info_t *tsn_stat_dev_info;
    109 } bcmi_tsn_stat_control_t;
    110 
    111 /* TSN stat control */
    112 STATIC bcmi_tsn_stat_control_t *tsn_stat_control[BCM_MAX_NUM_UNITS];
    113 
    114 /* Global initialized parameter for TSN stat */
    115 STATIC uint8 tsn_stat_initialized = 0;
    116 
    117 static soc_ser_tsn_stat_functions_t ser_tsn_stat_functions;
    118 
    119 /*
    120  * Macro:
    121  *    TSN_STAT_PORTCNT_IS_INIT (internal)
    122  * Purpose:
    123  *    Check that the unit is valid and confirm that
    124  *    the TSN Port Stat functions are initialized.
    125  * Parameters:
    126  *    unit - BCM device number
    127  * Notes:
    128  *    Results in return (BCM_E_UNIT), return (BCM_E_UNAVAIL), or
    129  *    return (BCM_E_INIT) if fails.
    130  */
    131 #define TSN_STAT_PORTCNT_IS_INIT(_unit_)                         \
    132     do {                                                         \
    133         if (!soc_feature(_unit_, soc_feature_tsn)) {             \
    134             return BCM_E_UNAVAIL;                                \
    135         }                                                        \
    136         if (NULL == tsn_stat_control[_unit_]) {                  \
    137             LOG_ERROR(BSL_LS_BCM_TSN,                            \
    138                       (BSL_META_U(_unit_,                        \
    139                                   "TSN stat control Error: "     \
    140                                   "not initialized\n")));        \
    141             return BCM_E_INIT;                                   \
    142         }                                                        \
    143         if (NULL == tsn_stat_control[_unit_]->portcnt_control) { \
    144             LOG_ERROR(BSL_LS_BCM_TSN,                            \
    145                       (BSL_META_U(_unit_,                        \
    146                                   "TSN portcnt control Error: "  \
    147                                   "not initialized\n")));        \
    148             return BCM_E_INIT;                                   \
    149         }                                                        \
    150     } while (0)
    151 
    152 /*
    153  * Macro:
    154  *    TSN_STAT_PORTCNT_IS_INIT (internal)
    155  * Purpose:
    156  *    Check that the unit is valid and confirm that
    157  *    the TSN Port Stat functions are initialized.
    158  * Parameters:
    159  *    unit - BCM device number
    160  * Notes:
    161  *    Results in return (BCM_E_UNIT), return (BCM_E_UNAVAIL), or
    162  *    return (BCM_E_INIT) if fails.
    163  */
    164 #define TSN_STAT_FLOWCNT_IS_INIT(_unit_)                         \
    165     do {                                                         \
    166         if (!soc_feature(_unit_, soc_feature_tsn)) {             \
    167             return BCM_E_UNAVAIL;                                \
    168         }                                                        \
    169         if (NULL == tsn_stat_control[_unit_]) {                  \
    170             LOG_ERROR(BSL_LS_BCM_TSN,                            \
    171                       (BSL_META_U(_unit_,                        \
    172                                   "TSN stat control Error: "     \
    173                                   "not initialized\n")));        \
    174             return BCM_E_INIT;                                   \
    175         }                                                        \
    176         if (NULL == tsn_stat_control[_unit_]->flowcnt_control) { \
    177             LOG_ERROR(BSL_LS_BCM_TSN,                            \
    178                       (BSL_META_U(_unit_,                        \
    179                                   "TSN flowcnt control Error: "  \
    180                                   "not initialized\n")));        \
    181             return BCM_E_INIT;                                   \
    182         }                                                        \
    183     } while (0)
    184 
    185 
    186 /* TSN stat mutex lock and unlock */
    187 #define TSN_STAT_PORTCNT_LOCK(pc) \
    188         sal_mutex_take((pc)->portcnt_mutex, sal_mutex_FOREVER)
    189 #define TSN_STAT_PORTCNT_UNLOCK(pc) \
    190         sal_mutex_give((pc)->portcnt_mutex)
    191 #define TSN_STAT_FLOWCNT_LOCK(fc) \
    192             sal_mutex_take((fc)->flowcnt_mutex, sal_mutex_FOREVER)
    193 #define TSN_STAT_FLOWCNT_UNLOCK(fc) \
    194             sal_mutex_give((fc)->flowcnt_mutex)
    195 
    196 /*
    197  * Enabled matrix for TSN Portcnt Stat usage bitmap operations
    198  * - if any port is enabled
    199  */
    200 #define TSN_STAT_PORTCNT_USED_GET(portcnt_bk_info, stat) \
    201     (((portcnt_bk_info)->stat_bitmap) ? \
    202      SHR_BITGET((portcnt_bk_info)->stat_bitmap, (stat)) : 0)
    203 #define TSN_STAT_PORTCNT_USED_SET(portcnt_bk_info, stat) \
    204     SHR_BITSET((portcnt_bk_info)->stat_bitmap, (stat))
    205 #define TSN_STAT_PORTCNT_USED_CLR(portcnt_bk_info, stat) \
    206     SHR_BITCLR((portcnt_bk_info)->stat_bitmap, (stat))
    207 
    208 /*
    209  * Enabled matrix for TSN Portcnt Port usage bitmap operations
    210  * with specified TSN stat
    211  */
    212 #define TSN_STAT_PORTCNT_PORT_USED_GET(portcnt_bk_info, stat, port) \
    213     (((portcnt_bk_info)->stat_port_bitmap) ? \
    214      SHR_BITGET((portcnt_bk_info)->stat_port_bitmap, \
    215      ((stat * (portcnt_bk_info)->num_port) + port)) : 0)
    216 #define TSN_STAT_PORTCNT_PORT_USED_SET(portcnt_bk_info, stat, port) \
    217     SHR_BITSET((portcnt_bk_info)->stat_port_bitmap, \
    218                ((stat * (portcnt_bk_info)->num_port) + port))
    219 #define TSN_STAT_PORTCNT_PORT_USED_CLR(portcnt_bk_info, stat, port) \
    220     SHR_BITCLR((portcnt_bk_info)->stat_port_bitmap, \
    221                ((stat * (portcnt_bk_info)->num_port) + port))
    222 
    223 /* TSN stat type validation */
    224 #define TSN_STAT_IS_VALID(unit, type)                  \
    225         ((type >= bcmTsnStatIngressSrTaggedPackets) && \
    226          (type < bcmTsnStatCount))
    227 
    228 /* helper macro to execute dispatched specific device function */
    229 #define TSN_STAT_FLOWCNT_FUNC(_name_, _args_)                                \
    230         ((NULL == tsn_stat_control[unit]->tsn_stat_dev_info->                \
    231          tsn_stat_flowcnt_dev_info->tsn_stat_flowcnt_##_name_) ? BCM_E_INIT :\
    232          (tsn_stat_control[unit]->tsn_stat_dev_info->                        \
    233           tsn_stat_flowcnt_dev_info->tsn_stat_flowcnt_##_name_)_args_)
    234 
    235 
    236 /*
    237  * Function:
    238  *    tsn_stat_control_instance_get
    239  * Description:
    240  *    Helper function to retrieve TSN stat control pointer
    241  * Parameters:
    242  *    unit  - (IN) BCM device number
    243  *    tc   - (OUT) TSN stat control data structure
    244  * Returns:
    245  *    BCM_E_XXX
    246  */
    247 STATIC int
    248 tsn_stat_control_instance_get(
    249     int unit,
    250     bcmi_tsn_stat_control_t **tc)
    251 {
    252     /* Input parameter check. */
    253     if (NULL == tc) {
    254         return BCM_E_PARAM;
    255     }
    256 
    257     /* Check if TSN feature supported and initialized for TSN stat */
    258     if (!soc_feature(unit, soc_feature_tsn)) {
    259         return BCM_E_UNAVAIL;
    260     }
    261     if (NULL == tsn_stat_control[unit]) {
    262         LOG_ERROR(BSL_LS_BCM_TSN,
    263                   (BSL_META_U(unit,
    264                               "TSN stat control Error: "
    265                               "not initialized\n")));
    266         return BCM_E_INIT;
    267     }
    268     if (NULL == tsn_stat_control[unit]->tsn_stat_dev_info) {
    269         LOG_ERROR(BSL_LS_BCM_TSN,
    270                   (BSL_META_U(unit,
    271                               "TSN stat dev info Error: "
    272                               "not initialized\n")));
    273         return BCM_E_INIT;
    274     }
    275 
    276     /* Fill info structure. */
    277     *tc = tsn_stat_control[unit];
    278 
    279     return BCM_E_NONE;
    280 }
    281 
    282 /*
    283  * Function:
    284  *    tsn_stat_portcnt_control_instance_get
    285  * Description:
    286  *    Helper function to retrieve TSN stat portcnt control pointer
    287  * Parameters:
    288  *    unit  - (IN) BCM device number
    289  *    pc   - (OUT) TSN port stat control data structure
    290  * Returns:
    291  *    BCM_E_XXX
    292  */
    293 STATIC int
    294 tsn_stat_portcnt_control_instance_get(
    295     int unit,
    296     bcmi_tsn_stat_portcnt_control_t **pc)
    297 {
    298     /* Input parameter check. */
    299     if (NULL == pc) {
    300         return BCM_E_PARAM;
    301     }
    302 
    303     /* Check if TSN feature supported and initialized for TSN portcnt */
    304     TSN_STAT_PORTCNT_IS_INIT(unit);
    305 
    306     /* Fill info structure. */
    307     *pc = tsn_stat_control[unit]->portcnt_control;
    308 
    309     return BCM_E_NONE;
    310 }
    311 
    312 /*
    313  * Function:
    314  *    tsn_stat_flowcnt_control_instance_get
    315  * Description:
    316  *    Helper function to retrieve TSN stat flowcnt control pointer
    317  * Parameters:
    318  *    unit  - (IN) BCM device number
    319  *    fc   - (OUT) TSN flow stat control data structure
    320  * Returns:
    321  *    BCM_E_XXX
    322  */
    323 STATIC int
    324 tsn_stat_flowcnt_control_instance_get(
    325     int unit,
    326     bcmi_tsn_stat_flowcnt_control_t **fc)
    327 {
    328     /* Input parameter check. */
    329     if (NULL == fc) {
    330         return BCM_E_PARAM;
    331     }
    332 
    333     /* Check if TSN feature supported and initialized for TSN portcnt */
    334     TSN_STAT_FLOWCNT_IS_INIT(unit);
    335 
    336     /* Fill info structure. */
    337     *fc = tsn_stat_control[unit]->flowcnt_control;
    338 
    339     return BCM_E_NONE;
    340 }
    341 
    342 /*
    343  * Function:
    344  *    bcmi_esw_tsn_stat_gport_validate
    345  * Description:
    346  *    Helper function to validate port/gport parameter
    347  * Parameters:
    348  *    unit  - (IN) BCM device number
    349  *    port_in  - (IN) Port / Gport to validate
    350  *    port_out - (OUT) Port number if valid.
    351  * Returns:
    352  *    BCM_E_NONE - Port OK
    353  *    BCM_E_INIT - Not initialized
    354  *    BCM_E_PORT - Port Invalid
    355  */
    356 STATIC int
    357 bcmi_esw_tsn_stat_gport_validate(
    358     int unit,
    359     bcm_port_t port_in,
    360     bcm_port_t *port_out)
    361 {
    362     /* Input parameter check. */
    363     if (NULL == port_out) {
    364         return BCM_E_PARAM;
    365     }
    366 
    367     if (BCM_GPORT_IS_SET(port_in)) {
    368         BCM_IF_ERROR_RETURN(
    369             bcm_esw_port_local_get(unit, port_in, port_out));
    370     } else if (SOC_PORT_VALID(unit, port_in) &&
    371                SOC_PBMP_MEMBER(PBMP_ALL(unit), port_in)) {
    372         *port_out = port_in;
    373     } else {
    374         return BCM_E_PORT;
    375     }
    376 
    377     return BCM_E_NONE;
    378 }
    379 
    380 #ifdef BCM_WARM_BOOT_SUPPORT
    381 /*
    382  * Function:
    383  *    bcmi_esw_tsn_stat_portcnt_sync
    384  * Purpose:
    385  *    Synchronize the TSN Portcnt Stat/Port sw bitmap into scache
    386  * Parameters:
    387  *    unit - (IN) Unit number
    388  * Returns:
    389  *    BCM_E_xxx
    390  */
    391 int
    392 bcmi_esw_tsn_stat_portcnt_sync(int unit)
    393 {
    394     bcmi_tsn_stat_control_t *tc;
    395     bcmi_tsn_stat_portcnt_control_t *pc;
    396     bcmi_tsn_stat_portcnt_member_t *portcnt_member;
    397     bcmi_tsn_stat_portcnt_bk_info_t *portcnt_bk_info;
    398     const bcmi_esw_tsn_stat_dev_info_t *tsn_stat_dev_info;
    399     const tsn_stat_portcnt_dev_info_t *portcnt_dev_info;
    400     int num_stat;
    401     int num_stat_port;
    402     soc_scache_handle_t scache_handle;
    403     uint8 *portcnt_scache_ptr;
    404     uint32 portcnt_scache_size;
    405     int i, p, num_port;
    406 
    407     /* Get TSN stat control */
    408     BCM_IF_ERROR_RETURN(
    409         tsn_stat_control_instance_get(unit, &tc));
    410 
    411     /* Get portcnt control */
    412     BCM_IF_ERROR_RETURN(
    413         tsn_stat_portcnt_control_instance_get(unit, &pc));
    414 
    415     /* Get chip specific info for TSN stat portcnt */
    416     tsn_stat_dev_info = tc->tsn_stat_dev_info;
    417     portcnt_dev_info = tsn_stat_dev_info->tsn_stat_portcnt_dev_info;
    418     portcnt_bk_info = pc->portcnt_bk_info;
    419 
    420     /* Get num_stat  */
    421     num_stat = portcnt_dev_info->num_stats;
    422     /* Get num_stat_port */
    423     num_stat_port = (num_stat * portcnt_bk_info->num_port);
    424 
    425     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN,
    426                           BCM_TSN_WB_SCACHE_PART_TSN_STAT_PORTCNT);
    427     /* allocate the scache pointer size */
    428     /* TSN portcnt stat_bitmap and stat_port_bitmap */
    429     portcnt_scache_size = SHR_BITALLOCSIZE(num_stat) +
    430                           SHR_BITALLOCSIZE(num_stat_port);
    431 
    432     /* TSN Port Stat counter port_counter_hw and port_counter_sw */
    433     portcnt_member = &pc->stats[0];
    434     num_port = soc_mem_index_count(unit, portcnt_member->mem);
    435     portcnt_scache_size += (num_stat * (num_port * sizeof(uint64)) * 2);
    436 
    437     BCM_IF_ERROR_RETURN(
    438         _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
    439                                 portcnt_scache_size, &portcnt_scache_ptr,
    440                                 BCM_TSN_WB_DEFAULT_VERSION, NULL));
    441     if (NULL == portcnt_scache_ptr) {
    442         LOG_VERBOSE(BSL_LS_BCM_TSN,
    443                     (BSL_META_U(unit,
    444                                 "SCACHE Memory not available \n")));
    445         return BCM_E_MEMORY;
    446     }
    447 
    448     TSN_STAT_PORTCNT_LOCK(pc);
    449 
    450     /* TSN portcnt stat_bitmap */
    451     SHR_BITCOPY_RANGE((SHR_BITDCL *)(portcnt_scache_ptr), 0,
    452                       portcnt_bk_info->stat_bitmap, 0, num_stat);
    453     portcnt_scache_ptr += SHR_BITALLOCSIZE(num_stat);
    454 
    455     /* TSN portcnt stat_port_bitmap */
    456     SHR_BITCOPY_RANGE((SHR_BITDCL *)(portcnt_scache_ptr), 0,
    457                       portcnt_bk_info->stat_port_bitmap, 0, num_stat_port);
    458     portcnt_scache_ptr += SHR_BITALLOCSIZE(num_stat_port);
    459 
    460     /* TSN Port Stat counter for port_counter_hw and port_counter_sw */
    461     for (i = 0; i < num_stat; i++) {
    462         portcnt_member = &pc->stats[i];
    463         num_port = soc_mem_index_count(unit, portcnt_member->mem);
    464 
    465         for (p = 0; p < num_port; p++) {
    466             /* TSN Port Stat counter port_counter_hw */
    467             sal_memcpy(portcnt_scache_ptr,
    468                        &(portcnt_member->port_counter_hw[p]), sizeof(uint64));
    469             portcnt_scache_ptr += sizeof(uint64);
    470             /* TSN Port Stat counter port_counter_sw */
    471             sal_memcpy(portcnt_scache_ptr,
    472                        &(portcnt_member->port_counter_sw[p]), sizeof(uint64));
    473             portcnt_scache_ptr += sizeof(uint64);
    474         }
    475     }
    476 
    477     TSN_STAT_PORTCNT_UNLOCK(pc);
    478 
    479     return BCM_E_NONE;
    480 }
    481 
    482 /*
    483  * Function:
    484  *    bcmi_esw_tsn_stat_portcnt_reload
    485  * Purpose:
    486  *    Reload the scache data into TSN Portcnt Stat/Port sw bitmap
    487  * Parameters:
    488  *    unit - (IN) Unit number
    489  * Returns:
    490  *    BCM_E_xxx
    491  */
    492 int
    493 bcmi_esw_tsn_stat_portcnt_reload(int unit)
    494 {
    495     int rv = BCM_E_NONE;
    496     bcmi_tsn_stat_control_t *tc;
    497     bcmi_tsn_stat_portcnt_control_t *pc;
    498     bcmi_tsn_stat_portcnt_member_t *portcnt_member;
    499     bcmi_tsn_stat_portcnt_bk_info_t *portcnt_bk_info;
    500     const bcmi_esw_tsn_stat_dev_info_t *tsn_stat_dev_info;
    501     const tsn_stat_portcnt_dev_info_t *portcnt_dev_info;
    502     int num_stat;
    503     int num_stat_port;
    504     soc_scache_handle_t scache_handle;
    505     uint8 *portcnt_scache_ptr;
    506     int i, p, num_port;
    507 
    508     LOG_DEBUG(BSL_LS_BCM_TSN,
    509               (BSL_META_U(unit,
    510                          "bcmi_esw_tsn_stat_portcnt_reload\n")));
    511 
    512     /* Get TSN stat control */
    513     BCM_IF_ERROR_RETURN(
    514         tsn_stat_control_instance_get(unit, &tc));
    515 
    516     /* Get portcnt control */
    517     BCM_IF_ERROR_RETURN(
    518         tsn_stat_portcnt_control_instance_get(unit, &pc));
    519 
    520     /* Get chip specific info for TSN stat portcnt */
    521     tsn_stat_dev_info = tc->tsn_stat_dev_info;
    522     portcnt_dev_info = tsn_stat_dev_info->tsn_stat_portcnt_dev_info;
    523     portcnt_bk_info = pc->portcnt_bk_info;
    524 
    525     /* Get num_stat  */
    526     num_stat = portcnt_dev_info->num_stats;
    527     /* Get num_stat_port */
    528     num_stat_port = (num_stat * portcnt_bk_info->num_port);
    529 
    530     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN,
    531                           BCM_TSN_WB_SCACHE_PART_TSN_STAT_PORTCNT);
    532     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    533                                  0, &portcnt_scache_ptr,
    534                                  BCM_TSN_WB_DEFAULT_VERSION, NULL);
    535 
    536     if (rv == BCM_E_NOT_FOUND) {
    537         portcnt_scache_ptr = NULL;
    538         rv = BCM_E_NONE;
    539     } else if (BCM_FAILURE(rv)) {
    540         return rv;
    541     }
    542 
    543     if (portcnt_scache_ptr != NULL) {
    544         /* TSN portcnt stat_bitmap */
    545         SHR_BITCOPY_RANGE(portcnt_bk_info->stat_bitmap, 0,
    546                           (SHR_BITDCL *)(portcnt_scache_ptr), 0,
    547                           num_stat);
    548         portcnt_scache_ptr += SHR_BITALLOCSIZE(num_stat);
    549 
    550         /* TSN portcnt stat_port_bitmap */
    551         SHR_BITCOPY_RANGE(portcnt_bk_info->stat_port_bitmap, 0,
    552                           (SHR_BITDCL *)(portcnt_scache_ptr), 0,
    553                           num_stat_port);
    554         portcnt_scache_ptr += SHR_BITALLOCSIZE(num_stat_port);
    555 
    556         /* TSN Port Stat counter for port_counter_hw and port_counter_sw */
    557         for (i = 0; i < num_stat; i++) {
    558             portcnt_member = &pc->stats[i];
    559             num_port = soc_mem_index_count(unit, portcnt_member->mem);
    560 
    561             for (p = 0; p < num_port; p++) {
    562                 /* TSN Port Stat counter port_counter_hw */
    563                 sal_memcpy(&(portcnt_member->port_counter_hw[p]),
    564                            portcnt_scache_ptr, sizeof(uint64));
    565                 portcnt_scache_ptr += sizeof(uint64);
    566                 /* TSN Port Stat counter port_counter_sw */
    567                 sal_memcpy(&(portcnt_member->port_counter_sw[p]),
    568                            portcnt_scache_ptr, sizeof(uint64));
    569                 portcnt_scache_ptr += sizeof(uint64);
    570             }
    571         }
    572     }
    573 
    574     return rv;
    575 }
    576 
    577 /*
    578  * Function:
    579  *    bcmi_esw_tsn_stat_flowcnt_sync
    580  * Purpose:
    581  *    Synchronize the TSN Flowcnt Stat into scache
    582  * Parameters:
    583  *    unit - (IN) Unit number
    584  * Returns:
    585  *    BCM_E_xxx
    586  */
    587 int
    588 bcmi_esw_tsn_stat_flowcnt_sync(int unit)
    589 {
    590     int rv = BCM_E_NONE;
    591     bcmi_tsn_stat_flowcnt_control_t *fc;
    592     soc_scache_handle_t scache_handle;
    593     uint8 *scache_ptr;
    594     int scache_size;
    595 
    596     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN,
    597                           BCM_TSN_WB_SCACHE_PART_TSN_STAT_FLOWCNT);
    598 
    599     BCM_IF_ERROR_RETURN(
    600         tsn_stat_flowcnt_control_instance_get(unit, &fc));
    601 
    602     TSN_STAT_FLOWCNT_LOCK(fc);
    603     rv = TSN_STAT_FLOWCNT_FUNC(get_scache_size, (unit, &scache_size));
    604 
    605     if (BCM_SUCCESS(rv)) {
    606         rv = _bcm_esw_scache_ptr_get(
    607                  unit, scache_handle, TRUE,
    608                  scache_size,
    609                  &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL);
    610     }
    611 
    612     if (BCM_SUCCESS(rv)) {
    613         rv = TSN_STAT_FLOWCNT_FUNC(sync, (unit, scache_ptr));
    614     }
    615     TSN_STAT_FLOWCNT_UNLOCK(fc);
    616 
    617     return rv;
    618 }
    619 
    620 /*
    621  * Function:
    622  *    bcmi_esw_tsn_stat_flowcnt_reload
    623  * Purpose:
    624  *    Reload the scache data into TSN Flowcnt Stat
    625  * Parameters:
    626  *    unit - (IN) Unit number
    627  * Returns:
    628  *    BCM_E_xxx
    629  */
    630 int
    631 bcmi_esw_tsn_stat_flowcnt_reload(int unit)
    632 {
    633     int rv = BCM_E_NONE;
    634     bcmi_tsn_stat_flowcnt_control_t *fc;
    635     soc_scache_handle_t scache_handle;
    636     uint8 *scache_ptr;
    637     int scache_size;
    638 
    639     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN,
    640                           BCM_TSN_WB_SCACHE_PART_TSN_STAT_FLOWCNT);
    641 
    642     BCM_IF_ERROR_RETURN(
    643         tsn_stat_flowcnt_control_instance_get(unit, &fc));
    644 
    645     TSN_STAT_FLOWCNT_LOCK(fc);
    646     rv = TSN_STAT_FLOWCNT_FUNC(get_scache_size, (unit, &scache_size));
    647 
    648     if (BCM_SUCCESS(rv)) {
    649         rv = _bcm_esw_scache_ptr_get(
    650                  unit, scache_handle, FALSE,
    651                  scache_size,
    652                  &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL);
    653     }
    654 
    655     if (BCM_E_NOT_FOUND == rv) {
    656         /* proceed with Level 1 Warm Boot */
    657         rv = TSN_STAT_FLOWCNT_FUNC(reload_l1, (unit));
    658     } else if (BCM_E_NONE == rv) {
    659         if (NULL == scache_ptr) {
    660             rv = BCM_E_INTERNAL;
    661         } else {
    662             rv = TSN_STAT_FLOWCNT_FUNC(reload_l2, (unit, scache_ptr));
    663         }
    664     }
    665     TSN_STAT_FLOWCNT_UNLOCK(fc);
    666 
    667     return rv;
    668 }
    669 #endif /* BCM_WARM_BOOT_SUPPORT */
    670 
    671 /*
    672  * Function:
    673  *    bcmi_esw_tsn_stat_portcnt_collect
    674  * Description:
    675  *    TSN Port Counter accumulation routine called periodically
    676  *    to sync s/w copy with h/w copy.
    677  * Parameters:
    678  *    unit - (IN) Unit number
    679  *    mem -  (IN) TSN port stat counter memory (if -1 for all memories)
    680  *    counter_idx - (IN) counter index (port index).
    681  *                  if -1 accumulate for all counters (for ports)
    682  *                  else retrieve a specific counter (one port).
    683  * Returns:
    684  *    None
    685  * Notes:
    686  */
    687 STATIC void
    688 bcmi_esw_tsn_stat_portcnt_collect(
    689     int unit,
    690     soc_mem_t mem,
    691     int counter_idx)
    692 {
    693     uint32 mem_index_min;
    694     int mem_index_max;
    695     uint32 packet_count_hw[2];
    696     uint64 new_packet_count;
    697     uint64 prev_packet_count;
    698     uint64 max_packet_size;
    699     soc_memacc_t memacc_pkt;
    700     soc_mem_t l_mem;
    701     soc_field_t l_field;
    702     int i, index, width;
    703     bcmi_tsn_stat_control_t *tc;
    704     bcmi_tsn_stat_portcnt_control_t *pc;
    705     bcmi_tsn_stat_portcnt_member_t *portcnt_member;
    706     bcmi_tsn_stat_portcnt_table_entry_t *portcnt_entry_temp;
    707     const bcmi_esw_tsn_stat_dev_info_t *tsn_stat_dev_info;
    708     const tsn_stat_portcnt_dev_info_t *portcnt_dev_info;
    709     uint32 *portcnt_entry_temp_ptr_start, *portcnt_entry_temp_ptr;
    710     int entry_words;
    711 
    712     /* Get TSN stat control */
    713     (void)tsn_stat_control_instance_get(unit, &tc);
    714     if (NULL == tc) {
    715         return;
    716     }
    717 
    718     /* Get chip specific info for TSN stat */
    719     tsn_stat_dev_info = tc->tsn_stat_dev_info;
    720     if (NULL == tsn_stat_dev_info) {
    721         return;
    722     }
    723     portcnt_dev_info = tsn_stat_dev_info->tsn_stat_portcnt_dev_info;
    724     if (NULL == portcnt_dev_info) {
    725         return;
    726     }
    727 
    728     /* Get portcnt control */
    729     (void)tsn_stat_portcnt_control_instance_get(unit, &pc);
    730     if (NULL == pc) {
    731         return;
    732     }
    733 
    734     COMPILER_64_ZERO(new_packet_count);
    735     COMPILER_64_ZERO(prev_packet_count);
    736     COMPILER_64_ZERO(max_packet_size);
    737 
    738     l_mem = pc->stats[0].mem;
    739     l_field = pc->stats[0].field;
    740     /* Get the packet count field width for this device */
    741     width = soc_mem_field_length(unit, l_mem, l_field);
    742 
    743     /* Hardware support maximum packet size */
    744     COMPILER_64_SET(max_packet_size, 0, 1);
    745     COMPILER_64_SHL(max_packet_size, width);
    746 
    747     portcnt_entry_temp = pc->portcnt_entry_temp;
    748     portcnt_entry_temp_ptr_start = &(portcnt_entry_temp[0].entry_data[0]);
    749     for (i = 0; i < portcnt_dev_info->num_stats; i++) {
    750         /* Check if the matrix of (stats) is enabled for portcnt callback */
    751         if (!TSN_STAT_PORTCNT_USED_GET(pc->portcnt_bk_info, i)) {
    752             continue;
    753         }
    754 
    755         l_mem = pc->stats[i].mem;
    756         l_field = pc->stats[i].field;
    757 
    758         /* Get entry_words for each memory */
    759         entry_words = soc_mem_entry_words(unit, l_mem);
    760         if ((mem == -1) || (l_mem == mem)) {
    761             portcnt_member = &pc->stats[i];
    762 
    763             mem_index_min = soc_mem_index_min(unit, l_mem);
    764             mem_index_max = soc_mem_index_max(unit, l_mem);
    765 
    766             /*
    767              * If counter_idx != -1, retrieve specific
    768              * counter index from the flex counter memory pool.
    769              */
    770             if (counter_idx != -1) {
    771                 if ((counter_idx < mem_index_min) ||
    772                     (counter_idx > mem_index_max)) {
    773                     return;
    774                 }
    775                 mem_index_min = mem_index_max = counter_idx;
    776             }
    777 
    778             /* Read all the counters or a specific counter from memory */
    779             if (counter_idx == -1) {
    780                 if (soc_mem_read_range(unit, l_mem, MEM_BLOCK_ANY,
    781                                        mem_index_min, mem_index_max,
    782                                        portcnt_entry_temp_ptr_start) !=
    783                                        BCM_E_NONE) {
    784                     LOG_ERROR(BSL_LS_BCM_TSN,
    785                               (BSL_META_U(unit,
    786                                           "Unable to read a range of mem: "
    787                                           "%s\n"),
    788                               SOC_MEM_UFNAME(unit, l_mem)));
    789                     return;
    790                 }
    791             } else {
    792                 portcnt_entry_temp_ptr =
    793                     (portcnt_entry_temp_ptr_start + (entry_words * counter_idx));
    794                 if (soc_mem_read(unit, l_mem, MEM_BLOCK_ANY,
    795                                  counter_idx,
    796                                  portcnt_entry_temp_ptr) != BCM_E_NONE) {
    797                     LOG_ERROR(BSL_LS_BCM_TSN,
    798                               (BSL_META_U(unit,
    799                                           "Unable to read mem: %s\n"),
    800                               SOC_MEM_UFNAME(unit, l_mem)));
    801                     return;
    802                 }
    803             }
    804 
    805             /* Get a (memory, field) access information structure */
    806             if (soc_memacc_init(unit, l_mem, l_field, &memacc_pkt)) {
    807                 LOG_ERROR(BSL_LS_BCM_TSN,
    808                           (BSL_META_U(unit,
    809                                       "Invalid mem: %s or field: %s\n"),
    810                           SOC_MEM_UFNAME(unit, l_mem),
    811                           SOC_FIELD_NAME(unit, l_field)));
    812                 return;
    813             }
    814 
    815             for (index = mem_index_min; index <= mem_index_max; index++) {
    816                 /*
    817                  * Check if the matrix of (stat, port) is enabled
    818                  * for portcnt callback
    819                  */
    820                 if (!TSN_STAT_PORTCNT_PORT_USED_GET(pc->portcnt_bk_info,
    821                                                     i, index)) {
    822                     continue;
    823                 }
    824 
    825                 portcnt_entry_temp_ptr =
    826                     (portcnt_entry_temp_ptr_start + (entry_words * index));
    827                 soc_memacc_field_get(&memacc_pkt,
    828                                      portcnt_entry_temp_ptr,
    829                                      packet_count_hw);
    830 
    831                 /* Set current hw counter into 64-bit new_packet_count */
    832                 if (width > 32) {
    833                     /* 64-bit field */
    834                     COMPILER_64_SET(new_packet_count,
    835                                     packet_count_hw[1],
    836                                     packet_count_hw[0]);
    837                 } else {
    838                      /* 32-bit field */
    839                     COMPILER_64_SET(new_packet_count,
    840                                     0,
    841                                     packet_count_hw[0]);
    842                 }
    843 
    844                 /* Set previous hw counter into prev_packet_count */
    845                 COMPILER_64_COPY(prev_packet_count,
    846                                  portcnt_member->port_counter_hw[index]);
    847 
    848                 /* Compare old and new hardware counter */
    849                 if (!COMPILER_64_EQ(prev_packet_count, new_packet_count)) {
    850                     LOG_VERBOSE(BSL_LS_BCM_TSN,
    851                                 (BSL_META_U(unit,
    852                                             "Port %d: TSN stat(%d)==>"
    853                                             "Old Packet Count Value %x:%x\t"
    854                                             "New Packet Count Value %x:%x\n"),
    855                                 index, i,
    856                                 COMPILER_64_HI(prev_packet_count),
    857                                 COMPILER_64_LO(prev_packet_count),
    858                                 COMPILER_64_HI(new_packet_count),
    859                                 COMPILER_64_LO(new_packet_count)));
    860                     /* Update Soft Copy for current HW counter */
    861                     COMPILER_64_COPY(portcnt_member->port_counter_hw[index],
    862                                      new_packet_count);
    863                 }
    864 
    865                 /*
    866                  * Calculate the differences between new and previous
    867                  * packet counters
    868                  */
    869                 if (COMPILER_64_GT(prev_packet_count, new_packet_count)) {
    870                     /* Roll over case */
    871                     LOG_VERBOSE(BSL_LS_BCM_TSN,
    872                                 (BSL_META_U(unit,
    873                                             "Roll over happend!\n")));
    874                     LOG_VERBOSE(BSL_LS_BCM_TSN,
    875                                 (BSL_META_U(unit,
    876                                             "... Read Packet HW Count    :"
    877                                             " %x:%x\n"),
    878                                 COMPILER_64_HI(new_packet_count),
    879                                 COMPILER_64_LO(new_packet_count)));
    880 
    881                     COMPILER_64_ADD_64(new_packet_count, max_packet_size);
    882                     COMPILER_64_SUB_64(new_packet_count, prev_packet_count);
    883                     LOG_VERBOSE(BSL_LS_BCM_TSN,
    884                                 (BSL_META_U(unit,
    885                                             "... Diffed Packet HW Count    :"
    886                                             " %x:%x\n"),
    887                                 COMPILER_64_HI(new_packet_count),
    888                                 COMPILER_64_LO(new_packet_count)));
    889                 } else {
    890                     /* Normal case */
    891                     COMPILER_64_SUB_64(new_packet_count, prev_packet_count);
    892                 }
    893 
    894                 /* Add difference (if it is) */
    895                 if (!COMPILER_64_IS_ZERO(new_packet_count)) {
    896                     LOG_VERBOSE(BSL_LS_BCM_TSN,
    897                                 (BSL_META_U(unit,
    898                                             "Port %d: TSN stat(%d)==>"
    899                                             "Old Packet Count SW Value: "
    900                                             "%x:%x\t"),
    901                                 index, i,
    902                                 COMPILER_64_HI(
    903                                     portcnt_member->port_counter_sw[index]),
    904                                 COMPILER_64_LO(
    905                                     portcnt_member->port_counter_sw[index])));
    906                     COMPILER_64_ADD_64(
    907                         portcnt_member->port_counter_sw[index],
    908                         new_packet_count);
    909                     LOG_VERBOSE(BSL_LS_BCM_TSN,
    910                                 (BSL_META_U(unit,
    911                                             "New Packet Count SW Value: "
    912                                             "%x:%x\n"),
    913                                 COMPILER_64_HI(
    914                                     portcnt_member->port_counter_sw[index]),
    915                                 COMPILER_64_LO(
    916                                     portcnt_member->port_counter_sw[index])));
    917                 }
    918             }
    919         }
    920     }
    921 
    922     return;
    923 }
    924 
    925 /*
    926  * Function:
    927  *    bcmi_esw_tsn_stat_portcnt_map
    928  * Description:
    929  *    Get the counter table index information based on
    930  *    the giving TSN statistic type
    931  * Parameters:
    932  *    unit - (IN) Unit number
    933  *    port - (IN) port number
    934  *    stat - (IN) TSN statistics type (see tsn.h)
    935  *    stat_index - (OUT) TSN stat table index
    936  *    offset_index - (OUT) offset index (port) in the counter table
    937  *                         (specified TSN stat)
    938  * Returns:
    939  *    BCM_E_XXX
    940  * Notes:
    941  */
    942 STATIC int
    943 bcmi_esw_tsn_stat_portcnt_map(
    944     int unit,
    945     bcm_gport_t port,
    946     bcm_tsn_stat_t stat,
    947     int *stat_index,
    948     int *offset_index)
    949 {
    950     int i, rv = BCM_E_NONE;
    951     bcmi_tsn_stat_control_t *tc;
    952     const bcmi_esw_tsn_stat_dev_info_t *tsn_stat_dev_info;
    953     const tsn_stat_portcnt_dev_info_t *portcnt_dev_info;
    954     const tsn_stat_portcnt_table_info_t *portcnt_table;
    955     bcm_port_t port_out;
    956 
    957     /* Input parameter check. */
    958     if (NULL == stat_index) {
    959         return BCM_E_PARAM;
    960     }
    961     if (!TSN_STAT_IS_VALID(unit, stat)) {
    962         return BCM_E_PARAM;
    963     }
    964 
    965     /* The port will be ignored if offset_index == NULL */
    966     if (offset_index != NULL) {
    967         /* Get offset_index based on the giving gport */
    968         rv = bcmi_esw_tsn_stat_gport_validate(unit, port, &port_out);
    969         if (BCM_FAILURE(rv)) {
    970             return rv;
    971         }
    972         *offset_index = port_out;
    973     }
    974 
    975     /* Get TSN stat control */
    976     BCM_IF_ERROR_RETURN(
    977         tsn_stat_control_instance_get(unit, &tc));
    978 
    979     /* Get chip specific info for TSN stat */
    980     tsn_stat_dev_info = tc->tsn_stat_dev_info;
    981     if (NULL == tsn_stat_dev_info) {
    982         return BCM_E_UNAVAIL;
    983     }
    984     portcnt_dev_info = tsn_stat_dev_info->tsn_stat_portcnt_dev_info;
    985     if (NULL == portcnt_dev_info) {
    986         return BCM_E_UNAVAIL;
    987     }
    988 
    989     /* Get stat_index based on the giving TSN statistic type = stat */
    990     portcnt_table = portcnt_dev_info->portcnt_table_info;
    991     if (NULL == portcnt_table) {
    992         return BCM_E_UNAVAIL;
    993     }
    994 
    995     *stat_index = -1;
    996     for (i = 0; i < portcnt_dev_info->num_stats; i++) {
    997         bcm_tsn_stat_t stat_itr = portcnt_table[i].portcnt_stat;
    998 
    999         assert((stat_itr >= 0) && (stat_itr < bcmTsnStatCount));
   1000         if (!soc_feature(unit, tsn_stat_type_feature[stat_itr])) {
   1001             continue;
   1002         }
   1003         if (stat == stat_itr) {
   1004             *stat_index = i;
   1005             break;
   1006         }
   1007     }
   1008 
   1009     if (*stat_index == -1) {
   1010         /* Cannot find specified TSN statistic type for this device */
   1011         return BCM_E_UNAVAIL;
   1012     }
   1013 
   1014     return rv;
   1015 }
   1016 
   1017 /*
   1018  * Function:
   1019  *    bcmi_esw_tsn_stat_portcnt_cleanup
   1020  * Description:
   1021  *    Clean and free all allocated TSN port counter resources
   1022  * Parameters:
   1023  *    unit - (IN) Unit number
   1024  * Returns:
   1025  *    BCM_E_XXX
   1026  */
   1027 STATIC int
   1028 bcmi_esw_tsn_stat_portcnt_cleanup(int unit)
   1029 {
   1030     bcmi_tsn_stat_portcnt_control_t *pc;
   1031     bcmi_tsn_stat_portcnt_member_t *portcnt_member;
   1032     bcmi_tsn_stat_portcnt_bk_info_t *portcnt_bk_info;
   1033     const bcmi_esw_tsn_stat_dev_info_t *tsn_stat_dev_info;
   1034     const tsn_stat_portcnt_dev_info_t *portcnt_dev_info;
   1035     int i;
   1036 
   1037     LOG_DEBUG(BSL_LS_BCM_TSN,
   1038               (BSL_META_U(unit,
   1039                           "bcmi_esw_tsn_stat_portcnt_cleanup\n")));
   1040 
   1041     pc = tsn_stat_control[unit]->portcnt_control;
   1042 
   1043     if (pc->stats != NULL) {
   1044         tsn_stat_dev_info = tsn_stat_control[unit]->tsn_stat_dev_info;
   1045         if (tsn_stat_dev_info != NULL) {
   1046             portcnt_dev_info =
   1047                 tsn_stat_dev_info->tsn_stat_portcnt_dev_info;
   1048             if (portcnt_dev_info != NULL) {
   1049                 for (i = 0; i < portcnt_dev_info->num_stats; i++) {
   1050                     portcnt_member = &pc->stats[i];
   1051                     if (portcnt_member->port_counter_sw != NULL) {
   1052                         sal_free(portcnt_member->port_counter_sw);
   1053                         portcnt_member->port_counter_sw = NULL;
   1054                     }
   1055                     if (portcnt_member->port_counter_hw != NULL) {
   1056                         sal_free(portcnt_member->port_counter_hw);
   1057                         portcnt_member->port_counter_hw = NULL;
   1058                     }
   1059                 }
   1060             }
   1061         }
   1062         sal_free(pc->stats);
   1063         pc->stats = NULL;
   1064     }
   1065 
   1066     if (pc->portcnt_entry_temp != NULL) {
   1067         soc_cm_sfree(unit, pc->portcnt_entry_temp);
   1068         pc->portcnt_entry_temp = NULL;
   1069     }
   1070 
   1071     if (pc->portcnt_bk_info != NULL) {
   1072         portcnt_bk_info = pc->portcnt_bk_info;
   1073         if (portcnt_bk_info->stat_bitmap != NULL) {
   1074             sal_free(portcnt_bk_info->stat_bitmap);
   1075             portcnt_bk_info->stat_bitmap = NULL;
   1076         }
   1077         if (portcnt_bk_info->stat_port_bitmap != NULL) {
   1078             sal_free(portcnt_bk_info->stat_port_bitmap);
   1079             portcnt_bk_info->stat_port_bitmap = NULL;
   1080         }
   1081         sal_free(pc->portcnt_bk_info);
   1082         pc->portcnt_bk_info = NULL;
   1083     }
   1084 
   1085     if (pc->portcnt_mutex != NULL) {
   1086         sal_mutex_destroy(pc->portcnt_mutex);
   1087         pc->portcnt_mutex = NULL;
   1088     }
   1089 
   1090     return BCM_E_NONE;
   1091 }
   1092 
   1093 /*
   1094  * Function:
   1095  *    bcmi_esw_tsn_stat_portcnt_init
   1096  * Description:
   1097  *    Initialize and allocate all required resources for TSN port counters
   1098  * Parameters:
   1099  *    unit - (IN) Unit number
   1100  * Returns:
   1101  *    BCM_E_XXX
   1102  */
   1103 STATIC int
   1104 bcmi_esw_tsn_stat_portcnt_init(int unit)
   1105 {
   1106     int rv = BCM_E_NONE;
   1107     bcmi_tsn_stat_control_t *tc;
   1108     bcmi_tsn_stat_portcnt_control_t *pc;
   1109     bcmi_tsn_stat_portcnt_member_t *portcnt_member;
   1110     bcmi_tsn_stat_portcnt_bk_info_t *portcnt_bk_info;
   1111     const bcmi_esw_tsn_stat_dev_info_t *tsn_stat_dev_info;
   1112     const tsn_stat_portcnt_dev_info_t *portcnt_dev_info;
   1113     const tsn_stat_portcnt_table_info_t *portcnt_table;
   1114     int i, num_port = 0;
   1115 
   1116     /* Get TSN stat control */
   1117     BCM_IF_ERROR_RETURN(
   1118         tsn_stat_control_instance_get(unit, &tc));
   1119 
   1120     pc = tc->portcnt_control;
   1121     if (NULL == pc) {
   1122         return BCM_E_INIT;
   1123     }
   1124     sal_memset(pc, 0, sizeof(bcmi_tsn_stat_portcnt_control_t));
   1125 
   1126     /* Create portcnt protection mutex. */
   1127     pc->portcnt_mutex = sal_mutex_create("tsn portcnt control mutex");
   1128     if (NULL == pc->portcnt_mutex) {
   1129         return BCM_E_RESOURCE;
   1130     }
   1131 
   1132     /* Get chip specific info for TSN stat portcnt */
   1133     tsn_stat_dev_info = tc->tsn_stat_dev_info;
   1134     if (NULL == tsn_stat_dev_info) {
   1135         return BCM_E_UNAVAIL;
   1136     }
   1137     portcnt_dev_info = tsn_stat_dev_info->tsn_stat_portcnt_dev_info;
   1138     if (NULL == portcnt_dev_info) {
   1139         return BCM_E_UNAVAIL;
   1140     }
   1141 
   1142     /* Allocate the TSN portcnt stats member resource */
   1143     pc->stats =
   1144         sal_alloc((portcnt_dev_info->num_stats *
   1145                    sizeof(bcmi_tsn_stat_portcnt_member_t)),
   1146                   "TSN portcnt stats");
   1147     if (NULL == pc->stats) {
   1148         return BCM_E_MEMORY;
   1149     }
   1150     sal_memset(pc->stats, 0,
   1151                (portcnt_dev_info->num_stats *
   1152                 sizeof(bcmi_tsn_stat_portcnt_member_t)));
   1153 
   1154     /*
   1155      * For each TSN Port Stat counter:
   1156      * allocate *port_counter_sw and *port_counter_hw for all ports
   1157      */
   1158     portcnt_table = portcnt_dev_info->portcnt_table_info;
   1159     for (i = 0; i < portcnt_dev_info->num_stats; i++) {
   1160         portcnt_member = &pc->stats[i];
   1161         portcnt_member->mem = portcnt_table[i].portcnt_mem;
   1162         portcnt_member->field = portcnt_table[i].portcnt_field;
   1163         num_port = soc_mem_index_count(unit, portcnt_member->mem);
   1164 
   1165         /* Allocate port_counter_sw */
   1166         portcnt_member->port_counter_sw =
   1167             sal_alloc((num_port * sizeof(uint64)), "TSN port counter sw");
   1168         if (NULL == portcnt_member->port_counter_sw) {
   1169             return BCM_E_MEMORY;
   1170         }
   1171         sal_memset(portcnt_member->port_counter_sw, 0,
   1172                    (num_port * sizeof(uint64)));
   1173 
   1174         /* Allocate port_counter_hw */
   1175         portcnt_member->port_counter_hw =
   1176             sal_alloc((num_port * sizeof(uint64)), "TSN port counter hw");
   1177         if (NULL == portcnt_member->port_counter_hw) {
   1178             return BCM_E_MEMORY;
   1179         }
   1180         sal_memset(portcnt_member->port_counter_hw, 0,
   1181                    (num_port * sizeof(uint64)));
   1182     }
   1183 
   1184     /* Allocate the TSN portcnt temporary counter resource for DMA */
   1185     num_port = soc_mem_index_count(unit, portcnt_table[0].portcnt_mem);
   1186     pc->portcnt_entry_temp =
   1187         soc_cm_salloc(unit,
   1188                       (num_port * sizeof(bcmi_tsn_stat_portcnt_table_entry_t)),
   1189                       "TSN portcnt temporary counter");
   1190     if (NULL == pc->portcnt_entry_temp) {
   1191         return BCM_E_MEMORY;
   1192     }
   1193     sal_memset(pc->portcnt_entry_temp, 0,
   1194                (num_port * sizeof(bcmi_tsn_stat_portcnt_table_entry_t)));
   1195 
   1196     /* Allocate the TSN portcnt book keeping info resource */
   1197     pc->portcnt_bk_info =
   1198         sal_alloc(sizeof(bcmi_tsn_stat_portcnt_bk_info_t),
   1199                   "TSN portcnt book keeping");
   1200     if (NULL == pc->portcnt_bk_info) {
   1201         return BCM_E_MEMORY;
   1202     }
   1203     sal_memset(pc->portcnt_bk_info, 0,
   1204                sizeof(bcmi_tsn_stat_portcnt_bk_info_t));
   1205 
   1206     portcnt_bk_info = pc->portcnt_bk_info;
   1207     portcnt_bk_info->stat_bitmap =
   1208         sal_alloc(SHR_BITALLOCSIZE(portcnt_dev_info->num_stats),
   1209                   "TSN portcnt stat_bitmap");
   1210     if (NULL == portcnt_bk_info->stat_bitmap) {
   1211         return BCM_E_MEMORY;
   1212     }
   1213     sal_memset(portcnt_bk_info->stat_bitmap, 0,
   1214                SHR_BITALLOCSIZE(portcnt_dev_info->num_stats));
   1215 
   1216     portcnt_bk_info->stat_port_bitmap =
   1217         sal_alloc(SHR_BITALLOCSIZE(portcnt_dev_info->num_stats * num_port),
   1218                   "TSN portcnt stat_port_bitmap");
   1219     if (NULL == portcnt_bk_info->stat_port_bitmap) {
   1220         return BCM_E_MEMORY;
   1221     }
   1222     sal_memset(portcnt_bk_info->stat_port_bitmap, 0,
   1223                SHR_BITALLOCSIZE(portcnt_dev_info->num_stats * num_port));
   1224 
   1225     portcnt_bk_info->num_port = num_port;
   1226 
   1227     
   1228     /* WARMBOOT related */
   1229 
   1230     return rv;
   1231 }
   1232 
   1233 /*
   1234  * Function:
   1235  *    bcmi_esw_tsn_stat_portcnt_set
   1236  * Description:
   1237  *    Set 64-bit counter value for specified TSN statistic type.
   1238  * Parameters:
   1239  *    unit - (IN) Unit number
   1240  *    port - (IN) port number
   1241  *    stat - (IN) TSN statistics type (see tsn.h)
   1242  *     val - (IN) 64-bit counter value.
   1243  * Returns:
   1244  *    BCM_E_XXX.
   1245  * Notes:
   1246  */
   1247 int
   1248 bcmi_esw_tsn_stat_portcnt_set(
   1249     int unit,
   1250     bcm_gport_t port,
   1251     bcm_tsn_stat_t stat,
   1252     uint64 val)
   1253 {
   1254     int rv = BCM_E_NONE;
   1255     bcmi_tsn_stat_portcnt_control_t *pc;
   1256     bcmi_tsn_stat_portcnt_member_t *portcnt_member;
   1257     int stat_index, offset_index, total_entries;
   1258     uint32 entry[SOC_MAX_MEM_WORDS];
   1259     soc_mem_t counter_mem;
   1260     soc_field_t counter_field;
   1261     uint32 max_packet_value[2];
   1262     int width;
   1263 
   1264     BCM_IF_ERROR_RETURN(
   1265         tsn_stat_portcnt_control_instance_get(unit, &pc));
   1266 
   1267     rv = bcmi_esw_tsn_stat_portcnt_map(unit, port, stat,
   1268                                        &stat_index, &offset_index);
   1269     if (BCM_FAILURE(rv)) {
   1270         return rv;
   1271     }
   1272 
   1273     TSN_STAT_PORTCNT_LOCK(pc);
   1274     portcnt_member = &pc->stats[stat_index];
   1275     counter_mem = portcnt_member->mem;
   1276     counter_field = portcnt_member->field;
   1277     total_entries = soc_mem_index_count(unit, counter_mem);
   1278 
   1279     if (offset_index >= total_entries) {
   1280         LOG_ERROR(BSL_LS_BCM_TSN,
   1281                   (BSL_META_U(unit,
   1282                               "Wrong OFFSET_INDEX(Port). "
   1283                               "Must be < Total Entries %d \n"),
   1284                   total_entries));
   1285         TSN_STAT_PORTCNT_UNLOCK(pc);
   1286         assert(0);
   1287     }
   1288 
   1289     /* Memory read from hardware */
   1290     sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1291     if (soc_mem_read(unit, counter_mem, MEM_BLOCK_ANY,
   1292                      offset_index, &entry) != BCM_E_NONE) {
   1293         TSN_STAT_PORTCNT_UNLOCK(pc);
   1294         return BCM_E_INTERNAL;
   1295     }
   1296 
   1297     width = soc_mem_field_length(unit, counter_mem, counter_field);
   1298     if (width > 32) {
   1299         /* 64-bit field */
   1300         max_packet_value[0] = COMPILER_64_LO(val);
   1301         max_packet_value[1] = COMPILER_64_HI(val);
   1302     } else {
   1303          /* 32-bit field */
   1304         max_packet_value[0] = COMPILER_64_LO(val);
   1305         max_packet_value[1] = 0;
   1306     }
   1307     soc_mem_field_set(unit, counter_mem, (uint32 *)entry,
   1308                       counter_field, max_packet_value);
   1309 
   1310     LOG_DEBUG(BSL_LS_BCM_TSN,
   1311               (BSL_META_U(unit,
   1312                           "Packet Count HW Value\t:TABLE:"
   1313                           "%s INDEX(port):%d : %x:%x \n"),
   1314               SOC_MEM_UFNAME(unit, counter_mem),
   1315               offset_index,
   1316               max_packet_value[1],
   1317               max_packet_value[0]));
   1318 
   1319     /* Memory write into hardware */
   1320     if (soc_mem_write(unit, counter_mem, MEM_BLOCK_ALL,
   1321                       offset_index, &entry) != BCM_E_NONE) {
   1322         TSN_STAT_PORTCNT_UNLOCK(pc);
   1323         return BCM_E_INTERNAL;
   1324     }
   1325 
   1326     /* Update Soft Copy for HW counter */
   1327     COMPILER_64_SET(portcnt_member->port_counter_hw[offset_index],
   1328                     max_packet_value[1],
   1329                     max_packet_value[0]);
   1330 
   1331     /* Update Soft Copy for SW counter */
   1332     COMPILER_64_SET(portcnt_member->port_counter_sw[offset_index],
   1333                     COMPILER_64_HI(val),
   1334                     COMPILER_64_LO(val));
   1335 
   1336     /* Set to enable the portcnt callback for matrix of (stat, port) */
   1337     if (!TSN_STAT_PORTCNT_USED_GET(pc->portcnt_bk_info, stat_index)) {
   1338         TSN_STAT_PORTCNT_USED_SET(pc->portcnt_bk_info, stat_index);
   1339     }
   1340     if (!TSN_STAT_PORTCNT_PORT_USED_GET(pc->portcnt_bk_info,
   1341                                         stat_index, offset_index)) {
   1342         TSN_STAT_PORTCNT_PORT_USED_SET(pc->portcnt_bk_info,
   1343                                        stat_index, offset_index);
   1344     }
   1345 
   1346     TSN_STAT_PORTCNT_UNLOCK(pc);
   1347 
   1348     return BCM_E_NONE;
   1349 }
   1350 
   1351 /*
   1352  * Function:
   1353  *    bcmi_esw_tsn_stat_portcnt_get
   1354  * Description:
   1355  *    Get 64-bit counter value for specified TSN statistic type.
   1356  * Parameters:
   1357  *    unit - (IN) Unit number
   1358  *    port - (IN) port number
   1359  *    sync_mode - (IN) if 1 read hw counter else sw accumulated counter
   1360  *    stat - (IN) TSN statistics type (see tsn.h)
   1361  *     val - (OUT) 64-bit counter value.
   1362  * Returns:
   1363  *    BCM_E_XXX.
   1364  * Notes:
   1365  */
   1366 int
   1367 bcmi_esw_tsn_stat_portcnt_get(
   1368     int unit,
   1369     bcm_gport_t port,
   1370     int sync_mode,
   1371     bcm_tsn_stat_t stat,
   1372     uint64 *val)
   1373 {
   1374     int rv = BCM_E_NONE;
   1375     bcmi_tsn_stat_portcnt_control_t *pc;
   1376     bcmi_tsn_stat_portcnt_member_t *portcnt_member;
   1377     int stat_index, offset_index, total_entries;
   1378     soc_mem_t counter_mem;
   1379 
   1380     /* Input parameter check. */
   1381     if (NULL == val) {
   1382         return BCM_E_PARAM;
   1383     }
   1384 
   1385     BCM_IF_ERROR_RETURN(
   1386         tsn_stat_portcnt_control_instance_get(unit, &pc));
   1387 
   1388     rv = bcmi_esw_tsn_stat_portcnt_map(unit, port, stat,
   1389                                        &stat_index, &offset_index);
   1390     if (BCM_FAILURE(rv)) {
   1391         return rv;
   1392     }
   1393 
   1394     portcnt_member = &pc->stats[stat_index];
   1395     counter_mem = portcnt_member->mem;
   1396     total_entries = soc_mem_index_count(unit, counter_mem);
   1397 
   1398     if (offset_index >= total_entries) {
   1399         LOG_ERROR(BSL_LS_BCM_TSN,
   1400                   (BSL_META_U(unit,
   1401                               "Wrong OFFSET_INDEX(Port). "
   1402                               "Must be < Total Entries %d \n"),
   1403                   total_entries));
   1404         return BCM_E_PARAM;
   1405     }
   1406 
   1407     TSN_STAT_PORTCNT_LOCK(pc);
   1408 
   1409     /* Set to enable the portcnt callback for matrix of (stat, port) */
   1410     if (!TSN_STAT_PORTCNT_USED_GET(pc->portcnt_bk_info, stat_index)) {
   1411         TSN_STAT_PORTCNT_USED_SET(pc->portcnt_bk_info, stat_index);
   1412     }
   1413     if (!TSN_STAT_PORTCNT_PORT_USED_GET(pc->portcnt_bk_info,
   1414                                         stat_index, offset_index)) {
   1415         TSN_STAT_PORTCNT_PORT_USED_SET(pc->portcnt_bk_info,
   1416                                        stat_index, offset_index);
   1417         /* Force sync_mode = 1 for the first time touch */
   1418         sync_mode = 1;
   1419     }
   1420 
   1421     /* sync the software counter with hardware counter */
   1422     if (sync_mode == 1) {
   1423         bcmi_esw_tsn_stat_portcnt_collect(unit, counter_mem, offset_index);
   1424     }
   1425 
   1426     /* Packet Count HW Value */
   1427     LOG_DEBUG(BSL_LS_BCM_TSN,
   1428               (BSL_META_U(unit,
   1429                           "Packet Count HW Value\t:TABLE:"
   1430                           "%s INDEX(port):%d : %x:%x \n"),
   1431               SOC_MEM_UFNAME(unit, counter_mem),
   1432               offset_index,
   1433               COMPILER_64_HI(portcnt_member->port_counter_hw[offset_index]),
   1434               COMPILER_64_LO(portcnt_member->port_counter_hw[offset_index])));
   1435 
   1436     /* Return Packet Count SW Value */
   1437     COMPILER_64_COPY(*val,
   1438                      portcnt_member->port_counter_sw[offset_index]);
   1439     LOG_DEBUG(BSL_LS_BCM_TSN,
   1440               (BSL_META_U(unit,
   1441                           "Packet Count SW Value\t:TABLE:"
   1442                           "%s INDEX(port):%d : %x:%x \n"),
   1443               SOC_MEM_UFNAME(unit, counter_mem),
   1444               offset_index,
   1445               COMPILER_64_HI(*val),
   1446               COMPILER_64_LO(*val)));
   1447 
   1448     TSN_STAT_PORTCNT_UNLOCK(pc);
   1449 
   1450     return BCM_E_NONE;
   1451 }
   1452 
   1453 /*
   1454  * Function:
   1455  *    bcmi_esw_tsn_stat_portcnt_used_update
   1456  * Description:
   1457  *    Helper function to update TSN stat portcnt usage bitmap.
   1458  * Parameters:
   1459  *    unit - (IN) Unit number
   1460  *    port - (IN) port number
   1461  *    stat - (IN) TSN statistics type (see tsn.h)
   1462  *      op - (IN) TSN stat portcnt usage bitmap operation modes.
   1463  * Returns:
   1464  *    BCM_E_XXX.
   1465  * Notes:
   1466  */
   1467 int
   1468 bcmi_esw_tsn_stat_portcnt_used_update(
   1469     int unit,
   1470     bcm_gport_t port,
   1471     bcm_tsn_stat_t stat,
   1472     bcmi_tsn_stat_portcnt_used_operation_t op)
   1473 {
   1474     int rv = BCM_E_NONE;
   1475     bcmi_tsn_stat_portcnt_control_t *pc;
   1476     int stat_index, offset_index;
   1477     bcm_port_t port_out = 0, p;
   1478     bcm_pbmp_t pbmp;
   1479     int empty;
   1480 
   1481     BCM_PBMP_CLEAR(pbmp);
   1482     if (port == -1) {
   1483         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   1484         BCM_PBMP_ITER(pbmp, p) {
   1485             port_out = p;
   1486             break;
   1487         }
   1488     } else {
   1489         rv = bcmi_esw_tsn_stat_gport_validate(unit, port, &port_out);
   1490         if (BCM_FAILURE(rv)) {
   1491             return rv;
   1492         }
   1493         BCM_PBMP_PORT_SET(pbmp, port_out);
   1494     }
   1495 
   1496     BCM_IF_ERROR_RETURN(
   1497         tsn_stat_portcnt_control_instance_get(unit, &pc));
   1498 
   1499     rv = bcmi_esw_tsn_stat_portcnt_map(unit, port_out, stat,
   1500                                        &stat_index, &offset_index);
   1501     if (BCM_FAILURE(rv)) {
   1502         return rv;
   1503     }
   1504 
   1505     switch (op) {
   1506         case BCM_TSN_STAT_PORTCNT_USED_SET:
   1507             if (!TSN_STAT_PORTCNT_USED_GET(pc->portcnt_bk_info, stat_index)) {
   1508                 TSN_STAT_PORTCNT_USED_SET(pc->portcnt_bk_info, stat_index);
   1509             }
   1510 
   1511             BCM_PBMP_ITER(pbmp, p) {
   1512                 if (!TSN_STAT_PORTCNT_PORT_USED_GET(pc->portcnt_bk_info,
   1513                                                     stat_index, p)) {
   1514                     TSN_STAT_PORTCNT_PORT_USED_SET(pc->portcnt_bk_info,
   1515                                                    stat_index, p);
   1516                 }
   1517             }
   1518 
   1519             break;
   1520         case BCM_TSN_STAT_PORTCNT_USED_CLEAR:
   1521             if (TSN_STAT_PORTCNT_USED_GET(pc->portcnt_bk_info, stat_index)) {
   1522                 BCM_PBMP_ITER(pbmp, p) {
   1523                     if (TSN_STAT_PORTCNT_PORT_USED_GET(pc->portcnt_bk_info,
   1524                                                        stat_index, p)) {
   1525                         TSN_STAT_PORTCNT_PORT_USED_CLR(pc->portcnt_bk_info,
   1526                                                        stat_index, p);
   1527                     }
   1528                 }
   1529 
   1530                 empty = 1;
   1531                 PBMP_ALL_ITER(unit, p) {
   1532                     if (TSN_STAT_PORTCNT_PORT_USED_GET(pc->portcnt_bk_info,
   1533                                                        stat_index, p)) {
   1534                         empty = 0; /* Not empty */
   1535                         break;
   1536                     }
   1537                 }
   1538 
   1539                 if (empty) {
   1540                     TSN_STAT_PORTCNT_USED_CLR(pc->portcnt_bk_info, stat_index);
   1541                 }
   1542             }
   1543 
   1544             break;
   1545         default:
   1546             return BCM_E_PARAM;
   1547     }
   1548 
   1549     return rv;
   1550 }
   1551 
   1552 /*
   1553  * Function:
   1554  *    bcmi_esw_tsn_stat_portcnt_stat_sync
   1555  * Description:
   1556  *    Helper function to sync HW/SW TSN stat portcnt per specified stat type.
   1557  * Parameters:
   1558  *    unit - (IN) Unit number
   1559  *    stat - (IN) TSN statistics type (see tsn.h)
   1560  * Returns:
   1561  *    BCM_E_XXX.
   1562  * Notes:
   1563  */
   1564 int
   1565 bcmi_esw_tsn_stat_portcnt_stat_sync(int unit, bcm_tsn_stat_t stat)
   1566 {
   1567     bcmi_tsn_stat_portcnt_control_t *pc;
   1568     bcmi_tsn_stat_portcnt_member_t *portcnt_member;
   1569     int stat_index;
   1570     soc_mem_t counter_mem;
   1571 
   1572     BCM_IF_ERROR_RETURN(
   1573         tsn_stat_portcnt_control_instance_get(unit, &pc));
   1574 
   1575     BCM_IF_ERROR_RETURN(
   1576         bcmi_esw_tsn_stat_portcnt_map(unit, -1, stat,
   1577                                       &stat_index, NULL));
   1578 
   1579     portcnt_member = &(pc->stats[stat_index]);
   1580     counter_mem = portcnt_member->mem;
   1581 
   1582     /* Sync the software counter with hardware counter (per stat type) */
   1583     TSN_STAT_PORTCNT_LOCK(pc);
   1584     bcmi_esw_tsn_stat_portcnt_collect(unit, counter_mem, -1);
   1585     TSN_STAT_PORTCNT_UNLOCK(pc);
   1586 
   1587     return BCM_E_NONE;
   1588 }
   1589 
   1590 /*
   1591  * Function:
   1592  *    bcmi_esw_tsn_stat_portcnt_hw_sw_get
   1593  * Description:
   1594  *    Helper function to get both HW and SW TSN stat portcnt
   1595  *    per specified stat type and port.
   1596  * Parameters:
   1597  *    unit - (IN) Unit number
   1598  *    stat - (IN) TSN statistics type (see tsn.h)
   1599  *    port - (IN) port number
   1600  *    hw_value - (OUT) 64-bit HW counter value.
   1601  *    sw_value - (OUT) 64-bit SW counter value.
   1602  * Returns:
   1603  *    BCM_E_XXX.
   1604  * Notes:
   1605  */
   1606 int
   1607 bcmi_esw_tsn_stat_portcnt_hw_sw_get(
   1608     int unit,
   1609     bcm_tsn_stat_t stat,
   1610     bcm_gport_t port,
   1611     uint64 *hw_value,
   1612     uint64 *sw_value)
   1613 {
   1614     bcmi_tsn_stat_portcnt_control_t *pc;
   1615     bcmi_tsn_stat_portcnt_member_t *portcnt_member;
   1616     int stat_index, offset_index, total_entries;
   1617     soc_mem_t counter_mem;
   1618 
   1619     /* Input parameter check. */
   1620     if ((NULL == hw_value) || (NULL == sw_value)) {
   1621         return BCM_E_PARAM;
   1622     }
   1623 
   1624     BCM_IF_ERROR_RETURN(
   1625         tsn_stat_portcnt_control_instance_get(unit, &pc));
   1626 
   1627     BCM_IF_ERROR_RETURN(
   1628         bcmi_esw_tsn_stat_portcnt_map(unit, port, stat,
   1629                                       &stat_index, &offset_index));
   1630 
   1631     portcnt_member = &(pc->stats[stat_index]);
   1632     counter_mem = portcnt_member->mem;
   1633     total_entries = soc_mem_index_count(unit, counter_mem);
   1634 
   1635     if (offset_index >= total_entries) {
   1636         LOG_ERROR(BSL_LS_BCM_TSN,
   1637                   (BSL_META_U(unit,
   1638                               "Wrong OFFSET_INDEX(Port). "
   1639                               "Must be < Total Entries %d \n"),
   1640                   total_entries));
   1641         return BCM_E_PARAM;
   1642     }
   1643 
   1644     TSN_STAT_PORTCNT_LOCK(pc);
   1645 
   1646     /* Return Packet Count HW Value */
   1647     COMPILER_64_COPY(*hw_value,
   1648                      portcnt_member->port_counter_hw[offset_index]);
   1649     /* Return Packet Count SW Value */
   1650     COMPILER_64_COPY(*sw_value,
   1651                      portcnt_member->port_counter_sw[offset_index]);
   1652 
   1653     LOG_DEBUG(BSL_LS_BCM_TSN,
   1654               (BSL_META_U(unit,
   1655                           "Packet Count HW Value\t:TABLE:"
   1656                           "%s INDEX(port):%d : %x:%x \n"),
   1657               SOC_MEM_UFNAME(unit, counter_mem),
   1658               offset_index,
   1659               COMPILER_64_HI(*hw_value),
   1660               COMPILER_64_LO(*hw_value)));
   1661     LOG_DEBUG(BSL_LS_BCM_TSN,
   1662               (BSL_META_U(unit,
   1663                           "Packet Count SW Value\t:TABLE:"
   1664                           "%s INDEX(port):%d : %x:%x \n"),
   1665               SOC_MEM_UFNAME(unit, counter_mem),
   1666               offset_index,
   1667               COMPILER_64_HI(*sw_value),
   1668               COMPILER_64_LO(*sw_value)));
   1669 
   1670     TSN_STAT_PORTCNT_UNLOCK(pc);
   1671 
   1672     return BCM_E_NONE;
   1673 }
   1674 
   1675 /*
   1676  * Function:
   1677  *    bcmi_esw_tsn_stat_portcnt_hw_set
   1678  * Description:
   1679  *    Helper function to set HW only TSN stat portcnt
   1680  *    per specified stat type and port.
   1681  * Parameters:
   1682  *    unit - (IN) Unit number
   1683  *    stat - (IN) TSN statistics type (see tsn.h)
   1684  *    port - (IN) port number
   1685  *    hw_value - (OUT) 64-bit HW counter value.
   1686  * Returns:
   1687  *    BCM_E_XXX.
   1688  * Notes:
   1689  */
   1690 int
   1691 bcmi_esw_tsn_stat_portcnt_hw_set(
   1692     int unit,
   1693     bcm_tsn_stat_t stat,
   1694     bcm_gport_t port,
   1695     uint64 hw_value)
   1696 {
   1697     bcmi_tsn_stat_portcnt_control_t *pc;
   1698     bcmi_tsn_stat_portcnt_member_t *portcnt_member;
   1699     int stat_index, offset_index, total_entries;
   1700     uint32 entry[SOC_MAX_MEM_WORDS];
   1701     soc_mem_t counter_mem;
   1702     soc_field_t counter_field;
   1703     uint32 packet_count_hw[2];
   1704     uint64 old_packet_count;
   1705     int width;
   1706 
   1707     BCM_IF_ERROR_RETURN(
   1708         tsn_stat_portcnt_control_instance_get(unit, &pc));
   1709 
   1710     BCM_IF_ERROR_RETURN(
   1711         bcmi_esw_tsn_stat_portcnt_map(unit, port, stat,
   1712                                       &stat_index, &offset_index));
   1713 
   1714     TSN_STAT_PORTCNT_LOCK(pc);
   1715     portcnt_member = &(pc->stats[stat_index]);
   1716     counter_mem = portcnt_member->mem;
   1717     counter_field = portcnt_member->field;
   1718     total_entries = soc_mem_index_count(unit, counter_mem);
   1719 
   1720     if (offset_index >= total_entries) {
   1721         LOG_ERROR(BSL_LS_BCM_TSN,
   1722                   (BSL_META_U(unit,
   1723                               "Wrong OFFSET_INDEX(Port). "
   1724                               "Must be < Total Entries %d \n"),
   1725                   total_entries));
   1726         TSN_STAT_PORTCNT_UNLOCK(pc);
   1727         assert(0);
   1728     }
   1729 
   1730     /* Memory read from hardware */
   1731     sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1732     if (soc_mem_read(unit, counter_mem, MEM_BLOCK_ANY,
   1733                      offset_index, &entry) != BCM_E_NONE) {
   1734         TSN_STAT_PORTCNT_UNLOCK(pc);
   1735         return BCM_E_INTERNAL;
   1736     }
   1737 
   1738     width = soc_mem_field_length(unit, counter_mem, counter_field);
   1739 
   1740     /* Get current HW value */
   1741     sal_memset(packet_count_hw, 0, sizeof(uint32) * 2);
   1742     soc_mem_field_get(unit, counter_mem, (uint32 *)entry,
   1743                       counter_field, packet_count_hw);
   1744     if (width > 32) {
   1745         /* 64-bit field */
   1746         COMPILER_64_SET(old_packet_count,
   1747                         packet_count_hw[1],
   1748                         packet_count_hw[0]);
   1749     } else {
   1750          /* 32-bit field */
   1751         COMPILER_64_SET(old_packet_count,
   1752                         0,
   1753                         packet_count_hw[0]);
   1754     }
   1755 
   1756     /* Compare old and new hardware counter */
   1757     if (!COMPILER_64_EQ(old_packet_count, hw_value)) {
   1758         LOG_VERBOSE(BSL_LS_BCM_TSN,
   1759                     (BSL_META_U(unit,
   1760                                 "Port %d: TSN stat(%d)==>"
   1761                                 "Old HW Packet Count Value %x:%x\t"
   1762                                 "New HW Packet Count Value %x:%x\n"),
   1763                     offset_index, stat_index,
   1764                     COMPILER_64_HI(old_packet_count),
   1765                     COMPILER_64_LO(old_packet_count),
   1766                     COMPILER_64_HI(hw_value),
   1767                     COMPILER_64_LO(hw_value)));
   1768 
   1769         if (width > 32) {
   1770             /* 64-bit field */
   1771             packet_count_hw[0] = COMPILER_64_LO(hw_value);
   1772             packet_count_hw[1] = COMPILER_64_HI(hw_value);
   1773         } else {
   1774              /* 32-bit field */
   1775             packet_count_hw[0] = COMPILER_64_LO(hw_value);
   1776             packet_count_hw[1] = 0;
   1777         }
   1778 
   1779         soc_mem_field_set(unit, counter_mem, (uint32 *)entry,
   1780                           counter_field, packet_count_hw);
   1781 
   1782         /* Memory write into hardware */
   1783         if (soc_mem_write(unit, counter_mem, MEM_BLOCK_ALL,
   1784                           offset_index, &entry) != BCM_E_NONE) {
   1785             TSN_STAT_PORTCNT_UNLOCK(pc);
   1786             return BCM_E_INTERNAL;
   1787         }
   1788     }
   1789 
   1790     /* Update Soft Copy for current HW counter */
   1791     COMPILER_64_COPY(portcnt_member->port_counter_hw[offset_index],
   1792                      hw_value);
   1793 
   1794     LOG_DEBUG(BSL_LS_BCM_TSN,
   1795               (BSL_META_U(unit,
   1796                           "Packet Count HW Value\t:TABLE:"
   1797                           "%s INDEX(port):%d : %x:%x \n"),
   1798               SOC_MEM_UFNAME(unit, counter_mem),
   1799               offset_index,
   1800               COMPILER_64_HI(portcnt_member->port_counter_hw[offset_index]),
   1801               COMPILER_64_LO(portcnt_member->port_counter_hw[offset_index])));
   1802 
   1803     TSN_STAT_PORTCNT_UNLOCK(pc);
   1804 
   1805     return BCM_E_NONE;
   1806 }
   1807 
   1808 /*
   1809  * Function:
   1810  *    bcmi_esw_tsn_stat_portcnt_update
   1811  * Description:
   1812  *    For SER module to update the SW & HW counter
   1813  *    with given memory and memory index
   1814  * Parameters:
   1815  *    unit - (IN) Unit number
   1816  *    mem -  (IN) TSN stat counter memory
   1817  *    mem_idx - (IN) memory index
   1818  *    new_count - (IN) new counter value
   1819  * Returns:
   1820  *    BCM_E_XXX
   1821  */
   1822 int
   1823 bcmi_esw_tsn_stat_portcnt_update(
   1824     int unit,
   1825     soc_mem_t mem,
   1826     int mem_idx,
   1827     uint64 new_count)
   1828 {
   1829     bcmi_tsn_stat_control_t *tc;
   1830     const bcmi_esw_tsn_stat_dev_info_t *tsn_stat_dev_info;
   1831     const tsn_stat_portcnt_dev_info_t *portcnt_dev_info;
   1832     const tsn_stat_portcnt_table_info_t *portcnt_table;
   1833     int total_entries, i;
   1834     bcm_gport_t port;
   1835     bcm_tsn_stat_t stat_itr = 0;
   1836 
   1837     /* Input parameter check. */
   1838     if (!SOC_MEM_IS_VALID(unit, mem)) {
   1839         return BCM_E_PARAM;
   1840     }
   1841 
   1842     total_entries = soc_mem_index_count(unit, mem);
   1843     if (mem_idx >= total_entries) {
   1844         LOG_ERROR(BSL_LS_BCM_TSN,
   1845                   (BSL_META_U(unit,
   1846                               "Wrong OFFSET_INDEX(Port). "
   1847                               "Must be < Total Entries %d \n"),
   1848                   total_entries));
   1849         assert(0);
   1850     }
   1851 
   1852     /* Get TSN stat control */
   1853     BCM_IF_ERROR_RETURN(
   1854         tsn_stat_control_instance_get(unit, &tc));
   1855 
   1856     /* Get chip specific info for TSN stat */
   1857     tsn_stat_dev_info = tc->tsn_stat_dev_info;
   1858     if (NULL == tsn_stat_dev_info) {
   1859         return BCM_E_UNAVAIL;
   1860     }
   1861     portcnt_dev_info = tsn_stat_dev_info->tsn_stat_portcnt_dev_info;
   1862     if (NULL == portcnt_dev_info) {
   1863         return BCM_E_UNAVAIL;
   1864     }
   1865 
   1866     /* Get stat_index based on the giving TSN statistic type = stat */
   1867     portcnt_table = portcnt_dev_info->portcnt_table_info;
   1868     if (NULL == portcnt_table) {
   1869         return BCM_E_UNAVAIL;
   1870     }
   1871 
   1872     for (i = 0; i < portcnt_dev_info->num_stats; i++) {
   1873         stat_itr = portcnt_table[i].portcnt_stat;
   1874 
   1875         assert((stat_itr >= 0) && (stat_itr < bcmTsnStatCount));
   1876         if (!soc_feature(unit, tsn_stat_type_feature[stat_itr])) {
   1877             continue;
   1878         }
   1879         if (mem == portcnt_table[i].portcnt_mem) {
   1880             break;
   1881         }
   1882     }
   1883 
   1884     if (i == portcnt_dev_info->num_stats) {
   1885         return BCM_E_NOT_FOUND;
   1886     }
   1887 
   1888     port = mem_idx;
   1889     BCM_IF_ERROR_RETURN(
   1890         bcmi_esw_tsn_stat_portcnt_set(unit, port, stat_itr, new_count));
   1891 
   1892     return BCM_E_NONE;
   1893 }
   1894 
   1895 /*
   1896  * Function:
   1897  *      bcmi_esw_tsn_stat_flowcnt_group_create
   1898  * Description:
   1899  *      Create a TSN stat group by picking stat types (in an array) to be
   1900  *      included for counting
   1901  * Parameters:
   1902  *      unit             - (IN) unit number
   1903  *      group_type       - (IN) TSN statistic group type
   1904  *      count            - (IN) the number of elements in stat_arr
   1905  *      stat_arr         - (IN) array for tsn stat types
   1906  *      stat_id          - (OUT) tsn statistic group id
   1907  *
   1908  * Return Value:
   1909  *      BCM_E_XXX
   1910  * Notes:
   1911  */
   1912 int
   1913 bcmi_esw_tsn_stat_flowcnt_group_create(
   1914     int unit,
   1915     bcm_tsn_stat_group_type_t group_type,
   1916     int count,
   1917     bcm_tsn_stat_t *stat_arr,
   1918     bcm_tsn_stat_group_t *stat_id)
   1919 {
   1920     int i, rv = BCM_E_NONE;
   1921     uint32 enable_values;
   1922     uint32 group_id;
   1923     bcmi_tsn_stat_flowcnt_control_t *fc;
   1924 
   1925     BCM_IF_ERROR_RETURN(
   1926         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   1927 
   1928     /* check feature support or not */
   1929     for (i = 0; i < count; i++) {
   1930         bcm_tsn_stat_t stat_itr = stat_arr[i];
   1931 
   1932         if (stat_itr < 0 || stat_itr >= bcmTsnStatCount) {
   1933             return BCM_E_PARAM;
   1934         }
   1935         if (!soc_feature(unit, tsn_stat_type_feature[stat_itr])) {
   1936             return BCM_E_UNAVAIL;
   1937         }
   1938     }
   1939 
   1940     BCM_IF_ERROR_RETURN(
   1941         TSN_STAT_FLOWCNT_FUNC(group_enable_value_encode,
   1942             (unit, group_type, stat_arr, count, &enable_values)));
   1943 
   1944     TSN_STAT_FLOWCNT_LOCK(fc);
   1945     rv = TSN_STAT_FLOWCNT_FUNC(group_enable_value_insert,
   1946              (unit, group_type, enable_values, &group_id));
   1947     TSN_STAT_FLOWCNT_UNLOCK(fc);
   1948 
   1949     BCM_IF_ERROR_RETURN(rv);
   1950     BCM_IF_ERROR_RETURN(
   1951         TSN_STAT_FLOWCNT_FUNC(group_id_encode,
   1952             (unit, group_type, group_id, stat_id)));
   1953     return BCM_E_NONE;
   1954 }
   1955 
   1956 /*
   1957  * Function:
   1958  *      bcmi_esw_tsn_stat_flowcnt_group_set
   1959  * Description:
   1960  *      Set configuration of the TSN stat group
   1961  * Parameters:
   1962  *      unit             - (IN) unit number
   1963  *      stat_id          - (IN) TSN statistic group id
   1964  *      count            - (IN) the number of elements in stat_arr
   1965  *      stat_arr         - (IN) array for TSN stat types
   1966  *
   1967  * Return Value:
   1968  *      BCM_E_XXX
   1969  * Notes:
   1970  */
   1971 int
   1972 bcmi_esw_tsn_stat_flowcnt_group_set(
   1973     int unit,
   1974     bcm_tsn_stat_group_t stat_id,
   1975     int count,
   1976     bcm_tsn_stat_t *stat_arr)
   1977 {
   1978     int i, rv = BCM_E_NONE;
   1979     bcm_tsn_stat_group_type_t group_type;
   1980     uint32 group_id;
   1981     int group_refcnt;
   1982     uint32 new_enable_values;
   1983     bcmi_tsn_stat_flowcnt_control_t *fc;
   1984 
   1985     BCM_IF_ERROR_RETURN(
   1986         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   1987 
   1988     /* check feature support or not */
   1989     for (i = 0; i < count; i++) {
   1990         bcm_tsn_stat_t stat_itr = stat_arr[i];
   1991 
   1992         if (stat_itr < 0 || stat_itr >= bcmTsnStatCount) {
   1993             return BCM_E_PARAM;
   1994         }
   1995         if (!soc_feature(unit, tsn_stat_type_feature[stat_itr])) {
   1996             return BCM_E_UNAVAIL;
   1997         }
   1998     }
   1999 
   2000     /* decode */
   2001     BCM_IF_ERROR_RETURN(
   2002         TSN_STAT_FLOWCNT_FUNC(group_id_decode,
   2003             (unit, stat_id, &group_type, &group_id)));
   2004     BCM_IF_ERROR_RETURN(
   2005         TSN_STAT_FLOWCNT_FUNC(group_enable_value_encode,
   2006             (unit, group_type, stat_arr, count, &new_enable_values)));
   2007 
   2008     TSN_STAT_FLOWCNT_LOCK(fc);
   2009     /* check group id has been just created and
   2010      * not attached on any flow yet
   2011      */
   2012     rv = TSN_STAT_FLOWCNT_FUNC(group_refcnt_get,
   2013              (unit, group_type, group_id, &group_refcnt));
   2014     if (BCM_SUCCESS(rv)) {
   2015         if (0 == group_refcnt) {
   2016             rv = BCM_E_PARAM;
   2017         } else if (1 != group_refcnt) {
   2018             rv = BCM_E_BUSY;
   2019         }
   2020     }
   2021 
   2022     /* check the new setting has already existed or not */
   2023     if (BCM_SUCCESS(rv)) {
   2024         rv = TSN_STAT_FLOWCNT_FUNC(group_enable_value_exist_check,
   2025                  (unit, group_type, new_enable_values));
   2026     }
   2027 
   2028     /* write new value */
   2029     if (BCM_SUCCESS(rv)) {
   2030         rv = TSN_STAT_FLOWCNT_FUNC(group_enable_value_set,
   2031                  (unit, group_type, group_id, new_enable_values));
   2032     }
   2033     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2034 
   2035     return rv;
   2036 }
   2037 
   2038 /*
   2039  * Function:
   2040  *      bcmi_esw_tsn_stat_flowcnt_group_get
   2041  * Description:
   2042  *      Get configuration of the TSN stat group
   2043  * Parameters:
   2044  *      unit             - (IN) unit number
   2045  *      stat_id          - (IN) TSN statistic group id
   2046  *      group_type       - (IN) TSN statistic group type
   2047  *      max              - (OUT) the size of stat_arr
   2048  *      stat_arr         - (OUT) array for returned TSN stat types
   2049  *      count            - (OUT) actual number of TSN stat types
   2050  *
   2051  * Return Value:
   2052  *      BCM_E_XXX
   2053  * Notes:
   2054  */
   2055 int
   2056 bcmi_esw_tsn_stat_flowcnt_group_get(
   2057     int unit,
   2058     bcm_tsn_stat_group_t stat_id,
   2059     bcm_tsn_stat_group_type_t *ret_group_type,
   2060     int max,
   2061     bcm_tsn_stat_t *stat_arr,
   2062     int *count)
   2063 {
   2064     int rv = BCM_E_NONE;
   2065     bcm_tsn_stat_group_type_t group_type;
   2066     uint32 group_id;
   2067     int group_refcnt;
   2068     uint32 enable_values;
   2069     bcmi_tsn_stat_flowcnt_control_t *fc;
   2070 
   2071     BCM_IF_ERROR_RETURN(
   2072         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2073 
   2074     if (NULL == ret_group_type) {
   2075         return BCM_E_PARAM;
   2076     }
   2077 
   2078     /* decode stat_id to  group_type, group_id */
   2079     BCM_IF_ERROR_RETURN(
   2080         TSN_STAT_FLOWCNT_FUNC(group_id_decode,
   2081             (unit, stat_id, &group_type, &group_id)));
   2082 
   2083     TSN_STAT_FLOWCNT_LOCK(fc);
   2084     /* and check group id has been created or not */
   2085     rv = TSN_STAT_FLOWCNT_FUNC(group_refcnt_get,
   2086              (unit, group_type, group_id, &group_refcnt));
   2087     if (BCM_SUCCESS(rv)) {
   2088         if (0 == group_refcnt) {
   2089             rv = BCM_E_PARAM;
   2090         }
   2091     }
   2092     /* get value */
   2093     if (BCM_SUCCESS(rv)) {
   2094         rv = TSN_STAT_FLOWCNT_FUNC(group_enable_value_get,
   2095                  (unit, group_type, group_id, &enable_values));
   2096     }
   2097     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2098 
   2099     BCM_IF_ERROR_RETURN(rv);
   2100     BCM_IF_ERROR_RETURN(
   2101         TSN_STAT_FLOWCNT_FUNC(group_enable_value_decode,
   2102             (unit, group_type, enable_values, stat_arr, max, count)));
   2103     *ret_group_type = group_type;
   2104 
   2105     return BCM_E_NONE;
   2106 }
   2107 
   2108 /*
   2109  * Function:
   2110  *      bcmi_esw_tsn_stat_flowcnt_group_destroy
   2111  * Description:
   2112  *      Destroy a TSN stat group
   2113  * Parameters:
   2114  *      unit             - (IN) unit number
   2115  *      stat_id          - (IN) TSN statistic group id
   2116  *
   2117  * Return Value:
   2118  *      BCM_E_XXX
   2119  * Notes:
   2120  */
   2121 int
   2122 bcmi_esw_tsn_stat_flowcnt_group_destroy(
   2123     int unit,
   2124     bcm_tsn_stat_group_t stat_id)
   2125 {
   2126     int rv = BCM_E_NONE;
   2127     bcm_tsn_stat_group_type_t group_type;
   2128     uint32 group_id;
   2129     int group_refcnt;
   2130     bcmi_tsn_stat_flowcnt_control_t *fc;
   2131 
   2132     BCM_IF_ERROR_RETURN(
   2133         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2134 
   2135 
   2136     /* decode */
   2137     BCM_IF_ERROR_RETURN(
   2138         TSN_STAT_FLOWCNT_FUNC(group_id_decode,
   2139             (unit, stat_id, &group_type, &group_id)));
   2140 
   2141     TSN_STAT_FLOWCNT_LOCK(fc);
   2142     /* check group id has been created and not attached on any flow */
   2143     rv = TSN_STAT_FLOWCNT_FUNC(group_refcnt_get,
   2144              (unit, group_type, group_id, &group_refcnt));
   2145     if (BCM_SUCCESS(rv)) {
   2146         if (0 == group_refcnt) {
   2147             rv = BCM_E_PARAM;
   2148         } else if (1 != group_refcnt) {
   2149             rv = BCM_E_BUSY;
   2150         }
   2151     }
   2152     if (BCM_SUCCESS(rv)) {
   2153         rv = TSN_STAT_FLOWCNT_FUNC(group_enable_value_delete,
   2154                  (unit, group_type, group_id));
   2155     }
   2156     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2157 
   2158     return rv;
   2159 }
   2160 
   2161 /*
   2162  * Function:
   2163  *      bcmi_esw_tsn_stat_flowcnt_group_traverse
   2164  * Description:
   2165  *      Traverse TSN stat groups
   2166  * Parameters:
   2167  *      unit             - (IN) unit number
   2168  *      cb               - (IN) User provided call back function
   2169  *      user_data        - (IN) User provided data
   2170  *
   2171  * Return Value:
   2172  *      BCM_E_XXX
   2173  * Notes:
   2174  */
   2175 int
   2176 bcmi_esw_tsn_stat_flowcnt_group_traverse(
   2177     int unit,
   2178     bcm_tsn_stat_group_traverse_cb cb,
   2179     void *user_data)
   2180 {
   2181     int rv = BCM_E_NONE;
   2182     bcmi_tsn_stat_flowcnt_control_t *fc;
   2183 
   2184     BCM_IF_ERROR_RETURN(
   2185         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2186 
   2187     TSN_STAT_FLOWCNT_LOCK(fc);
   2188     rv = TSN_STAT_FLOWCNT_FUNC(group_traverse, (unit, cb, user_data));
   2189     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2190 
   2191     return rv;
   2192 }
   2193 
   2194 /*
   2195  * Function:
   2196  *      bcmi_esw_tsn_stat_flowcnt_flow_get
   2197  * Description:
   2198  *      Get the stat group for this flow with specified group type
   2199  * Parameters:
   2200  *      unit             - (IN) unit number
   2201  *      flow             - (IN) SR flow
   2202  *      group_type       - (IN) TSN statistic group type
   2203  *      stat_group       - (OUT)TSN statistic group
   2204  *
   2205  * Return Value:
   2206  *      BCM_E_XXX
   2207  * Notes:
   2208  */
   2209 int
   2210 bcmi_esw_tsn_stat_flowcnt_flow_get(
   2211     int unit,
   2212     bcm_tsn_sr_flow_t flow_id,
   2213     bcm_tsn_stat_group_type_t group_type,
   2214     bcm_tsn_stat_group_t *stat_id)
   2215 {
   2216     uint32 group_id;
   2217     int rv = BCM_E_NONE;
   2218     bcmi_tsn_stat_flowcnt_control_t *fc;
   2219 
   2220     BCM_IF_ERROR_RETURN(
   2221         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2222 
   2223     if (NULL == stat_id) {
   2224         return BCM_E_PARAM;
   2225     }
   2226 
   2227     TSN_STAT_FLOWCNT_LOCK(fc);
   2228     rv = TSN_STAT_FLOWCNT_FUNC(flow_get,
   2229              (unit, flow_id, group_type, &group_id));
   2230     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2231     BCM_IF_ERROR_RETURN(rv);
   2232 
   2233     if (BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED == group_id) {
   2234         *stat_id = BCM_TSN_STAT_GROUP_INVALID;
   2235     } else {
   2236         BCM_IF_ERROR_RETURN(
   2237             TSN_STAT_FLOWCNT_FUNC(group_id_encode,
   2238                 (unit, group_type, group_id, stat_id)));
   2239     }
   2240     return BCM_E_NONE;
   2241 }
   2242 
   2243 /*
   2244  * Function:
   2245  *      bcmi_esw_tsn_stat_flowcnt_flow_set
   2246  * Description:
   2247  *      Attach ingress/egress stat group to this flow and enable counting for
   2248  *      the stat group. To disable counting for a specific group type, set
   2249  *      BCM_TSN_STAT_GROUP_INVALID as stat_group
   2250  * Parameters:
   2251  *      unit             - (IN) unit number
   2252  *      flow             - (IN) SR flow
   2253  *      group_type       - (IN) TSN statistic group type
   2254  *      stat_group       - (IN) TSN statistic group
   2255  *
   2256  * Return Value:
   2257  *      BCM_E_XXX
   2258  * Notes:
   2259  */
   2260 int
   2261 bcmi_esw_tsn_stat_flowcnt_flow_set(
   2262     int unit,
   2263     bcm_tsn_sr_flow_t flow_id,
   2264     bcm_tsn_stat_group_type_t group_type,
   2265     bcm_tsn_stat_group_t new_stat_id)
   2266 {
   2267     int rv = BCM_E_NONE;
   2268     uint32 new_group_id;
   2269     int new_group_refcnt;
   2270     bcmi_tsn_stat_flowcnt_control_t *fc;
   2271 
   2272     BCM_IF_ERROR_RETURN(
   2273         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2274 
   2275     /* parameter check if the user want to switch to the new group id */
   2276     if (BCM_TSN_STAT_GROUP_INVALID != new_stat_id) {
   2277         bcm_tsn_stat_group_type_t new_group_type;
   2278 
   2279         /* new group id should have the right group type */
   2280         BCM_IF_ERROR_RETURN(
   2281             TSN_STAT_FLOWCNT_FUNC(group_id_decode,
   2282                 (unit, new_stat_id, &new_group_type, &new_group_id)));
   2283 
   2284         if (new_group_type != group_type) {
   2285             BCM_IF_ERROR_RETURN(BCM_E_PARAM);
   2286         }
   2287     } else {
   2288         new_group_id = BCMI_TSN_FLOWCNT_GROUP_ID_RESERVED;
   2289     }
   2290 
   2291     TSN_STAT_FLOWCNT_LOCK(fc);
   2292     /* check new group id has been created or not */
   2293     if (BCM_TSN_STAT_GROUP_INVALID != new_stat_id) {
   2294         rv = TSN_STAT_FLOWCNT_FUNC(group_refcnt_get,
   2295                  (unit, group_type, new_group_id, &new_group_refcnt));
   2296         if (BCM_SUCCESS(rv)) {
   2297             if (0 == new_group_refcnt) {
   2298                 rv = BCM_E_PARAM;
   2299             }
   2300         }
   2301     }
   2302     if (BCM_SUCCESS(rv)) {
   2303         rv = TSN_STAT_FLOWCNT_FUNC(flow_set,
   2304                  (unit, flow_id, group_type, new_group_id));
   2305     }
   2306     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2307 
   2308     return rv;
   2309 }
   2310 
   2311 /*
   2312  * Function:
   2313  *      bcmi_esw_tsn_stat_flowcnt_set
   2314  * Description:
   2315  *      Helper function for flow counter set
   2316  * Parameters:
   2317  *      unit             - (IN) unit number
   2318  *      flow_id          - (IN) SR flow
   2319  *      arr_cnt          - (IN) size of stat_arr and value_arr
   2320  *      stat_type_arr    - (IN) TSN stat types
   2321  *      stat_value_arr   - (IN) TSN stat values
   2322  *
   2323  * Return Value:
   2324  *      BCM_E_XXX
   2325  * Notes:
   2326  */
   2327 int
   2328 bcmi_esw_tsn_stat_flowcnt_set(
   2329     int unit,
   2330     bcm_tsn_sr_flow_t flow_id,
   2331     uint32 arr_cnt,
   2332     bcm_tsn_stat_t *stat_type_arr,
   2333     uint64 *stat_value_arr)
   2334 {
   2335     int i, rv = BCM_E_NONE;
   2336     bcmi_tsn_stat_flowcnt_control_t *fc;
   2337 
   2338     BCM_IF_ERROR_RETURN(
   2339         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2340 
   2341     /* check feature support or not */
   2342     for (i = 0; i < arr_cnt; i++) {
   2343         bcm_tsn_stat_t stat_itr = stat_type_arr[i];
   2344 
   2345         if (stat_itr < 0 || stat_itr >= bcmTsnStatCount) {
   2346             return BCM_E_PARAM;
   2347         }
   2348         if (!soc_feature(unit, tsn_stat_type_feature[stat_itr])) {
   2349             return BCM_E_UNAVAIL;
   2350         }
   2351     }
   2352 
   2353     TSN_STAT_FLOWCNT_LOCK(fc);
   2354     /* for write, write both sw and hw value */
   2355     rv = TSN_STAT_FLOWCNT_FUNC(counter_access,
   2356                                (unit, flow_id, bcmiTsnStatCounterActionWrite,
   2357                                 arr_cnt, stat_type_arr,
   2358                                 stat_value_arr, stat_value_arr));
   2359     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2360     return rv;
   2361 }
   2362 
   2363 /*
   2364  * Function:
   2365  *      bcmi_esw_tsn_stat_flowcnt_get
   2366  * Description:
   2367  *      Helper function for flow counter get
   2368  * Parameters:
   2369  *      unit             - (IN) unit number
   2370  *      flow_id          - (IN) SR flow
   2371  *      sync_mode        - (IN) if 1 read hw counter else sw accumulated counter
   2372  *      arr_cnt          - (IN) size of stat_arr and value_arr
   2373  *      stat_type_arr    - (IN) TSN stat types
   2374  *      stat_value_arr   - (IN) TSN stat values
   2375  *
   2376  * Return Value:
   2377  *      BCM_E_XXX
   2378  * Notes:
   2379  */
   2380 int
   2381 bcmi_esw_tsn_stat_flowcnt_get(
   2382     int unit,
   2383     bcm_tsn_sr_flow_t flow_id,
   2384     int sync_mode,
   2385     uint32 arr_cnt,
   2386     bcm_tsn_stat_t *stat_type_arr,
   2387     uint64 *stat_value_arr)
   2388 {
   2389     int i, rv = BCM_E_NONE;
   2390     bcmi_tsn_stat_flowcnt_control_t *fc;
   2391 
   2392     BCM_IF_ERROR_RETURN(
   2393         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2394 
   2395     /* check feature support or not */
   2396     for (i = 0; i < arr_cnt; i++) {
   2397         bcm_tsn_stat_t stat_itr = stat_type_arr[i];
   2398 
   2399         if (stat_itr < 0 || stat_itr >= bcmTsnStatCount) {
   2400             return BCM_E_PARAM;
   2401         }
   2402         if (!soc_feature(unit, tsn_stat_type_feature[stat_itr])) {
   2403             return BCM_E_UNAVAIL;
   2404         }
   2405     }
   2406 
   2407     TSN_STAT_FLOWCNT_LOCK(fc);
   2408     /* for read, just need to read value from sw database
   2409      * (maybe need to sync at first)
   2410      */
   2411     rv = TSN_STAT_FLOWCNT_FUNC(counter_access,
   2412                                (unit, flow_id,
   2413                                 (sync_mode ?
   2414                                  bcmiTsnStatCounterActionReadSync :
   2415                                  bcmiTsnStatCounterActionRead),
   2416                                 arr_cnt, stat_type_arr, stat_value_arr, NULL));
   2417     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2418     return rv;
   2419 }
   2420 
   2421 /*
   2422  * Function:
   2423  *      bcmi_esw_tsn_stat_flowcnt_fbmp_get
   2424  * Description:
   2425  *      given a stat type, return all hw flow_id(s) been attached on it
   2426  * Parameters:
   2427  *      unit             - (IN) unit number
   2428  *      stat             - (IN) TSN stat type
   2429  *      fbmp             - (OUT)bitmap for return hw flow_id(s)
   2430  *      fbmp_size        - (IN) size of fbmp
   2431  *
   2432  * Return Value:
   2433  *      BCM_E_XXX
   2434  * Notes:
   2435  */
   2436 int
   2437 bcmi_esw_tsn_stat_flowcnt_fbmp_get(
   2438     int unit,
   2439     bcm_tsn_stat_t stat,
   2440     SHR_BITDCL  *fbmp,
   2441     uint32 fbmp_size)
   2442 {
   2443     int rv = BCM_E_NONE;
   2444     bcmi_tsn_stat_flowcnt_control_t *fc;
   2445 
   2446     BCM_IF_ERROR_RETURN(
   2447         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2448 
   2449     if (stat < 0 || stat >= bcmTsnStatCount) {
   2450         return BCM_E_PARAM;
   2451     }
   2452 
   2453     if (!soc_feature(unit, tsn_stat_type_feature[stat])) {
   2454         return BCM_E_UNAVAIL;
   2455     }
   2456 
   2457     TSN_STAT_FLOWCNT_LOCK(fc);
   2458     rv = TSN_STAT_FLOWCNT_FUNC(flow_get_fbmp, (unit, stat, fbmp, fbmp_size));
   2459     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2460 
   2461     return rv;
   2462 }
   2463 
   2464 
   2465 /*
   2466  * Function:
   2467  *      bcmi_esw_tsn_stat_flowcnt_hw_sw_get
   2468  * Description:
   2469  *      Helper function for flow counter get both sw/hw value
   2470  * Parameters:
   2471  *      unit             - (IN) unit number
   2472  *      stat             - (IN) TSN stat type
   2473  *      flow_id          - (IN) SR flow
   2474  *      hw_value         - (OUT) hw value
   2475  *      sw_value         - (OUT) sw value
   2476  *
   2477  * Return Value:
   2478  *      BCM_E_XXX
   2479  * Notes:
   2480  */
   2481 int
   2482 bcmi_esw_tsn_stat_flowcnt_hw_sw_get(
   2483     int unit,
   2484     bcm_tsn_stat_t stat,
   2485     bcm_tsn_sr_flow_t flow_id,
   2486     uint64 *hw_value,
   2487     uint64 *sw_value)
   2488 {
   2489     int rv = BCM_E_NONE;
   2490     bcmi_tsn_stat_flowcnt_control_t *fc;
   2491 
   2492     BCM_IF_ERROR_RETURN(
   2493         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2494 
   2495     if (stat < 0 || stat >= bcmTsnStatCount) {
   2496         return BCM_E_PARAM;
   2497     }
   2498     if (!soc_feature(unit, tsn_stat_type_feature[stat])) {
   2499         return BCM_E_UNAVAIL;
   2500     }
   2501 
   2502     TSN_STAT_FLOWCNT_LOCK(fc);
   2503     rv = TSN_STAT_FLOWCNT_FUNC(counter_access,
   2504                                (unit, flow_id, bcmiTsnStatCounterActionReadSync,
   2505                                 1, &stat, sw_value, hw_value));
   2506     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2507     return rv;
   2508 }
   2509 
   2510 /*
   2511  * Function:
   2512  *      bcmi_esw_tsn_stat_flowcnt_hw_set
   2513  * Description:
   2514  *      Helper function for flow counter set hw value
   2515  * Parameters:
   2516  *      unit             - (IN) unit number
   2517  *      stat             - (IN) TSN stat type
   2518  *      flow_id          - (IN) SR flow
   2519  *      hw_value         - (IN) hw value
   2520  *
   2521  * Return Value:
   2522  *      BCM_E_XXX
   2523  * Notes:
   2524  */
   2525 int
   2526 bcmi_esw_tsn_stat_flowcnt_hw_set(
   2527     int unit,
   2528     bcm_tsn_stat_t stat,
   2529     bcm_tsn_sr_flow_t flow_id,
   2530     uint64 hw_value)
   2531 {
   2532     int rv = BCM_E_NONE;
   2533     bcmi_tsn_stat_flowcnt_control_t *fc;
   2534 
   2535     BCM_IF_ERROR_RETURN(
   2536         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2537 
   2538     if (stat < 0 || stat >= bcmTsnStatCount) {
   2539         return BCM_E_PARAM;
   2540     }
   2541     if (!soc_feature(unit, tsn_stat_type_feature[stat])) {
   2542         return BCM_E_UNAVAIL;
   2543     }
   2544 
   2545     TSN_STAT_FLOWCNT_LOCK(fc);
   2546     rv = TSN_STAT_FLOWCNT_FUNC(counter_access,
   2547                                (unit, flow_id, bcmiTsnStatCounterActionWrite,
   2548                                 1, &stat, NULL, &hw_value));
   2549     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2550     return rv;
   2551 }
   2552 
   2553 /*
   2554  * Function:
   2555  *    bcmi_esw_tsn_stat_flowcnt_stat_sync
   2556  * Description:
   2557  *    Helper function to sync HW/SW TSN stat flowcnt per specified stat type.
   2558  * Parameters:
   2559  *    unit - (IN) Unit number
   2560  *    stat - (IN) TSN statistics type (see tsn.h)
   2561  * Returns:
   2562  *    BCM_E_XXX.
   2563  * Notes:
   2564  */
   2565 int bcmi_esw_tsn_stat_flowcnt_stat_sync(int unit, bcm_tsn_stat_t stat)
   2566 {
   2567     int rv = BCM_E_NONE;
   2568     bcmi_tsn_stat_flowcnt_control_t *fc;
   2569 
   2570     BCM_IF_ERROR_RETURN(
   2571         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2572 
   2573     if (stat < 0 || stat >= bcmTsnStatCount) {
   2574         return BCM_E_PARAM;
   2575     }
   2576 
   2577     if (!soc_feature(unit, tsn_stat_type_feature[stat])) {
   2578         return BCM_E_UNAVAIL;
   2579     }
   2580 
   2581     TSN_STAT_FLOWCNT_LOCK(fc);
   2582     rv = TSN_STAT_FLOWCNT_FUNC(counter_sync_stat, (unit, stat));
   2583     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2584 
   2585     return rv;
   2586 }
   2587 
   2588 /*
   2589  * Function:
   2590  *    bcmi_esw_tsn_stat_flowcnt_cleanup
   2591  * Description:
   2592  *    Clean and free all allocated TSN flow counter resources
   2593  * Parameters:
   2594  *    unit - (IN) Unit number
   2595  * Returns:
   2596  *    BCM_E_XXX
   2597  */
   2598 STATIC int
   2599 bcmi_esw_tsn_stat_flowcnt_cleanup(int unit)
   2600 {
   2601     bcmi_tsn_stat_flowcnt_control_t *fc;
   2602 
   2603     LOG_DEBUG(BSL_LS_BCM_TSN,
   2604               (BSL_META_U(unit,
   2605                           "bcmi_esw_tsn_stat_flowcnt_cleanup\n")));
   2606 
   2607     fc = tsn_stat_control[unit]->flowcnt_control;
   2608     if (NULL != fc->flowcnt_mutex) {
   2609         sal_mutex_destroy(fc->flowcnt_mutex);
   2610         fc->flowcnt_mutex = NULL;
   2611     }
   2612 
   2613     return BCM_E_NONE;
   2614 }
   2615 
   2616 
   2617 /*
   2618  * Function:
   2619  *    bcmi_esw_tsn_stat_flowcnt_init
   2620  * Description:
   2621  *    Initialize and allocate all required resources for TSN flow counters
   2622  * Parameters:
   2623  *    unit - (IN) Unit number
   2624  * Returns:
   2625  *    BCM_E_XXX
   2626  */
   2627 STATIC int
   2628 bcmi_esw_tsn_stat_flowcnt_init(int unit)
   2629 {
   2630     bcmi_tsn_stat_control_t *tc;
   2631     bcmi_tsn_stat_flowcnt_control_t *fc;
   2632 
   2633     /* Get TSN stat control */
   2634     BCM_IF_ERROR_RETURN(
   2635         tsn_stat_control_instance_get(unit, &tc));
   2636 
   2637     /* Set up the unit flowcnt control structure. */
   2638     fc = tc->flowcnt_control;
   2639     if (NULL == fc) {
   2640         return BCM_E_INIT;
   2641     }
   2642     sal_memset(fc, 0, sizeof(bcmi_tsn_stat_flowcnt_control_t));
   2643 
   2644     /* Create flowcnt protection mutex. */
   2645     fc->flowcnt_mutex = sal_mutex_create("tsn flowcnt control mutex");
   2646     if (NULL == fc->flowcnt_mutex) {
   2647         return BCM_E_RESOURCE;
   2648     }
   2649 
   2650     return BCM_E_NONE;
   2651 }
   2652 
   2653 /*
   2654  * Function:
   2655  *    bcmi_esw_tsn_stat_flowcnt_update
   2656  * Description:
   2657  *    For SER module to update the SW & HW counter
   2658  *    with given memory and memory index
   2659  * Parameters:
   2660  *    unit - (IN) Unit number
   2661  *    mem -  (IN) TSN stat counter memory
   2662  *    mem_idx - (IN) memory index
   2663  *    new_count - (IN) new counter value
   2664  * Returns:
   2665  *    BCM_E_XXX
   2666  */
   2667 int
   2668 bcmi_esw_tsn_stat_flowcnt_update(
   2669     int unit,
   2670     soc_mem_t mem,
   2671     int mem_idx,
   2672     uint64 new_count)
   2673 {
   2674     bcm_error_t rv = BCM_E_NOT_FOUND;
   2675     bcmi_tsn_stat_flowcnt_control_t *fc;
   2676     int total_entries;
   2677 
   2678     /* Input parameter check. */
   2679     if (!SOC_MEM_IS_VALID(unit, mem)) {
   2680         return BCM_E_PARAM;
   2681     }
   2682 
   2683     total_entries = soc_mem_index_count(unit, mem);
   2684     if (mem_idx >= total_entries) {
   2685         LOG_ERROR(BSL_LS_BCM_TSN,
   2686                   (BSL_META_U(unit,
   2687                               "Wrong OFFSET_INDEX(Flow). "
   2688                               "Must be < Total Entries %d \n"),
   2689                   total_entries));
   2690         assert(0);
   2691     }
   2692     BCM_IF_ERROR_RETURN(
   2693         tsn_stat_flowcnt_control_instance_get(unit, &fc));
   2694 
   2695     TSN_STAT_FLOWCNT_LOCK(fc);
   2696     /* for write, write both sw and hw value */
   2697     rv = TSN_STAT_FLOWCNT_FUNC(counter_update,
   2698                                (unit, mem, mem_idx, new_count));
   2699     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2700     return rv;
   2701 }
   2702 
   2703 /*
   2704  * Function:
   2705  *    bcmi_esw_tsn_stat_counter_update
   2706  * Description:
   2707  *    For SER module to update the SW & HW counter
   2708  *    with given memory and memory index
   2709  * Parameters:
   2710  *    unit - (IN) Unit number
   2711  *    mem -  (IN) TSN stat counter memory
   2712  *    mem_idx - (IN) memory index
   2713  *    new_count - (IN) new counter value
   2714  * Returns:
   2715  *    BCM_E_XXX
   2716  */
   2717 int
   2718 bcmi_esw_tsn_stat_counter_update(
   2719     int unit,
   2720     soc_mem_t mem,
   2721     int mem_idx,
   2722     uint64 new_count)
   2723 {
   2724     bcm_error_t rv1 = BCM_E_NOT_FOUND, rv2 = BCM_E_NOT_FOUND;
   2725 
   2726     /* Check if it's sr flow memory, update flow cnt if it is */
   2727     rv1 = bcmi_esw_tsn_stat_flowcnt_update(
   2728             unit, mem, mem_idx, new_count);
   2729     if (BCM_SUCCESS(rv1)) {
   2730         return rv1;
   2731     }
   2732 
   2733     /* Check if it's sr port memory, update port cnt if it is */
   2734     rv2 = bcmi_esw_tsn_stat_portcnt_update(
   2735             unit, mem, mem_idx, new_count);
   2736     if (BCM_SUCCESS(rv2)) {
   2737         return rv2;
   2738     }
   2739 
   2740     return BCM_E_NOT_FOUND;
   2741 }
   2742 
   2743 /*
   2744  * Function:
   2745  *    bcmi_esw_tsn_stat_counter_cb
   2746  * Description:
   2747  *    Callback function for counter collection
   2748  * Parameters:
   2749  *    unit - (IN) Unit number
   2750  * Returns:
   2751  *    BCM_E_XXX
   2752  */
   2753 STATIC void
   2754 bcmi_esw_tsn_stat_counter_cb(int unit)
   2755 {
   2756     bcmi_tsn_stat_portcnt_control_t *pc;
   2757     bcmi_tsn_stat_flowcnt_control_t *fc;
   2758 
   2759     (void)tsn_stat_portcnt_control_instance_get(unit, &pc);
   2760     (void)tsn_stat_flowcnt_control_instance_get(unit, &fc);
   2761     if (NULL == pc || NULL == fc) {
   2762         return;
   2763     }
   2764 
   2765     /* TSN stat portcnt callback */
   2766     TSN_STAT_PORTCNT_LOCK(pc);
   2767     bcmi_esw_tsn_stat_portcnt_collect(unit, -1, -1);
   2768     TSN_STAT_PORTCNT_UNLOCK(pc);
   2769     /* TSN stat flowcnt callback */
   2770     TSN_STAT_FLOWCNT_LOCK(fc);
   2771     (void)TSN_STAT_FLOWCNT_FUNC(counter_sync_all, (unit));
   2772     TSN_STAT_FLOWCNT_UNLOCK(fc);
   2773 }
   2774 
   2775 /*
   2776  * Function:
   2777  *    bcmi_esw_tsn_stat_threshold_init
   2778  * Description:
   2779  *    Initialize for TSN stat counter threshold
   2780  * Parameters:
   2781  *    unit - (IN) Unit number
   2782  * Returns:
   2783  *    BCM_E_XXX
   2784  */
   2785 STATIC int
   2786 bcmi_esw_tsn_stat_threshold_init(int unit)
   2787 {
   2788     bcmi_tsn_stat_control_t *tc;
   2789     const bcmi_esw_tsn_stat_dev_info_t *stat_dev_info;
   2790     const tsn_stat_threshold_ctrl_info_t *threshold_ctrl_info;
   2791 
   2792     BCM_IF_ERROR_RETURN(
   2793         tsn_stat_control_instance_get(unit, &tc));
   2794     stat_dev_info = tc->tsn_stat_dev_info;
   2795 
   2796     threshold_ctrl_info = stat_dev_info->tsn_stat_threshold_ctrl_info;
   2797     if ((threshold_ctrl_info != NULL) &&
   2798         (threshold_ctrl_info->tsn_stat_threshold_ctrl_init != NULL)) {
   2799         return threshold_ctrl_info->tsn_stat_threshold_ctrl_init(unit);
   2800     }
   2801 
   2802     return BCM_E_UNAVAIL;
   2803 }
   2804 
   2805 /*
   2806  * Function:
   2807  *    bcmi_esw_tsn_stat_cleanup
   2808  * Description:
   2809  *    Clean and free all allocated TSN stat counter resources
   2810  * Parameters:
   2811  *    unit - (IN) Unit number
   2812  * Returns:
   2813  *    BCM_E_XXX
   2814  */
   2815 int
   2816 bcmi_esw_tsn_stat_cleanup(int unit)
   2817 {
   2818     LOG_VERBOSE(BSL_LS_BCM_TSN,
   2819                 (BSL_META_U(unit,
   2820                             "bcmi_esw_tsn_stat_cleanup\n")));
   2821 
   2822 
   2823     soc_counter_extra_unregister(unit, bcmi_esw_tsn_stat_counter_cb);
   2824 
   2825     if (tsn_stat_control[unit] != NULL) {
   2826         if (tsn_stat_control[unit]->portcnt_control != NULL) {
   2827             bcmi_esw_tsn_stat_portcnt_cleanup(unit);
   2828             sal_free(tsn_stat_control[unit]->portcnt_control);
   2829             tsn_stat_control[unit]->portcnt_control = NULL;
   2830         }
   2831         if (tsn_stat_control[unit]->flowcnt_control != NULL) {
   2832             bcmi_esw_tsn_stat_flowcnt_cleanup(unit);
   2833             sal_free(tsn_stat_control[unit]->flowcnt_control);
   2834             tsn_stat_control[unit]->flowcnt_control = NULL;
   2835         }
   2836         if (tsn_stat_control[unit]->tsn_stat_dev_info != NULL) {
   2837             TSN_STAT_FLOWCNT_FUNC(cleanup, (unit));
   2838         }
   2839         sal_free(tsn_stat_control[unit]);
   2840         tsn_stat_control[unit] = NULL;
   2841     }
   2842 
   2843     ser_tsn_stat_functions._soc_tsn_stat_counter_update_f = NULL;
   2844     soc_ser_tsn_stat_function_register(unit, &ser_tsn_stat_functions);
   2845 
   2846     return BCM_E_NONE;
   2847 }
   2848 
   2849 /*
   2850  * Function:
   2851  *    bcmi_esw_tsn_stat_init
   2852  * Description:
   2853  *    Initialize and allocate all required resources for TSN stat counters
   2854  * Parameters:
   2855  *    unit - (IN) Unit number
   2856  * Returns:
   2857  *    BCM_E_XXX
   2858  */
   2859 int
   2860 bcmi_esw_tsn_stat_init(int unit)
   2861 {
   2862     int rv = BCM_E_NONE;
   2863     int i;
   2864     bcmi_tsn_stat_control_t *tc;
   2865 
   2866     LOG_VERBOSE(BSL_LS_BCM_TSN,
   2867                 (BSL_META_U(unit,
   2868                             "bcmi_esw_tsn_stat_init\n")));
   2869 
   2870     /* Global initialization flag setup */
   2871     if (tsn_stat_initialized == 0) {
   2872         for (i = 0; i < BCM_MAX_NUM_UNITS; i++) {
   2873             tsn_stat_control[i] = NULL;
   2874         }
   2875         tsn_stat_initialized = 1;
   2876     }
   2877 
   2878     /* Clean up the TSN stat control related resources */
   2879     if (tsn_stat_control[unit] != NULL) {
   2880         bcmi_esw_tsn_stat_cleanup(unit);
   2881     }
   2882 
   2883     /* Allocate TSN stat control resource for this unit. */
   2884     tsn_stat_control[unit] = sal_alloc(sizeof(bcmi_tsn_stat_control_t),
   2885                                        "tsn stat control");
   2886     tc = tsn_stat_control[unit];
   2887     if (NULL == tc) {
   2888         return BCM_E_MEMORY;
   2889     }
   2890     sal_memset(tc, 0, sizeof(bcmi_tsn_stat_control_t));
   2891 
   2892 
   2893     /* Get the chip tsn_stat_dev_info structure. */
   2894 #if defined(BCM_GREYHOUND2_SUPPORT)
   2895     if (SOC_IS_GREYHOUND2(unit)) {
   2896         rv = bcmi_gh2_tsn_stat_info_init(unit, &tc->tsn_stat_dev_info);
   2897         if (BCM_SUCCESS(rv) && NULL == tc->tsn_stat_dev_info) {
   2898             rv = BCM_E_INIT;
   2899         }
   2900     } else
   2901 #endif /* BCM_GREYHOUND2_SUPPORT */
   2902     {
   2903         rv = BCM_E_UNAVAIL;
   2904     }
   2905 
   2906     /* Release resource if any error occurred. */
   2907     if (BCM_FAILURE(rv)) {
   2908         bcmi_esw_tsn_stat_cleanup(unit);
   2909         return rv;
   2910     }
   2911     /* Check if tsn_stat_dev_info is NULL */
   2912     if (NULL == tc->tsn_stat_dev_info) {
   2913         bcmi_esw_tsn_stat_cleanup(unit);
   2914         return BCM_E_UNAVAIL;
   2915     }
   2916 
   2917     /* Initialize TSN Stat portcnt */
   2918     tsn_stat_control[unit]->portcnt_control
   2919         = sal_alloc(sizeof(bcmi_tsn_stat_portcnt_control_t),
   2920                     "tsn portcnt control");
   2921     if (NULL == tsn_stat_control[unit]->portcnt_control) {
   2922         bcmi_esw_tsn_stat_cleanup(unit);
   2923         return BCM_E_MEMORY;
   2924     }
   2925     rv = bcmi_esw_tsn_stat_portcnt_init(unit);
   2926     if (BCM_FAILURE(rv)) {
   2927         bcmi_esw_tsn_stat_cleanup(unit);
   2928         return rv;
   2929     }
   2930 
   2931     /* Initialize TSN Stat flowtcnt */
   2932     tsn_stat_control[unit]->flowcnt_control
   2933         = sal_alloc(sizeof(bcmi_tsn_stat_flowcnt_control_t),
   2934                     "tsn flowcnt control");
   2935     if (NULL == tsn_stat_control[unit]->flowcnt_control) {
   2936         bcmi_esw_tsn_stat_cleanup(unit);
   2937         return BCM_E_MEMORY;
   2938     }
   2939     rv = bcmi_esw_tsn_stat_flowcnt_init(unit);
   2940     if (BCM_FAILURE(rv)) {
   2941         bcmi_esw_tsn_stat_cleanup(unit);
   2942         return rv;
   2943     }
   2944 
   2945     /* Initialize chip-specific data */
   2946     rv = TSN_STAT_FLOWCNT_FUNC(init, (unit));
   2947     if (BCM_FAILURE(rv)) {
   2948         bcmi_esw_tsn_stat_cleanup(unit);
   2949         return rv;
   2950     }
   2951 
   2952     /* Register callback function for TSN stat counter */
   2953     rv = soc_counter_extra_register(unit, bcmi_esw_tsn_stat_counter_cb);
   2954     if (BCM_FAILURE(rv)) {
   2955         bcmi_esw_tsn_stat_cleanup(unit);
   2956         return rv;
   2957     }
   2958 
   2959     /* Register callback function for SER TSN stat counter */
   2960     ser_tsn_stat_functions._soc_tsn_stat_counter_update_f =
   2961         &bcmi_esw_tsn_stat_counter_update;
   2962     rv = soc_ser_tsn_stat_function_register(unit, &ser_tsn_stat_functions);
   2963     if (BCM_FAILURE(rv)) {
   2964         bcmi_esw_tsn_stat_cleanup(unit);
   2965         return rv;
   2966     }
   2967 
   2968     /* Initialize TSN Stat counter threshold */
   2969     rv = bcmi_esw_tsn_stat_threshold_init(unit);
   2970     /* Release resource if any error occurred. */
   2971     if (BCM_FAILURE(rv)) {
   2972         bcmi_esw_tsn_stat_cleanup(unit);
   2973         return rv;
   2974     }
   2975 
   2976     return BCM_E_NONE;
   2977 }
   2978 
   2979 /*
   2980  * Function:
   2981  *    bcmi_esw_tsn_stat_threshold_set
   2982  * Purpose:
   2983  *    Configure threshold for a specific stat type on
   2984  *    a specific source
   2985  * Parameters:
   2986  *    unit   - (IN) Unit number
   2987  *    source - (IN) Stat source for TSN stat threshold check
   2988  *    stat   - (IN) TSN statistics type (see tsn.h)
   2989  *    config - (IN) TSN stat threshold configuration structure
   2990  * Returns:
   2991  *    BCM_E_XXX
   2992  */
   2993 int
   2994 bcmi_esw_tsn_stat_threshold_set(
   2995     int unit,
   2996     bcm_tsn_stat_threshold_source_t source,
   2997     bcm_tsn_stat_t stat,
   2998     bcm_tsn_stat_threshold_config_t *config)
   2999 {
   3000     bcmi_tsn_stat_control_t *tc;
   3001     const bcmi_esw_tsn_stat_dev_info_t *stat_dev_info;
   3002     const tsn_stat_threshold_ctrl_info_t *threshold_ctrl_info;
   3003 
   3004     BCM_IF_ERROR_RETURN(
   3005         tsn_stat_control_instance_get(unit, &tc));
   3006     stat_dev_info = tc->tsn_stat_dev_info;
   3007 
   3008     threshold_ctrl_info = stat_dev_info->tsn_stat_threshold_ctrl_info;
   3009     if ((threshold_ctrl_info != NULL) &&
   3010         (threshold_ctrl_info->tsn_stat_threshold_ctrl_set != NULL)) {
   3011         BCM_IF_ERROR_RETURN(
   3012             threshold_ctrl_info->tsn_stat_threshold_ctrl_set(unit,
   3013                                                              source,
   3014                                                              stat,
   3015                                                              config));
   3016 
   3017         /* Enable stat matrix (all ports) for syncing the counter */
   3018         return bcmi_esw_tsn_stat_portcnt_used_update
   3019                       (unit, -1, stat, BCM_TSN_STAT_PORTCNT_USED_SET);
   3020     }
   3021 
   3022     return BCM_E_UNAVAIL;
   3023 }
   3024 
   3025 /*
   3026  * Function:
   3027  *    bcmi_esw_tsn_stat_threshold_get
   3028  * Purpose:
   3029  *    Get the threshold configuration for a specific stat type on
   3030  *    a specific source
   3031  * Parameters:
   3032  *    unit   - (IN) Unit number
   3033  *    source - (IN) Stat source for TSN stat threshold check
   3034  *    stat   - (IN) TSN statistics type (see tsn.h)
   3035  *    config - (OUT) TSN stat threshold configuration structure
   3036  * Returns:
   3037  *    BCM_E_XXX
   3038  */
   3039 int
   3040 bcmi_esw_tsn_stat_threshold_get(
   3041     int unit,
   3042     bcm_tsn_stat_threshold_source_t source,
   3043     bcm_tsn_stat_t stat,
   3044     bcm_tsn_stat_threshold_config_t *config)
   3045 {
   3046     bcmi_tsn_stat_control_t *tc;
   3047     const bcmi_esw_tsn_stat_dev_info_t *stat_dev_info;
   3048     const tsn_stat_threshold_ctrl_info_t *threshold_ctrl_info;
   3049 
   3050     BCM_IF_ERROR_RETURN(
   3051         tsn_stat_control_instance_get(unit, &tc));
   3052     stat_dev_info = tc->tsn_stat_dev_info;
   3053 
   3054     threshold_ctrl_info = stat_dev_info->tsn_stat_threshold_ctrl_info;
   3055     if ((threshold_ctrl_info != NULL) &&
   3056         (threshold_ctrl_info->tsn_stat_threshold_ctrl_get != NULL)) {
   3057         return threshold_ctrl_info->tsn_stat_threshold_ctrl_get(unit,
   3058                                                                 source,
   3059                                                                 stat,
   3060                                                                 config);
   3061     }
   3062 
   3063     return BCM_E_UNAVAIL;
   3064 }
   3065 
   3066 #endif /* BCM_TSN_SUPPORT */
   3067