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

pstats.c (42623B)


      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  * Packetized Statistic
      8  * Purpose: API to set Packetized Stats registers.
      9  */
     10 
     11 #include <sal/core/libc.h>
     12 
     13 #include <shared/bsl.h>
     14 #include <soc/defs.h>
     15 
     16 #if defined(INCLUDE_PSTATS) && defined(BCM_TOMAHAWK3_SUPPORT)
     17 #include <soc/drv.h>
     18 #include <soc/mem.h>
     19 #include <soc/profile_mem.h>
     20 #include <soc/debug.h>
     21 #include <soc/tomahawk3.h>
     22 #include <soc/pstats.h>
     23 
     24 #include <bcm/error.h>
     25 #include <bcm/pstats.h>
     26 
     27 #include <bcm_int/bst.h>
     28 #include <bcm_int/esw/mbcm.h>
     29 #include <bcm_int/esw/tomahawk.h>
     30 #include <bcm_int/esw/tomahawk2.h>
     31 #include <bcm_int/esw/tomahawk3.h>
     32 
     33 #include <bcm_int/esw_dispatch.h>
     34 #include <bcm_int/esw/pstats.h>
     35 
     36 #ifdef BCM_WARM_BOOT_SUPPORT
     37 #include <bcm_int/esw/switch.h>
     38 #endif /* BCM_WARM_BOOT_SUPPORT */
     39 
     40 /* MMU pktstats control flags */
     41 
     42 
     43 #define PSTATS_SESSION_MIN          1
     44 #define PSTATS_SESSION_MAX          256
     45 
     46 #define TH3_MAX_POOL_COUNT          4
     47 #define TH3_MAX_UCQ_COUNT           1908
     48 
     49 /* Max Elements Count = UCQ + ING POOL + EGR POOL */
     50 #define TH3_MAX_ELEMENT_COUNT       TH3_MAX_UCQ_COUNT + TH3_MAX_POOL_COUNT * 2
     51 
     52 #define TH3_PORT_NUM_COS(unit, port)                            \
     53     ((IS_CPU_PORT(unit, port)) ? NUM_CPU_COSQ(unit) :           \
     54      (IS_LB_PORT(unit, port)) ? 12 : NUM_COS(unit))
     55 
     56 
     57 typedef struct pstats_session_s {
     58     bcm_pstats_session_id_t         session_id;
     59 
     60     /* session buffer */
     61     bcm_pstats_timestamp_t          timestamp;
     62     bcm_pstats_data_t               *data_array;
     63 
     64     /* session element info */
     65     int                             element_array_count;
     66     bcm_pstats_session_element_t    element_array[TH3_MAX_ELEMENT_COUNT];
     67 
     68     uint32                          enable;
     69 
     70     /* prev session */
     71     struct pstats_session_s         *prev_session;
     72     /* next session */
     73     struct pstats_session_s         *next_session;
     74 } pstats_session_t;
     75 
     76 typedef struct pstats_buffer_s {
     77     soc_mem_t                       mem;
     78     soc_mem_t                       clear_mem;
     79     int                             min_idx;
     80     int                             max_idx;
     81     int                             num_entries;
     82     uint8                           *buf;
     83 } pstats_buffer_t;
     84 
     85 
     86 typedef struct pstats_control_s {
     87     /* full buffer */
     88 #ifdef BCM_PSTATS_MEASURE
     89     uint64                              local_time;
     90     uint64                              local_time_end;
     91 #endif
     92     uint64                              utc_time;
     93     pstats_buffer_t                     ucq_buffer[2];
     94     _bcm_bst_cmn_unit_info_t        *bst_info;
     95     bcm_pstats_session_id_t         next_session_id;
     96     uint32                          session_count;
     97 #ifdef BCM_PSTATS_MEASURE
     98     uint64                          time_cost;
     99 #endif
    100     int                             stat_mode;
    101     int                             hw_cor_in_max_use_count;
    102     pstats_session_t                *first_session;
    103 } pstats_control_t;
    104 
    105 static soc_field_t                  ucq_field[4] = {BST_QUEUE_TOTAL_COUNT_0f, BST_QUEUE_TOTAL_COUNT_1f,
    106                                                     BST_QUEUE_TOTAL_COUNT_2f, BST_QUEUE_TOTAL_COUNT_3f};
    107 
    108 static pstats_control_t             *pstats_control[BCM_MAX_NUM_UNITS];
    109 #define PSTATS_CTRL_PTR(u)          (pstats_control[u])
    110 #define PSTATS_CTRL(u)              (*(pstats_control[u]))
    111 
    112 STATIC int
    113 bcm_th3_pstats_session_create(int unit, int options, int array_count,
    114                               bcm_pstats_session_element_t  *element_array,
    115                               bcm_pstats_session_id_t *session_id);
    116 STATIC int
    117 bcm_th3_pstats_session_destroy(int unit, bcm_pstats_session_id_t session_id);
    118 STATIC int
    119 bcm_th3_pstats_session_get(int unit, bcm_pstats_session_id_t session_id,
    120                            int array_max,
    121                            bcm_pstats_session_element_t *element_array,
    122                            int *array_count);
    123 STATIC int bcm_th3_pstats_data_sync(int unit);
    124 STATIC int
    125 bcm_th3_pstats_session_data_get(int unit, bcm_pstats_session_id_t session_id,
    126                                 int sync,
    127                                 bcm_pstats_timestamp_t *timestamp,
    128                                 int array_max,
    129                                 bcm_pstats_data_t *data,
    130                                 int *array_count);
    131 STATIC int
    132 bcm_th3_pstats_session_data_clear(int unit, bcm_pstats_session_id_t session_id);
    133 STATIC int
    134 bcm_th3_pstats_session_traverse(int unit, bcm_pstats_session_traverse_cb cb,
    135                                 void *user_data);
    136 
    137 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
    138 /*
    139  * Function:
    140  *     bcm_th3_pstats_sw_dump
    141  * Purpose:
    142  *     Displays PSTATS information maintained by software.
    143  * Parameters:
    144  *     unit - Device unit number
    145  * Returns:
    146  *     None
    147  */
    148 STATIC void
    149 bcm_th3_pstats_sw_dump(int unit)
    150 {
    151     pstats_session_t *cur_session;
    152 
    153     LOG_CLI((BSL_META_U(unit,
    154                         "=========== \n")));
    155     LOG_CLI((BSL_META_U(unit, "Pstats mode: %s\n"),
    156                         PSTATS_CTRL(unit).stat_mode ?
    157                         "Max-use-count" : "Instantaneous"));
    158     LOG_CLI((BSL_META_U(unit, "Total pstats session count: %d\n"),
    159                         PSTATS_CTRL(unit).session_count));
    160     cur_session = PSTATS_CTRL(unit).first_session;
    161     while (NULL != cur_session) {
    162         LOG_CLI((BSL_META_U(unit,
    163                             "Pstats session id: %d element count: %d\n"),
    164                             cur_session->session_id,
    165                             cur_session->element_array_count));
    166         cur_session = cur_session->next_session;
    167     }
    168     LOG_CLI((BSL_META_U(unit,
    169                         "=========== \n")));
    170     return;
    171 }
    172 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
    173 
    174 
    175 STATIC void
    176 _bcm_th3_pstats_session_cleanup(int unit, pstats_session_t *session)
    177 {
    178     session->enable = FALSE;
    179     if (NULL != session->data_array) {
    180         sal_free(session->data_array);
    181     }
    182 
    183     sal_memset(session, 0, sizeof(pstats_session_t));
    184 
    185     return;
    186 }
    187 
    188 STATIC pstats_session_t*
    189 _bcm_th3_pstats_session_get(int unit, bcm_pstats_session_id_t session_id)
    190 {
    191     int                 found = 0;
    192     pstats_session_t   *cur_session;
    193 
    194     cur_session = PSTATS_CTRL(unit).first_session;
    195     while (NULL != cur_session) {
    196         if (cur_session->session_id == session_id) {
    197             found = 1;
    198             break;
    199         }
    200         cur_session = cur_session->next_session;
    201     }
    202 
    203     if (found) {
    204         return cur_session;
    205     }
    206 
    207     return NULL;
    208 }
    209 
    210 /* Set a minimum available session id */
    211 STATIC void
    212 _bcm_th3_pstats_session_next_id_set(int unit)
    213 {
    214     pstats_session_t            *cur_session;
    215     bcm_pstats_session_id_t     id = PSTATS_SESSION_MIN;
    216 
    217     cur_session = PSTATS_CTRL(unit).first_session;
    218     while (NULL != cur_session) {
    219         if (id < cur_session->session_id) {
    220             break;
    221         } else if (id == cur_session->session_id) {
    222             /* this id already existed */
    223             id++;
    224         }
    225         cur_session = cur_session->next_session;
    226     }
    227 
    228     PSTATS_CTRL(unit).next_session_id = id;
    229 
    230     LOG_INFO(BSL_LS_BCM_PSTATS, (BSL_META_U(unit, "next %d\n"), id));
    231 }
    232 
    233 STATIC int
    234 _bcm_th3_pstats_session_delete(int unit, bcm_pstats_session_id_t session_id)
    235 {
    236     pstats_session_t            *cur_session;
    237 
    238     cur_session = _bcm_th3_pstats_session_get(unit, session_id);
    239     if (NULL == cur_session) {
    240         LOG_INFO(BSL_LS_BCM_PSTATS,
    241                  (BSL_META_U(unit, "pstats session %d not found\n"), session_id));
    242         return BCM_E_NOT_FOUND;
    243     }
    244     /* update session link */
    245     if ((NULL == cur_session->prev_session) &&
    246         (NULL == cur_session->next_session)) {
    247         /* only one session */
    248         PSTATS_CTRL(unit).first_session = NULL;
    249     } else if (NULL == cur_session->prev_session) {
    250         /* first session */
    251         PSTATS_CTRL(unit).first_session = cur_session->next_session;
    252         cur_session->next_session->prev_session = NULL;
    253     } else if (NULL == cur_session->next_session) {
    254         /* last session */
    255         cur_session->prev_session->next_session = NULL;
    256     } else {
    257         cur_session->prev_session->next_session = cur_session->next_session;
    258         cur_session->next_session->prev_session = cur_session->prev_session;
    259     }
    260     _bcm_th3_pstats_session_cleanup(unit, cur_session);
    261     if (NULL != cur_session) {
    262         sal_free(cur_session);
    263     }
    264     PSTATS_CTRL(unit).session_count--;
    265 
    266     _bcm_th3_pstats_session_next_id_set(unit);
    267 
    268     return BCM_E_NONE;
    269 }
    270 
    271 STATIC void
    272 _bcm_th3_pstats_session_insert(int unit, pstats_session_t *session)
    273 {
    274     pstats_session_t            *cur_session;
    275     bcm_pstats_session_id_t     id = session->session_id;
    276 
    277     cur_session = PSTATS_CTRL(unit).first_session;
    278     if (NULL == cur_session) {
    279         /* first session */
    280         PSTATS_CTRL(unit).first_session = session;
    281         session->prev_session = NULL;
    282         session->next_session = NULL;
    283     }
    284     while (NULL != cur_session) {
    285         if (id > cur_session->session_id) {
    286             /* last session */
    287             if (NULL == cur_session->next_session) {
    288                 cur_session->next_session = session;
    289                 session->prev_session = cur_session;
    290                 session->next_session = NULL;
    291                 break;
    292             } else {
    293                 cur_session = cur_session->next_session;
    294             }
    295         } else {
    296             /* first session */
    297             if (NULL == cur_session->prev_session) {
    298                 PSTATS_CTRL(unit).first_session = session;
    299                 session->prev_session = NULL;
    300                 session->next_session = cur_session;
    301                 cur_session->prev_session = session;
    302                 break;
    303             } else {
    304                 session->prev_session = cur_session->prev_session;
    305                 session->next_session = cur_session;
    306                 cur_session->prev_session->next_session = session;
    307                 cur_session->prev_session = session;
    308                 break;
    309             }
    310             break;
    311         }
    312     }
    313     PSTATS_CTRL(unit).session_count++;
    314 
    315     session->enable = TRUE;
    316 
    317     return;
    318 }
    319 
    320 STATIC void
    321 _bcm_th3_pstats_buffer_deinit(int unit, pstats_buffer_t *pbuf)
    322 {
    323     if (NULL == pbuf) {
    324         return;
    325     }
    326 
    327     if (NULL != pbuf->buf) {
    328         sal_free(pbuf->buf);
    329     }
    330     sal_memset(pbuf, 0, sizeof(pstats_buffer_t));
    331 
    332     return;
    333 }
    334 
    335 
    336 STATIC int
    337 _bcm_th3_pstats_buffer_init(int unit, soc_mem_t mem, soc_mem_t clear_mem,
    338                             pstats_buffer_t *pbuf)
    339 {
    340     int alloc_size;
    341 
    342     if (NULL == pbuf) {
    343         return BCM_E_PARAM;
    344     }
    345 
    346     if (NULL != pbuf->buf) {
    347         return BCM_E_PARAM;
    348     }
    349 
    350     pbuf->mem = mem;
    351     pbuf->clear_mem = clear_mem;
    352     pbuf->min_idx = soc_mem_index_min(unit, mem);
    353     pbuf->max_idx = soc_mem_index_max(unit, mem);
    354     pbuf->num_entries = soc_mem_index_max(unit, mem) + 1;
    355     alloc_size = sizeof(uint32) * soc_mem_entry_words(unit, mem);
    356     alloc_size *= pbuf->num_entries;
    357 
    358     pbuf->buf = sal_alloc(alloc_size, "pstats buffer");
    359     if (pbuf->buf == NULL) {
    360         return BCM_E_MEMORY;
    361     }
    362     sal_memset(pbuf->buf, 0, alloc_size);
    363 
    364     return BCM_E_NONE;
    365 }
    366 
    367 
    368 /*
    369  * Function:
    370  *      bcm_th3_pstats_deinit
    371  * Purpose:
    372  *      Deinitialize PSTATS driver functions
    373  *      for Tomahawk2 (BCM56970).
    374  * Parameters:
    375  *      unit - (IN) StrataSwitch unit number.
    376  * Returns:
    377  *      BCM_E_XXX
    378  */
    379 void
    380 bcm_th3_pstats_deinit(int unit)
    381 {
    382     pstats_session_t *cur_session, *next_session;
    383     int i;
    384 
    385     soc_pstats_deinit(unit);
    386     if (NULL != PSTATS_CTRL_PTR(unit)) {
    387         /* deinit Service pool will be done in BST*/
    388 
    389         for (i = 0; i < NUM_ITM(unit); i++) {
    390             if (soc_tomahawk3_itm_valid(unit, i)) {
    391                 _bcm_th3_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).ucq_buffer[i]);
    392             }
    393         }
    394 
    395         cur_session = PSTATS_CTRL(unit).first_session;
    396         while (NULL != cur_session) {
    397             next_session = cur_session->next_session;
    398             _bcm_th3_pstats_session_cleanup(unit, cur_session);
    399             if (NULL != cur_session) {
    400                 sal_free(cur_session);
    401             }
    402             PSTATS_CTRL(unit).session_count--;
    403             cur_session = next_session;
    404         }
    405 
    406         if (PSTATS_CTRL(unit).session_count != 0) {
    407             /* debug info */
    408         }
    409         sal_free(PSTATS_CTRL_PTR(unit));
    410         PSTATS_CTRL_PTR(unit) = NULL;
    411     }
    412 
    413     return;
    414 }
    415 
    416 
    417 /*
    418  * Function:
    419  *      bcm_th3_pstats_init
    420  * Purpose:
    421  *      Initialize PSTATS driver functions
    422  *      for Tomahawk3 (BCM56980).
    423  * Parameters:
    424  *      unit - (IN) StrataSwitch unit number.
    425  * Returns:
    426  *      BCM_E_XXX
    427  */
    428 int
    429 bcm_th3_pstats_init(int unit)
    430 {
    431     _bcm_pstats_unit_driver_t   *pstats_driver;
    432     pstats_buffer_t             *pbuf;
    433     int                         rv = BCM_E_NONE;
    434     soc_mem_t                   mem, clear_mem, base_mem;
    435     int                         itm;
    436     uint32                      flag;
    437     pstats_control_t            *ctrl;
    438 
    439     if (2 != soc_property_get(unit, spn_BUFFER_STATS_COLLECT_TYPE, 1)) {
    440         LOG_INFO(BSL_LS_BCM_PSTATS,
    441                  (BSL_META_U(unit, "current mode is not pstats, no need init\n")));
    442         return BCM_E_NONE;
    443     }
    444 
    445     pstats_driver = _BCM_PSTATS_UNIT_DRIVER(unit);
    446     if (pstats_driver == NULL) {
    447         return BCM_E_MEMORY;
    448     }
    449 
    450     ctrl = PSTATS_CTRL_PTR(unit);
    451 
    452     if (NULL == ctrl) {
    453         ctrl = sal_alloc(sizeof(pstats_control_t), "pstats_control_t");
    454         if (ctrl == NULL) {
    455             return BCM_E_MEMORY;
    456         }
    457     }
    458     sal_memset(ctrl, 0, sizeof(pstats_control_t));
    459     ctrl->bst_info = _BCM_UNIT_BST_INFO(unit);
    460     if (ctrl->bst_info == NULL) {
    461         return BCM_E_INTERNAL;
    462     }
    463     PSTATS_CTRL_PTR(unit) = ctrl;
    464     /* Initializing Driver functions for PSTATS */
    465     pstats_driver->session_create = bcm_th3_pstats_session_create;
    466     pstats_driver->session_destroy = bcm_th3_pstats_session_destroy;
    467     pstats_driver->session_get = bcm_th3_pstats_session_get;
    468     pstats_driver->data_sync = bcm_th3_pstats_data_sync;
    469     pstats_driver->session_data_get = bcm_th3_pstats_session_data_get;
    470     pstats_driver->session_data_clear = bcm_th3_pstats_session_data_clear;
    471     pstats_driver->session_traverse = bcm_th3_pstats_session_traverse;
    472 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
    473     pstats_driver->pstats_sw_dump = bcm_th3_pstats_sw_dump;
    474 #endif
    475 
    476     /* alloc buffer for full pstats table */
    477 
    478     /* ucq buffer */
    479     base_mem = MMU_THDO_BST_TOTAL_QUEUE_PKTSTATm;
    480     for (itm = 0; itm < NUM_ITM(unit); itm++) {
    481         if (!soc_tomahawk3_itm_valid(unit, itm)) {
    482             continue;
    483         }
    484         mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, itm);
    485         clear_mem = SOC_MEM_UNIQUE_ACC_ITM(unit, MMU_THDO_BST_TOTAL_QUEUEm, itm);
    486         if (mem == INVALIDm) {
    487             continue;
    488         }
    489 
    490         pbuf = &PSTATS_CTRL(unit).ucq_buffer[itm];
    491 
    492         rv = _bcm_th3_pstats_buffer_init(unit, mem, clear_mem, pbuf);
    493         if (BCM_FAILURE(rv)) {
    494             goto cleanup;
    495         }
    496     }
    497 
    498     PSTATS_CTRL(unit).next_session_id = PSTATS_SESSION_MIN;
    499 
    500     rv = soc_pstats_init(unit);
    501     if (BCM_FAILURE(rv)) {
    502         LOG_INFO(BSL_LS_SOC_COMMON,
    503                  (BSL_META_U(unit, "soc_pstats_init failed rv = %d\n"), rv));
    504         goto cleanup;
    505     }
    506     
    507 #ifdef BCM_WARM_BOOT_SUPPORT
    508     if (SOC_WARM_BOOT(unit)) {
    509         int config;
    510 
    511         /* get pstats config from HW */
    512         rv = soc_tomahawk3_mmu_pstats_mode_get(unit, &flag);
    513         if (BCM_FAILURE(rv)) {
    514             goto cleanup;
    515         }
    516 
    517         /* HW config is different with config property */
    518         if (!(flag & _TH3_MMU_PSTATS_ENABLE)) {
    519             LOG_ERROR(BSL_LS_SOC_COMMON,
    520                       (BSL_META_U(unit,
    521                                   "WARMBOOT ERROR.\n"
    522                                   "Current buffer stats mode is not pstats.\n")));
    523             rv = BCM_E_INIT;
    524             goto cleanup;
    525         }
    526 
    527         if (flag & _TH3_MMU_PSTATS_HWM_MOD) {
    528             PSTATS_CTRL(unit).stat_mode = 1;
    529             if (flag & _TH3_MMU_PSTATS_RESET_ON_READ) {
    530                 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 1;
    531             } else {
    532                 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 0;
    533             }
    534         } else {
    535             PSTATS_CTRL(unit).stat_mode = 0;
    536             PSTATS_CTRL(unit).hw_cor_in_max_use_count = 0;
    537         }
    538 
    539         config = soc_property_get(unit, spn_BUFFER_STATS_COLLECT_MODE, 0);
    540         if (config != PSTATS_CTRL(unit).stat_mode) {
    541             LOG_WARN(BSL_LS_SOC_COMMON,
    542                      (BSL_META_U(unit,
    543                                  "WARMBOOT WARNING.\n"
    544                                  "Config mode %d. HW mode %d.\n"),
    545                                  config, PSTATS_CTRL(unit).stat_mode));
    546         }
    547 
    548         flag |= _TH3_MMU_PSTATS_SYNC | _TH3_MMU_PSTATS_MOR_EN;
    549 
    550         /* Reset pstats mode in warmboot */
    551         rv = soc_tomahawk3_mmu_pstats_mode_set(unit, flag);
    552         if (BCM_FAILURE(rv)) {
    553             goto cleanup;
    554         }
    555     } else
    556 #endif
    557     {
    558         PSTATS_CTRL(unit).stat_mode =
    559                 soc_property_get(unit, spn_BUFFER_STATS_COLLECT_MODE, 0);
    560         if ((PSTATS_CTRL(unit).stat_mode == 1) &&
    561             soc_property_get(unit, "oob_pstats_hw_cor_en", 1)) {
    562             PSTATS_CTRL(unit).hw_cor_in_max_use_count = 1;
    563         } else {
    564             PSTATS_CTRL(unit).hw_cor_in_max_use_count = 0;
    565         }
    566 
    567         /* call soc function */
    568         flag = _TH3_MMU_PSTATS_ENABLE |
    569                _TH3_MMU_PSTATS_SYNC |
    570                _TH3_MMU_PSTATS_MOR_EN;
    571 
    572 
    573         if (PSTATS_CTRL(unit).stat_mode) {
    574             flag |= _TH3_MMU_PSTATS_HWM_MOD;
    575             if (PSTATS_CTRL(unit).hw_cor_in_max_use_count == 1) {
    576                 flag |= _TH3_MMU_PSTATS_RESET_ON_READ;
    577             }
    578         }
    579 
    580         rv = soc_tomahawk3_mmu_pstats_mode_set(unit, flag);
    581         if (BCM_FAILURE(rv)) {
    582             goto cleanup;
    583         }
    584     }
    585     return BCM_E_NONE;
    586 
    587 cleanup:
    588     soc_pstats_deinit(unit);
    589     (void)bcm_th3_pstats_deinit(unit);
    590 
    591     return rv;
    592 }
    593 
    594 STATIC int
    595 _bcm_th3_pstats_session_element_check(int unit,
    596                                        bcm_pstats_session_element_t element)
    597 {
    598     bcm_gport_t                 gport;
    599     bcm_port_t                  local_port;
    600     bcm_cos_queue_t             cosq;
    601 
    602     LOG_INFO(BSL_LS_BCM_PSTATS,
    603              (BSL_META_U(unit, "pstats_session_element_check unit %d\n"), unit));
    604 
    605     if (element.type == bcmPStatsSessionUnicastQueue) {
    606         gport = element.gport;
    607         cosq = element.cosq;
    608         if (BCM_GPORT_IS_SET(gport)) {
    609             if (BCM_GPORT_IS_LOCAL(gport)) {
    610                 local_port = BCM_GPORT_LOCAL_GET(gport);
    611             } else if (BCM_GPORT_IS_MODPORT(gport)) {
    612                 BCM_IF_ERROR_RETURN(
    613                     bcm_esw_port_local_get(unit, gport, &local_port));
    614             } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    615                 return BCM_E_NONE;
    616             } else {
    617                 LOG_INFO(BSL_LS_BCM_PSTATS,
    618                          (BSL_META_U(unit,
    619                                      "pstats_session_element_check: "
    620                                      "gport 0x%x is illegal!\n"), gport));
    621                 return BCM_E_PARAM;
    622             }
    623         } else {
    624             local_port = gport;
    625         }
    626 
    627         if (!SOC_PORT_VALID(unit, local_port) || IS_CPU_PORT(unit, local_port)) {
    628             LOG_INFO(BSL_LS_BCM_PSTATS,
    629                      (BSL_META_U(unit,
    630                                  "pstats_session_element_check: "
    631                                  "gport 0x%x is illegal!\n"), gport));
    632             return BCM_E_PORT;
    633         }
    634         /* cosq check when gport is a port gport */
    635         if ((cosq < 0) || (cosq >= TH3_PORT_NUM_COS(unit, local_port))) {
    636             LOG_INFO(BSL_LS_BCM_PSTATS,
    637                      (BSL_META_U(unit,
    638                                  "pstats_session_element_check: "
    639                                  "cosq %d is illegal!\n"), cosq));
    640             return BCM_E_PARAM;
    641         }
    642     } else if ((element.type == bcmPStatsSessionIngPool) ||
    643                (element.type == bcmPStatsSessionEgrPool)) {
    644         if ((element.pool < 0) || (element.pool >= TH3_MAX_POOL_COUNT)) {
    645             LOG_INFO(BSL_LS_BCM_PSTATS,
    646                      (BSL_META_U(unit,
    647                                  "pstats_session_element_check: "
    648                                  "pool_id %d is illegal!\n"), element.pool));
    649             return BCM_E_PARAM;
    650         }
    651     } else {
    652         LOG_INFO(BSL_LS_BCM_PSTATS,
    653                  (BSL_META_U(unit,
    654                              "pstats_session_element_check: "
    655                              "unknow element type %d\n"), element.type));
    656         return BCM_E_PARAM;
    657     }
    658 
    659     return BCM_E_NONE;
    660 }
    661 
    662 
    663 /*
    664  * Function:
    665  *      bcm_th3_pstats_session_create
    666  * Purpose:
    667  *      Create a PKT STAT session instance for SDK management.
    668  * Parameters:
    669  *      unit - (IN) StrataSwitch unit number.
    670  *      options - (IN) BCM_PSTATS_REPLACE: replace existing.
    671  *                     BCM_PSTATS_WITH_ID: session_id argument is given.
    672  *      array_count - (IN) Number of elements in array.
    673  *      element_array - (IN) PSTATS session element array.
    674  *      session_id - (INOUT) id of a PSTATS session created via this API.
    675  * Returns:
    676  *      BCM_E_XXX
    677  */
    678 STATIC int
    679 bcm_th3_pstats_session_create(int unit, int options, int array_count,
    680                               bcm_pstats_session_element_t  *element_array,
    681                               bcm_pstats_session_id_t *session_id)
    682 {
    683     int                         rv, i, alloc_size;
    684     bcm_pstats_session_id_t     id = 0;
    685     pstats_session_t            *cur_session = NULL;
    686 
    687     LOG_INFO(BSL_LS_BCM_PSTATS,
    688              (BSL_META_U(unit, "pstats_session_create unit %d options %d "
    689                                "array_count %d\n"), unit, options, array_count));
    690 
    691     /* element check */
    692     if ((array_count < 0) ||
    693         (array_count > TH3_MAX_ELEMENT_COUNT)) {
    694         LOG_ERROR(BSL_LS_BCM_PSTATS,
    695                   (BSL_META_U(unit, "array_count %d is illegal!\n"), array_count));
    696         return BCM_E_PARAM;
    697     }
    698     if (NULL == element_array) {
    699         LOG_ERROR(BSL_LS_BCM_PSTATS,
    700                   (BSL_META_U(unit, "element_array is null\n")));
    701         return BCM_E_PARAM;
    702     }
    703 
    704     for (i = 0; i < array_count; i++) {
    705         BCM_IF_ERROR_RETURN(
    706                 _bcm_th3_pstats_session_element_check(unit, element_array[i]));
    707     }
    708 
    709     if (options & BCM_PSTATS_OPTIONS_REPLACE) {
    710         /* delete original session first */
    711         id = *session_id;
    712         BCM_IF_ERROR_RETURN(_bcm_th3_pstats_session_delete(unit, id));
    713     } else if (options & BCM_PSTATS_OPTIONS_WITH_ID) {
    714         id = *session_id;
    715         if (id < PSTATS_SESSION_MIN) {
    716             LOG_ERROR(BSL_LS_BCM_PSTATS,
    717                       (BSL_META_U(unit, "input session_id %d is illegal!\n"), id));
    718             return BCM_E_PARAM;
    719         }
    720         cur_session = _bcm_th3_pstats_session_get(unit, id);
    721         if (NULL != cur_session) {
    722             LOG_INFO(BSL_LS_BCM_PSTATS,
    723                      (BSL_META_U(unit, "pstats_session_create: "
    724                                        "session_id %d is existed\n"), id));
    725             return BCM_E_EXISTS;
    726         }
    727     } else {
    728         id = PSTATS_CTRL(unit).next_session_id;
    729     }
    730 
    731     /* SDK has a limitation of maxium session count */
    732     if (PSTATS_CTRL(unit).session_count >= PSTATS_SESSION_MAX) {
    733         LOG_INFO(BSL_LS_BCM_PSTATS,
    734                  (BSL_META_U(unit, "pstats_session_create: "
    735                                    "session count is full\n")));
    736         return BCM_E_FULL;
    737     }
    738 
    739     cur_session =
    740         (pstats_session_t*) sal_alloc(sizeof(pstats_session_t),
    741                                       "pstats session");
    742     if (NULL == cur_session) {
    743         return BCM_E_MEMORY;
    744     }
    745     sal_memset(cur_session, 0, sizeof(pstats_session_t));
    746 
    747     /* record session info */
    748     cur_session->session_id = id;
    749     cur_session->element_array_count = array_count;
    750     sal_memcpy(cur_session->element_array,
    751                element_array,
    752                array_count * sizeof(bcm_pstats_session_element_t));
    753 
    754     alloc_size = array_count * sizeof(bcm_pstats_data_t);
    755     cur_session->data_array = sal_alloc(alloc_size, "data array");
    756     if (NULL == cur_session->data_array) {
    757         rv = BCM_E_MEMORY;
    758         goto cleanup;
    759     }
    760     sal_memset(cur_session->data_array, 0, alloc_size);
    761 
    762     _bcm_th3_pstats_session_insert(unit, cur_session);
    763     _bcm_th3_pstats_session_next_id_set(unit);
    764 
    765     *session_id = id;
    766     return BCM_E_NONE;
    767 cleanup:
    768     _bcm_th3_pstats_session_cleanup(unit, cur_session);
    769     if (NULL != cur_session) {
    770         sal_free(cur_session);
    771     }
    772     return rv;
    773 }
    774 
    775 /*
    776  * Function:
    777  *      bcm_th3_pstats_session_destroy
    778  * Purpose:
    779  *      Destroy an existing PSTATS session.
    780  * Parameters:
    781  *      unit - (IN) StrataSwitch unit number.
    782  *      session_id - (IN) id of a PSTATS session created via the
    783  *                        bcm_pkt==stats_session_create
    784  * Returns:
    785  *      BCM_E_XXX
    786  */
    787 STATIC int
    788 bcm_th3_pstats_session_destroy(int unit,
    789                                bcm_pstats_session_id_t session_id)
    790 {
    791     return _bcm_th3_pstats_session_delete(unit, session_id);
    792 }
    793 
    794 /*
    795  * Function:
    796  *      bcm_th3_pstats_session_get
    797  * Purpose:
    798  *      Get an existing PSTATS session info.
    799  * Parameters:
    800  *      unit - (IN) StrataSwitch unit number.
    801  *      session_id - (IN) id of a PSTATS session created via the
    802  *                        bcm_pstats_session_create
    803  *      array_max - (IN) Maximum number of elements in array.
    804  *      element_array - (OUT) element array of a PSTATS session.
    805  *      array_count - (OUT) Number of elements in array.
    806  * Returns:
    807  *      BCM_E_XXX
    808  */
    809 STATIC int
    810 bcm_th3_pstats_session_get(int unit,
    811                            bcm_pstats_session_id_t session_id,
    812                            int array_max,
    813                            bcm_pstats_session_element_t *element_array,
    814                            int *array_count)
    815 {
    816     pstats_session_t *cur_session = NULL;
    817     LOG_INFO(BSL_LS_BCM_PSTATS,
    818              (BSL_META_U(unit, "pstats_session_get unit %d session_id %d\n"),
    819                                unit, session_id));
    820 
    821     if (NULL == element_array) {
    822         LOG_ERROR(BSL_LS_BCM_PSTATS,
    823                   (BSL_META_U(unit, "element_array is null\n")));
    824         return BCM_E_PARAM;
    825     }
    826 
    827     cur_session = _bcm_th3_pstats_session_get(unit, session_id);
    828     if (NULL == cur_session) {
    829         LOG_INFO(BSL_LS_BCM_PSTATS,
    830                  (BSL_META_U(unit, "pstats session %d not found\n"), session_id));
    831         return BCM_E_NOT_FOUND;
    832     }
    833 
    834     if (array_max >= cur_session->element_array_count) {
    835         *array_count = cur_session->element_array_count;
    836     } else if (array_max >= 0){
    837         *array_count = array_max;
    838     } else {
    839         return BCM_E_PARAM;
    840     }
    841 
    842     sal_memcpy(element_array,
    843                cur_session->element_array,
    844                *array_count * sizeof(bcm_pstats_session_element_t));
    845 
    846     return BCM_E_NONE;
    847 }
    848 
    849 STATIC int
    850 _bcm_th3_pstats_session_data_update(int unit,
    851                                     bcm_pstats_session_element_t element,
    852                                     bcm_pstats_data_t *data)
    853 {
    854     bcm_gport_t                 gport;
    855     bcm_port_t                  local_port;
    856     bcm_cos_queue_t             cosq;
    857     int                         pen_idx = 0;
    858     int                         mode, i, itm, startq, offset;
    859     uint8                       *total_buf;
    860     uint32                      cur_val = 0, *pre_p;
    861     void                        *pentry;
    862     soc_mem_t                   mem;
    863     _bcm_bst_cmn_unit_info_t    *bst_info;
    864 
    865     mode = PSTATS_CTRL(unit).stat_mode;
    866 
    867     if (element.type == bcmPStatsSessionUnicastQueue) {
    868 
    869         gport = element.gport;
    870         cosq = element.cosq;
    871         BCM_IF_ERROR_RETURN(
    872             _bcm_th3_cosq_index_resolve(unit, gport, cosq,
    873                                        _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
    874                                        &local_port, &startq, NULL));
    875         for (itm = 0, i = 0; itm < NUM_ITM(unit); itm++) {
    876             if (!soc_tomahawk3_itm_valid(unit, itm)) {
    877                 continue;
    878             }
    879             total_buf = PSTATS_CTRL(unit).ucq_buffer[itm].buf;
    880             mem = PSTATS_CTRL(unit).ucq_buffer[itm].mem;
    881             pen_idx = startq / 4;
    882             offset = startq % 4;
    883             pentry = soc_mem_table_idx_to_pointer(unit, mem, void*,
    884                                                   total_buf, pen_idx);
    885             cur_val = soc_mem_field32_get(unit, mem, pentry, ucq_field[offset]);
    886 
    887             pre_p = &data->use_counts_array[i];
    888             if (mode) {
    889                 if (cur_val > *pre_p) {
    890                     *pre_p = cur_val;
    891                 }
    892             } else {
    893                 *pre_p = cur_val;
    894             }
    895             i++;
    896         }
    897         data->array_count = i;
    898     } else if(element.type == bcmPStatsSessionIngPool ||
    899                     element.type == bcmPStatsSessionEgrPool) {
    900         bcm_bst_stat_id_t bid = -1;
    901         bcm_service_pool_id_t pool = element.pool;
    902         bst_info = PSTATS_CTRL(unit).bst_info;
    903         if (pool < 0 || pool >= TH3_MAX_POOL_COUNT) {
    904             return BCM_E_PARAM;
    905         }
    906         if (element.type == bcmPStatsSessionIngPool) {
    907             bid = bcmBstStatIdIngPool;
    908         } else {
    909             bid = bcmBstStatIdEgrPool;
    910         }
    911         for (itm = 0, i = 0; itm < NUM_ITM(unit); itm++) {
    912             if (!soc_tomahawk3_itm_valid(unit, itm)) {
    913                 continue;
    914             }
    915             cur_val =
    916                     bst_info->resource_tbl[bid].p_stat[itm * TH3_MAX_POOL_COUNT + pool];
    917             pre_p = &data->use_counts_array[i];
    918             if (mode) {
    919                 if (cur_val > *pre_p) {
    920                     *pre_p = cur_val;
    921                 }
    922             } else {
    923                 *pre_p = cur_val;
    924             }
    925             i++;
    926         }
    927         data->array_count = i;
    928     }
    929 
    930     return BCM_E_NONE;
    931 }
    932 
    933 STATIC int
    934 _bcm_th3_pstats_session_update(int unit, pstats_session_t *session)
    935 {
    936     bcm_pstats_session_element_t    element;
    937     bcm_pstats_data_t               *data;
    938     pstats_session_t                *cur_session = session;
    939     int                             i;
    940     soc_reg_t                       reg;
    941     uint32                          fval;
    942     /*
    943      * update UTC timestamp
    944      */
    945     reg = MMU_GLBCFG_UTC_TIMESTAMPr;
    946     cur_session->timestamp.nanoseconds =
    947             soc_reg64_field32_get
    948                 (unit, reg, PSTATS_CTRL(unit).utc_time, UTC_TIMESTAMP_NSECf);
    949 
    950     fval = soc_reg64_field32_get(unit, reg, PSTATS_CTRL(unit).utc_time, UTC_TIMESTAMP_SECf);
    951     COMPILER_64_ADD_32(cur_session->timestamp.seconds, fval);
    952 
    953 #ifdef BCM_PSTATS_MEASURE
    954     if (soc_property_get(unit, "pstats_timestamp_info", 0) == 1) {
    955         COMPILER_64_TO_32_LO(cur_session->timestamp.nanoseconds,
    956                              PSTATS_CTRL(unit).time_cost);
    957     }
    958 #endif
    959 
    960     /* update element data */
    961     for (i = 0; i < cur_session->element_array_count; i++) {
    962         element = cur_session->element_array[i];
    963         data = &cur_session->data_array[i];
    964         BCM_IF_ERROR_RETURN(
    965             _bcm_th3_pstats_session_data_update(unit, element, data));
    966     }
    967 
    968     return BCM_E_NONE;
    969 }
    970 
    971 /*
    972  * Function:
    973  *      _bcm_th3_pstats_hw_sync
    974  * Purpose:
    975  *      Start a pstats sync operation.
    976  * Parameters:
    977  *      unit - (IN) StrataSwitch unit number
    978  * Returns:
    979  *      BCM_E_XXX
    980  */
    981 STATIC int
    982 _bcm_th3_pstats_hw_sync(int unit)
    983 {
    984     pstats_buffer_t             *pbuf;
    985     int                         itm;
    986     soc_reg_t                   reg;
    987     SOC_IF_ERROR_RETURN(soc_pstats_sync(unit));
    988 
    989 #ifdef BCM_PSTATS_MEASURE
    990     
    991     reg = MMU_GLBCFG_TIMESTAMPr;
    992     SOC_IF_ERROR_RETURN(
    993             soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &PSTATS_CTRL(unit).local_time));
    994 
    995     SOC_IF_ERROR_RETURN(
    996             soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &PSTATS_CTRL(unit).local_time));
    997 #endif
    998     /*sync UTC time */
    999     COMPILER_64_ZERO(PSTATS_CTRL(unit).utc_time);
   1000     reg = MMU_GLBCFG_UTC_TIMESTAMPr;
   1001     SOC_IF_ERROR_RETURN(
   1002             soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &PSTATS_CTRL(unit).utc_time));
   1003     /* sync uc queue */
   1004     for (itm = 0; itm < NUM_ITM(unit); itm++) {
   1005         if (soc_tomahawk3_itm_valid(unit, itm)) {
   1006             pbuf = &PSTATS_CTRL(unit).ucq_buffer[itm];
   1007             SOC_IF_ERROR_RETURN(
   1008                 soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0));
   1009         }
   1010     }
   1011 
   1012     /* following resources are shared with BST */
   1013     BCM_IF_ERROR_RETURN(bcm_th_cosq_bst_stat_sync(unit, bcmBstStatIdIngPool));
   1014 
   1015     BCM_IF_ERROR_RETURN(bcm_th_cosq_bst_stat_sync(unit, bcmBstStatIdEgrPool));
   1016 
   1017     return BCM_E_NONE;
   1018 }
   1019 
   1020 /*
   1021  * Function:
   1022  *      _bcm_th3_pstats_session_data_sync
   1023  * Purpose:
   1024  *      Start a pstats sync operation for a special session
   1025  * Parameters:
   1026  *      unit - (IN) StrataSwitch unit number
   1027  * Returns:
   1028  *      BCM_E_XXX
   1029  */
   1030 STATIC int
   1031 _bcm_th3_pstats_session_data_sync(int unit, pstats_session_t *session)
   1032 {
   1033     BCM_IF_ERROR_RETURN(_bcm_th3_pstats_hw_sync(unit));
   1034     BCM_IF_ERROR_RETURN(_bcm_th3_pstats_session_update(unit, session));
   1035     return BCM_E_NONE;
   1036 }
   1037 
   1038 /*
   1039  * Function:
   1040  *      bcm_th3_pstats_data_sync
   1041  * Purpose:
   1042  *      Start a pstats sync operation.
   1043  * Parameters:
   1044  *      unit - (IN) StrataSwitch unit number
   1045  * Returns:
   1046  *      BCM_E_XXX
   1047  */
   1048 STATIC int
   1049 bcm_th3_pstats_data_sync(int unit)
   1050 {
   1051     pstats_session_t    *cur_session = NULL;
   1052     sal_usecs_t         start_time = sal_time_usecs();
   1053 
   1054     BCM_IF_ERROR_RETURN(_bcm_th3_pstats_hw_sync(unit));
   1055     LOG_DEBUG(BSL_LS_SOC_COMMON,
   1056               (BSL_META_U(unit, "Time taken for pstats dma: %d usec\n"),
   1057                           SAL_USECS_SUB(sal_time_usecs(), start_time)));
   1058     cur_session = PSTATS_CTRL(unit).first_session;
   1059     while (NULL != cur_session) {
   1060         if (cur_session->enable != TRUE) {
   1061             continue;
   1062         }
   1063         BCM_IF_ERROR_RETURN(
   1064                 _bcm_th3_pstats_session_update(unit, cur_session));
   1065         cur_session = cur_session->next_session;
   1066     }
   1067     return BCM_E_NONE;
   1068 }
   1069 
   1070 /*
   1071  * Function:
   1072  *      bcm_th3_pstats_session_data_get
   1073  * Purpose:
   1074  *      Get an existing PSTATS session data.
   1075  * Parameters:
   1076  *      unit - (IN) StrataSwitch unit number
   1077  *      session_id - (IN) id of a PSTATS session created via the
   1078  *                        bcm_pstats_session_create
   1079  *      sync - (IN) Need a sync operation
   1080  *      timestamp - (OUT) time stamp info.
   1081  *      array_max - (IN) Maximum number of elements in array.
   1082  *      data - (OUT) array of use count data.
   1083  *      array_count - (OUT) Number of elements in array.
   1084  * Returns:
   1085  *      BCM_E_XXX
   1086  */
   1087 STATIC int
   1088 bcm_th3_pstats_session_data_get(int unit, bcm_pstats_session_id_t session_id,
   1089                                 int sync,
   1090                                 bcm_pstats_timestamp_t *timestamp,
   1091                                 int array_max,
   1092                                 bcm_pstats_data_t *data_array,
   1093                                 int *array_count)
   1094 {
   1095     pstats_session_t        *cur_session = NULL;
   1096     int                     mode;
   1097 
   1098     LOG_INFO(BSL_LS_BCM_PSTATS,
   1099              (BSL_META_U(unit, "pstats_session_data_get unit %d session_id %d "
   1100                                "sync %d\n"), unit, session_id, sync));
   1101 
   1102     if (NULL == data_array) {
   1103         LOG_ERROR(BSL_LS_BCM_PSTATS,
   1104                   (BSL_META_U(unit, "data_array is null\n")));
   1105         return BCM_E_PARAM;
   1106     }
   1107 
   1108     mode = PSTATS_CTRL(unit).stat_mode;
   1109     cur_session = _bcm_th3_pstats_session_get(unit, session_id);
   1110     if (NULL == cur_session) {
   1111         LOG_INFO(BSL_LS_BCM_PSTATS,
   1112                  (BSL_META_U(unit, "pstats_session_data_get: "
   1113                                    "session_id %d is not found\n"), session_id));
   1114         return BCM_E_NOT_FOUND;
   1115     }
   1116 
   1117     if (array_max >= cur_session->element_array_count) {
   1118         *array_count = cur_session->element_array_count;
   1119     } else if (array_max >= 0){
   1120         *array_count = array_max;
   1121     } else {
   1122         LOG_ERROR(BSL_LS_BCM_PSTATS,
   1123                   (BSL_META_U(unit, "array_max %d is illegal\n"), array_max));
   1124         return BCM_E_PARAM;
   1125     }
   1126 
   1127     /* if PKT STAT mode is HWM, need to sync up all sessions */
   1128     if (TRUE == sync) {
   1129         if (mode) {
   1130             BCM_IF_ERROR_RETURN(bcm_th3_pstats_data_sync(unit));
   1131         } else {
   1132             BCM_IF_ERROR_RETURN(
   1133                     _bcm_th3_pstats_session_data_sync(unit, cur_session));
   1134         }
   1135     }
   1136 
   1137     sal_memcpy(data_array, cur_session->data_array,
   1138                *array_count * sizeof(bcm_pstats_data_t));
   1139 
   1140     sal_memcpy(timestamp, &cur_session->timestamp, sizeof(bcm_pstats_timestamp_t));
   1141 
   1142     return BCM_E_NONE;
   1143 }
   1144 
   1145 STATIC int
   1146 _bcm_th3_pstats_session_data_hw_clear(int unit, bcm_pstats_session_element_t element)
   1147 {
   1148     bcm_gport_t                 gport;
   1149     bcm_port_t                  local_port;
   1150     bcm_cos_queue_t             cosq;
   1151     int                         itm, startq;
   1152     soc_mem_t                   mem;
   1153     uint32                      entry[SOC_MAX_MEM_WORDS];
   1154     _bcm_bst_cmn_unit_info_t    *bst_info;
   1155 
   1156     bst_info = PSTATS_CTRL(unit).bst_info;
   1157 
   1158     if (element.type == bcmPStatsSessionUnicastQueue) {
   1159         gport = element.gport;
   1160         cosq = element.cosq;
   1161         /* Retrieve HW mem Index from resolve */
   1162         BCM_IF_ERROR_RETURN(
   1163             _bcm_th3_cosq_index_resolve(unit, gport, cosq,
   1164                                        _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   1165                                        &local_port, &startq, NULL));
   1166         for (itm = 0; itm < NUM_ITM(unit); itm++) {
   1167             if (!soc_tomahawk3_itm_valid(unit, itm)) {
   1168                 continue;
   1169             }
   1170             mem = PSTATS_CTRL(unit).ucq_buffer[itm].clear_mem;
   1171             SOC_IF_ERROR_RETURN(
   1172                 soc_mem_read(unit, mem, MEM_BLOCK_ANY, startq, entry));
   1173             soc_mem_field32_set(unit, mem, entry, BST_QUEUE_TOTAL_COUNTf, 0);
   1174             SOC_IF_ERROR_RETURN(
   1175                 soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   1176         }
   1177     } else if (element.type == bcmPStatsSessionIngPool
   1178         || element.type == bcmPStatsSessionEgrPool) {
   1179         bcm_bst_stat_id_t bid = -1;
   1180         if (element.type == bcmPStatsSessionIngPool) {
   1181             bid = bcmBstStatIdIngPool;
   1182         } else {
   1183             bid = bcmBstStatIdEgrPool;
   1184         }
   1185 
   1186         BCM_IF_ERROR_RETURN(
   1187             bcm_bst_th3_hw_stat_clear(unit, &bst_info->resource_tbl[bid],
   1188                 bid, -1, -1, element.pool, -1));
   1189     }
   1190     return BCM_E_NONE;
   1191 }
   1192 
   1193 /*
   1194  * Function:
   1195  *      bcm_th3_pstats_session_data_clear
   1196  * Purpose:
   1197  *      Clear an existing PSTATS session hw use counts and sw use counts buffer.
   1198  * Parameters:
   1199  *      unit - (IN) StrataSwitch unit number.
   1200  *      session_id - (IN) id of a PSTATS session created via the
   1201  *                        bcm_pstats_session_create.
   1202  * Returns:
   1203  *      BCM_E_XXX
   1204  */
   1205 STATIC int
   1206 bcm_th3_pstats_session_data_clear(int unit, bcm_pstats_session_id_t session_id)
   1207 {
   1208     bcm_pstats_session_element_t    element;
   1209     pstats_session_t                *cur_session = NULL;
   1210     int                             i, need_hw_clear = 1;
   1211 
   1212     LOG_INFO(BSL_LS_BCM_PSTATS,
   1213              (BSL_META_U(unit, "pstats_session_data_clear unit %d session_id %d\n"),
   1214                                unit, session_id));
   1215 
   1216     cur_session = _bcm_th3_pstats_session_get(unit, session_id);
   1217     if (NULL == cur_session) {
   1218         LOG_INFO(BSL_LS_BCM_PSTATS,
   1219                  (BSL_META_U(unit, "pstats_session_data_clear: "
   1220                                    "session_id %d is not found\n"), session_id));
   1221         return BCM_E_NOT_FOUND;
   1222     }
   1223 
   1224     /* clear HW use count buffer */
   1225     if ((PSTATS_CTRL(unit).stat_mode == 1) &&
   1226         (PSTATS_CTRL(unit).hw_cor_in_max_use_count == 1)) {
   1227         /* HW clear on read is enabled, no need do hw clear */
   1228         need_hw_clear = 0;
   1229     }
   1230 
   1231     if (need_hw_clear == 1) {
   1232         for (i = 0; i < cur_session->element_array_count; i++) {
   1233             element = cur_session->element_array[i];
   1234             BCM_IF_ERROR_RETURN(
   1235                 _bcm_th3_pstats_session_data_hw_clear(unit, element));
   1236         }
   1237     }
   1238 
   1239     /* clear SW use count buffer */
   1240     sal_memset(cur_session->data_array, 0,
   1241                cur_session->element_array_count * sizeof(bcm_pstats_data_t));
   1242 
   1243     return BCM_E_NONE;
   1244 }
   1245 
   1246 /*
   1247  * Function:
   1248  *      bcm_th3_pstats_session_traverse
   1249  * Purpose:
   1250  *      Traverse through the pstats sessions and run callback at each session.
   1251  * Parameters:
   1252  *      unit - (IN) StrataSwitch unit number.
   1253  *      cb - (IN) bcm_pstats_session_traverse_cb.
   1254  *      user_data - (IN) User data to be passed to callback function.
   1255  * Returns:
   1256  *      BCM_E_XXX
   1257  */
   1258 STATIC int
   1259 bcm_th3_pstats_session_traverse(int unit, bcm_pstats_session_traverse_cb cb,
   1260                                 void *user_data)
   1261 {
   1262     bcm_pstats_session_element_t    *element_array;
   1263     bcm_pstats_session_id_t         session_id;
   1264     pstats_session_t                *cur_session = NULL;
   1265     int                             array_count;
   1266     int                             rv = BCM_E_NONE;
   1267 
   1268     LOG_INFO(BSL_LS_BCM_PSTATS,
   1269              (BSL_META_U(unit, "pstats_session_travers unit %d\n"), unit));
   1270 
   1271     cur_session = PSTATS_CTRL(unit).first_session;
   1272     while (NULL != cur_session) {
   1273         session_id = cur_session->session_id;
   1274         array_count = cur_session->element_array_count;
   1275         element_array = (bcm_pstats_session_element_t *) sal_alloc(
   1276             sizeof(bcm_pstats_session_element_t) * array_count,
   1277                                                 "pstats session elements");
   1278         if (element_array == NULL) {
   1279             return BCM_E_MEMORY;
   1280         }
   1281 
   1282         sal_memcpy(element_array, cur_session->element_array,
   1283                    array_count * sizeof(bcm_pstats_session_element_t));
   1284 
   1285         cur_session = cur_session->next_session;
   1286 
   1287         rv = cb(unit, session_id, array_count, element_array, user_data);
   1288 #ifdef BCM_CB_ABORT_ON_ERR
   1289         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   1290             sal_free(element_array);
   1291             return rv;
   1292         }
   1293 #else
   1294         /*
   1295          * If CB_ABORT_ON_ERR is not defined don't return error
   1296          * and continue.
   1297          */
   1298         sal_free(element_array);
   1299         rv = BCM_E_NONE;
   1300 #endif
   1301     }
   1302 
   1303     return rv;
   1304 }
   1305 #else  /* INCLUDE_PSTATS && BCM_TOMAHAWK3_SUPPORT */
   1306 int bcm_esw_tomahawk3_pstats_not_empty;
   1307 #endif /* INCLUDE_PSTATS && BCM_TOMAHAWK3_SUPPORT */
   1308 
   1309 
   1310