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


      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_TRIDENT3_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/trident3.h>
     22 #include <soc/pstats.h>
     23 
     24 #include <bcm/error.h>
     25 #include <bcm/pstats.h>
     26 
     27 #include <bcm_int/esw/mbcm.h>
     28 #include <bcm_int/esw/tomahawk.h>
     29 #include <bcm_int/esw/trident3.h>
     30 
     31 #include <bcm_int/esw_dispatch.h>
     32 #include <bcm_int/esw/pstats.h>
     33 
     34 #ifdef BCM_WARM_BOOT_SUPPORT
     35 #include <bcm_int/esw/switch.h>
     36 #endif /* BCM_WARM_BOOT_SUPPORT */
     37 
     38 #define PSTATS_SESSION_MIN          1
     39 #define PSTATS_SESSION_MAX          256
     40 /* Max 1 XPEs and 2 PIPEs */
     41 #define TD3_MAX_XPEPIPE             _TD3_PIPES_PER_DEV * _TD3_XPES_PER_DEV
     42 
     43 #define TD3_MAX_POOL_COUNT          4
     44 #define TD3_MAX_UCQ_COUNT           1328
     45 
     46 /* Max Elements Count = UCQ + ING POOL + EGR POOL */
     47 #define TD3_MAX_ELEMENT_COUNT       TD3_MAX_UCQ_COUNT + TD3_MAX_POOL_COUNT * 2
     48 
     49 #define TD3_PORT_NUM_COS(unit, port)                            \
     50     ((IS_CPU_PORT(unit, port)) ? NUM_CPU_COSQ(unit) :           \
     51      (IS_LB_PORT(unit, port)) ? 10 : NUM_COS(unit))
     52 
     53 /*
     54  * Macro to get buffer index
     55  * Per XPE or PIPE instance (ING POOL & EGR POOL)
     56  * buffer_id = xpe or pipe
     57  *  ----------------------
     58  * | buffer |  pool id   |
     59  * |   0    |     0      |
     60  * |   1    |     1      | 
     61  * |   2    |     2      |
     62  * |   3    |     3      |
     63  *  ----------------------
     64  * Per XPE-PIPE instance (UCQ)
     65  * buffer_id = xpe * NUM_PIPE(unit) + pipe
     66  *  --------------------
     67  * | buffer | xpe | pipe |
     68  * |   0    |  0  |  0   |
     69  * |   1    |  0  |  1   |
     70  */
     71 #define TD3_XPE_PIPE_INDEX(unit, xpe, pipe)                     \
     72     (((xpe) == -1) ? (pipe) :                                   \
     73      ((pipe) == -1) ? (xpe) : (xpe) * NUM_PIPE(unit) + (pipe))
     74 
     75 #define TD3_XPE_VALID(unit, xpe, valid)                        \
     76     if (xpe >  NUM_XPE(unit)) {                                \
     77         valid = FALSE;                                         \
     78     }                                                          \
     79 
     80 
     81 typedef struct pstats_session_s {
     82     bcm_pstats_session_id_t         session_id;
     83 
     84     /* session buffer */
     85     bcm_pstats_timestamp_t          timestamp;
     86     bcm_pstats_data_t               *data_array;
     87 
     88     /* session element info */
     89     int                             element_array_count;
     90     bcm_pstats_session_element_t    element_array[TD3_MAX_ELEMENT_COUNT];
     91 
     92     uint32                          enable;
     93 
     94     /* prev session */
     95     struct pstats_session_s         *prev_session;
     96     /* next session */
     97     struct pstats_session_s         *next_session;
     98 } pstats_session_t;
     99 
    100 typedef struct pstats_buffer_s {
    101     soc_mem_t                       mem;
    102     soc_mem_t                       clear_mem;
    103     int                             min_idx;
    104     int                             max_idx;
    105     int                             num_entries;
    106     uint8                           *buf;
    107 } pstats_buffer_t;
    108 
    109 typedef struct pstats_control_s {
    110     /* full buffer */
    111 #ifdef BCM_PSTATS_MEASURE
    112     pstats_buffer_t                 local_time;
    113     pstats_buffer_t                 local_time_end;
    114 #endif
    115     pstats_buffer_t                 utc_time;
    116     pstats_buffer_t                 ucq_buffer[TD3_MAX_XPEPIPE];
    117     pstats_buffer_t                 ing_pool_buffer[TD3_MAX_POOL_COUNT];
    118     pstats_buffer_t                 egr_pool_buffer[TD3_MAX_POOL_COUNT];
    119 
    120     bcm_pstats_session_id_t         next_session_id;
    121     uint32                          session_count;
    122 #ifdef BCM_PSTATS_MEASURE
    123     uint64                          time_cost;
    124 #endif
    125     int                             stat_mode;
    126     int                             hw_cor_in_max_use_count;
    127     pstats_session_t                *first_session;
    128 } pstats_control_t;
    129 
    130 static soc_field_t                  ucq_field[4] = {UCQ_COUNT0f, UCQ_COUNT1f,
    131                                                     UCQ_COUNT2f, UCQ_COUNT3f};
    132 static soc_field_t                  isp_field[4] = {SP0f, SP1f, SP2f, SP3f};
    133 static soc_field_t                  esp_field[4] = {COUNT_0f, COUNT_1f,
    134                                                     COUNT_2f, COUNT_3f};
    135 
    136 static pstats_control_t             pstats_control[BCM_MAX_NUM_UNITS];
    137 #define PSTATS_CTRL(u)              pstats_control[u]
    138 
    139 STATIC int
    140 bcm_td3_pstats_session_create(int unit, int options, int array_count,
    141                               bcm_pstats_session_element_t  *element_array,
    142                               bcm_pstats_session_id_t *session_id);
    143 STATIC int
    144 bcm_td3_pstats_session_destroy(int unit, bcm_pstats_session_id_t session_id);
    145 STATIC int
    146 bcm_td3_pstats_session_get(int unit, bcm_pstats_session_id_t session_id,
    147                            int array_max,
    148                            bcm_pstats_session_element_t *element_array,
    149                            int *array_count);
    150 STATIC int bcm_td3_pstats_data_sync(int unit);
    151 STATIC int
    152 bcm_td3_pstats_session_data_get(int unit, bcm_pstats_session_id_t session_id,
    153                                 int sync,
    154                                 bcm_pstats_timestamp_t *timestamp,
    155                                 int array_max,
    156                                 bcm_pstats_data_t *data,
    157                                 int *array_count);
    158 STATIC int
    159 bcm_td3_pstats_session_data_clear(int unit, bcm_pstats_session_id_t session_id);
    160 
    161 STATIC int
    162 bcm_td3_pstats_session_traverse(int unit, bcm_pstats_session_traverse_cb cb,
    163                                 void *user_data);
    164 
    165 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
    166 /*
    167  * Function:
    168  *     bcm_td3_pstats_sw_dump
    169  * Purpose:
    170  *     Displays PSTATS information maintained by software.
    171  * Parameters:
    172  *     unit - Device unit number
    173  * Returns:
    174  *     None
    175  */
    176 STATIC void
    177 bcm_td3_pstats_sw_dump(int unit)
    178 {
    179     pstats_session_t *cur_session;
    180 
    181     LOG_CLI((BSL_META_U(unit,
    182                         "=========== \n")));
    183     LOG_CLI((BSL_META_U(unit, "Pstats mode: %s\n"),
    184                         PSTATS_CTRL(unit).stat_mode ?
    185                         "Max-use-count" : "Instantaneous"));
    186     LOG_CLI((BSL_META_U(unit, "Total pstats session count: %d\n"),
    187                         PSTATS_CTRL(unit).session_count));
    188     cur_session = PSTATS_CTRL(unit).first_session;
    189     while (NULL != cur_session) {
    190         LOG_CLI((BSL_META_U(unit,
    191                             "Pstats session id: %d element count: %d\n"),
    192                             cur_session->session_id,
    193                             cur_session->element_array_count));
    194         cur_session = cur_session->next_session;
    195     }
    196     LOG_CLI((BSL_META_U(unit,
    197                         "=========== \n")));
    198     return;
    199 }
    200 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
    201 
    202 STATIC void
    203 _bcm_td3_pstats_session_cleanup(int unit, pstats_session_t *session)
    204 {
    205     session->enable = FALSE;
    206     if (NULL != session->data_array) {
    207         sal_free(session->data_array);
    208     }
    209 
    210     sal_memset(session, 0, sizeof(pstats_session_t));
    211 
    212     return;
    213 }
    214 
    215 STATIC pstats_session_t*
    216 _bcm_td3_pstats_session_get(int unit, bcm_pstats_session_id_t session_id)
    217 {
    218     int                 found = 0;
    219     pstats_session_t   *cur_session;
    220 
    221     cur_session = PSTATS_CTRL(unit).first_session;
    222     while (NULL != cur_session) {
    223         if (cur_session->session_id == session_id) {
    224             found = 1;
    225             break;
    226         }
    227         cur_session = cur_session->next_session;
    228     }
    229 
    230     if (found) {
    231         return cur_session;
    232     }
    233 
    234     return NULL;
    235 }
    236 
    237 /* Set a minimum available session id */
    238 STATIC void
    239 _bcm_td3_pstats_session_next_id_set(int unit)
    240 {
    241     pstats_session_t            *cur_session;
    242     bcm_pstats_session_id_t     id = PSTATS_SESSION_MIN;
    243 
    244     cur_session = PSTATS_CTRL(unit).first_session;
    245     while (NULL != cur_session) {
    246         if (id < cur_session->session_id) {
    247             break;
    248         } else if (id == cur_session->session_id) {
    249             /* this id already existed */
    250             id++;
    251         }
    252         cur_session = cur_session->next_session;
    253     }
    254 
    255     PSTATS_CTRL(unit).next_session_id = id;
    256 
    257     LOG_INFO(BSL_LS_BCM_PSTATS, (BSL_META_U(unit, "next %d\n"), id));
    258 }
    259 
    260 STATIC int
    261 _bcm_td3_pstats_session_delete(int unit, bcm_pstats_session_id_t session_id)
    262 {
    263     pstats_session_t            *cur_session;
    264 
    265     cur_session = _bcm_td3_pstats_session_get(unit, session_id);
    266     if (NULL == cur_session) {
    267         LOG_INFO(BSL_LS_BCM_PSTATS,
    268             (BSL_META_U(unit, "pstats session %d not found\n"), session_id));
    269         return BCM_E_NOT_FOUND;
    270     }
    271     /* update session link */
    272     if ((NULL == cur_session->prev_session) &&
    273         (NULL == cur_session->next_session)) {
    274         /* only one session */
    275         PSTATS_CTRL(unit).first_session = NULL;
    276     } else if (NULL == cur_session->prev_session) {
    277         /* first session */
    278         PSTATS_CTRL(unit).first_session = cur_session->next_session;
    279         cur_session->next_session->prev_session = NULL;
    280     } else if (NULL == cur_session->next_session) {
    281         /* last session */
    282         cur_session->prev_session->next_session = NULL;
    283     } else {
    284         cur_session->prev_session->next_session = cur_session->next_session;
    285         cur_session->next_session->prev_session = cur_session->prev_session;
    286     }
    287     _bcm_td3_pstats_session_cleanup(unit, cur_session);
    288     if (NULL != cur_session) {
    289         sal_free(cur_session);
    290     }
    291     PSTATS_CTRL(unit).session_count--;
    292 
    293     _bcm_td3_pstats_session_next_id_set(unit);
    294 
    295     return BCM_E_NONE;
    296 }
    297 
    298 STATIC void
    299 _bcm_td3_pstats_session_insert(int unit, pstats_session_t *session)
    300 {
    301     pstats_session_t            *cur_session;
    302     bcm_pstats_session_id_t     id = session->session_id;
    303 
    304     cur_session = PSTATS_CTRL(unit).first_session;
    305     if (NULL == cur_session) {
    306         /* first session */
    307         PSTATS_CTRL(unit).first_session = session;
    308         session->prev_session = NULL;
    309         session->next_session = NULL;
    310     }
    311     while (NULL != cur_session) {
    312         if (id > cur_session->session_id) {
    313             /* last session */
    314             if (NULL == cur_session->next_session) {
    315                 cur_session->next_session = session;
    316                 session->prev_session = cur_session;
    317                 session->next_session = NULL;
    318                 break;
    319             } else {
    320                 cur_session = cur_session->next_session;
    321             }
    322         } else {
    323             /* first session */
    324             if (NULL == cur_session->prev_session) {
    325                 PSTATS_CTRL(unit).first_session = session;
    326                 session->prev_session = NULL;
    327                 session->next_session = cur_session;
    328                 cur_session->prev_session = session;
    329                 break;
    330             } else {
    331                 session->prev_session = cur_session->prev_session;
    332                 session->next_session = cur_session;
    333                 cur_session->prev_session->next_session = session;
    334                 cur_session->prev_session = session;
    335                 break;
    336             }
    337             break;
    338         }
    339     }
    340     PSTATS_CTRL(unit).session_count++;
    341 
    342     session->enable = TRUE;
    343 
    344     return;
    345 }
    346 
    347 STATIC void
    348 _bcm_td3_pstats_buffer_deinit(int unit, pstats_buffer_t *pbuf)
    349 {
    350     if (NULL == pbuf) {
    351         return;
    352     }
    353 
    354     if (NULL != pbuf->buf) {
    355         sal_free(pbuf->buf);
    356     }
    357     sal_memset(pbuf, 0, sizeof(pstats_buffer_t));
    358 
    359     return;
    360 }
    361 
    362 STATIC int
    363 _bcm_td3_pstats_buffer_init(int unit, soc_mem_t mem, soc_mem_t clear_mem,
    364                             pstats_buffer_t *pbuf)
    365 {
    366     int alloc_size;
    367 
    368     if (NULL == pbuf) {
    369         return BCM_E_PARAM;
    370     }
    371 
    372     if (NULL != pbuf->buf) {
    373         return BCM_E_PARAM;
    374     }
    375 
    376     pbuf->mem = mem;
    377     pbuf->clear_mem = clear_mem;
    378     pbuf->min_idx = soc_mem_index_min(unit, mem);
    379     pbuf->max_idx = soc_mem_index_max(unit, mem);
    380     pbuf->num_entries = soc_mem_index_max(unit, mem) + 1;
    381     alloc_size = sizeof(uint32) * soc_mem_entry_words(unit, mem);
    382     alloc_size *= pbuf->num_entries;
    383 
    384     pbuf->buf = sal_alloc(alloc_size, "pstats buffer");
    385     if (pbuf->buf == NULL) {
    386         return BCM_E_MEMORY;
    387     }
    388     sal_memset(pbuf->buf, 0, alloc_size);
    389 
    390     return BCM_E_NONE;
    391 }
    392 
    393 /*
    394  * Function:
    395  *      bcm_td3_pstats_deinit
    396  * Purpose:
    397  *      Deinitialize PSTATS driver functions
    398  *      for Trident3 (BCM56870).
    399  * Parameters:
    400  *      unit - (IN) StrataSwitch unit number.
    401  * Returns:
    402  *      BCM_E_XXX
    403  */
    404 void
    405 bcm_td3_pstats_deinit(int unit)
    406 {
    407     pstats_session_t *cur_session, *next_session;
    408     int i;
    409 
    410     soc_pstats_deinit(unit);
    411 
    412 #ifdef BCM_PSTATS_MEASURE
    413     _bcm_td3_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).local_time);
    414     _bcm_td3_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).local_time_end);
    415 #endif
    416     _bcm_td3_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).utc_time);
    417     for (i = 0; i < TD3_MAX_XPEPIPE; i++) {
    418         _bcm_td3_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).ucq_buffer[i]);
    419     }
    420     for (i = 0; i < TD3_MAX_POOL_COUNT; i++) {
    421         _bcm_td3_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).ing_pool_buffer[i]);
    422         _bcm_td3_pstats_buffer_deinit(unit, &PSTATS_CTRL(unit).egr_pool_buffer[i]);
    423     }
    424 
    425     cur_session = PSTATS_CTRL(unit).first_session;
    426     while (NULL != cur_session) {
    427         next_session = cur_session->next_session;
    428         _bcm_td3_pstats_session_cleanup(unit, cur_session);
    429         if (NULL != cur_session) {
    430             sal_free(cur_session);
    431         }
    432         PSTATS_CTRL(unit).session_count--;
    433         cur_session = next_session;
    434     }
    435 
    436     if (PSTATS_CTRL(unit).session_count != 0) {
    437         /* debug info */
    438     }
    439     sal_memset(&PSTATS_CTRL(unit), 0, sizeof(pstats_control_t));
    440 
    441     return;
    442 }
    443 
    444 
    445 /*
    446  * Function:
    447  *      bcm_td3_pstats_init
    448  * Purpose:
    449  *      Initialize PSTATS driver functions
    450  *      for Trident3 (BCM56970).
    451  * Parameters:
    452  *      unit - (IN) StrataSwitch unit number.
    453  * Returns:
    454  *      BCM_E_XXX
    455  */
    456 int
    457 bcm_td3_pstats_init(int unit)
    458 {
    459     _bcm_pstats_unit_driver_t   *pstats_driver;
    460     pstats_buffer_t             *pbuf;
    461     int                         rv = BCM_E_NONE;
    462     soc_mem_t                   mem, clear_mem, base_mem;
    463     int                         index, pipe, xpe;
    464     uint32                      flag;
    465 
    466     if (2 != soc_property_get(unit, spn_BUFFER_STATS_COLLECT_TYPE, 1)) {
    467         LOG_INFO(BSL_LS_BCM_PSTATS,
    468             (BSL_META_U(unit, "current mode is not pstats, no need init\n")));
    469         return BCM_E_NONE;
    470     }
    471 
    472     pstats_driver = _BCM_PSTATS_UNIT_DRIVER(unit);
    473     if (pstats_driver == NULL) {
    474         return BCM_E_MEMORY;
    475     }
    476 
    477     /* Initializing Driver functions for PSTATS */
    478     pstats_driver->session_create = bcm_td3_pstats_session_create;
    479     pstats_driver->session_destroy = bcm_td3_pstats_session_destroy;
    480     pstats_driver->session_get = bcm_td3_pstats_session_get;
    481     pstats_driver->data_sync = bcm_td3_pstats_data_sync;
    482     pstats_driver->session_data_get = bcm_td3_pstats_session_data_get;
    483     pstats_driver->session_data_clear = bcm_td3_pstats_session_data_clear;
    484     pstats_driver->session_traverse = bcm_td3_pstats_session_traverse;
    485 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
    486     pstats_driver->pstats_sw_dump = bcm_td3_pstats_sw_dump;
    487 #endif
    488 
    489     /* alloc buffer for full pstats table */
    490 #ifdef BCM_PSTATS_MEASURE
    491     /* local time */
    492     mem = MMU_INTFO_TIMESTAMPm;
    493     pbuf = &PSTATS_CTRL(unit).local_time;
    494     rv = _bcm_td3_pstats_buffer_init(unit, mem, mem, pbuf);
    495     if (BCM_FAILURE(rv)) {
    496         goto cleanup;
    497     }
    498     mem = MMU_INTFO_TIMESTAMPm;
    499     pbuf = &PSTATS_CTRL(unit).local_time_end;
    500     rv = _bcm_td3_pstats_buffer_init(unit, mem, mem, pbuf);
    501     if (BCM_FAILURE(rv)) {
    502         goto cleanup;
    503     }
    504 #endif
    505 
    506     /* utc time */
    507     mem = MMU_INTFO_UTC_TIMESTAMPm;
    508     pbuf = &PSTATS_CTRL(unit).utc_time;
    509     rv = _bcm_td3_pstats_buffer_init(unit, mem, mem, pbuf);
    510     if (BCM_FAILURE(rv)) {
    511         goto cleanup;
    512     }
    513 
    514     /* ucq buffer */
    515     base_mem = MMU_THDU_UCQ_STATS_TABLEm;
    516     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
    517         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
    518             mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe);
    519             clear_mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, MMU_THDU_UCQ_STATSm,
    520                                                     xpe, pipe);
    521             if (mem == INVALIDm) {
    522                 continue;
    523             }
    524 
    525             index = TD3_XPE_PIPE_INDEX(unit, xpe, pipe);
    526             if (index >= TD3_MAX_XPEPIPE) {
    527                 rv = BCM_E_INTERNAL;
    528                 goto cleanup;
    529             }
    530             pbuf = &PSTATS_CTRL(unit).ucq_buffer[index];
    531 
    532             rv = _bcm_td3_pstats_buffer_init(unit, mem, clear_mem, pbuf);
    533             if (BCM_FAILURE(rv)) {
    534                 goto cleanup;
    535             }
    536         }
    537     } /* ucq buffer */
    538 
    539     /* ing pool buffer */
    540     base_mem = THDI_PKT_STAT_SP_SHARED_COUNTm;
    541     for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
    542         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[xpe];
    543         if (mem == INVALIDm) {
    544             continue;
    545         }
    546 
    547         index = TD3_XPE_PIPE_INDEX(unit, xpe, -1);
    548         if (index >= TD3_MAX_POOL_COUNT) {
    549             rv = BCM_E_INTERNAL;
    550             goto cleanup;
    551         }
    552 
    553         pbuf = &PSTATS_CTRL(unit).ing_pool_buffer[index];
    554 
    555         rv = _bcm_td3_pstats_buffer_init(unit, mem, mem, pbuf);
    556         if (BCM_FAILURE(rv)) {
    557             goto cleanup;
    558         }
    559     } /* ing pool buffer */
    560 
    561     /* egr pool buffer */
    562     base_mem = MMU_THDM_DB_POOL_MCUC_PKSTATm;
    563     for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 
    564         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[xpe];
    565         if (mem == INVALIDm) {
    566             continue;
    567         }
    568 
    569         index = TD3_XPE_PIPE_INDEX(unit, xpe, -1);
    570         if (index >= TD3_MAX_POOL_COUNT) {
    571             rv = BCM_E_INTERNAL;
    572             goto cleanup;
    573         }
    574 
    575         pbuf = &PSTATS_CTRL(unit).egr_pool_buffer[index];
    576 
    577         rv = _bcm_td3_pstats_buffer_init(unit, mem, mem, pbuf);
    578         if (BCM_FAILURE(rv)) {
    579             goto cleanup;
    580         }
    581     } /* egr pool buffer */
    582 
    583     PSTATS_CTRL(unit).next_session_id = PSTATS_SESSION_MIN;
    584 
    585     rv = soc_pstats_init(unit);
    586     if (BCM_FAILURE(rv)) {
    587         LOG_INFO(BSL_LS_SOC_COMMON,
    588             (BSL_META_U(unit, "soc_pstats_init failed rv = %d\n"), rv));
    589         goto cleanup;
    590     }
    591 
    592 #ifdef BCM_WARM_BOOT_SUPPORT
    593     if (SOC_WARM_BOOT(unit)) {
    594         int config;
    595 
    596         /* get pstats config from HW */
    597         rv = soc_trident3_mmu_pstats_mode_get(unit, &flag);
    598         if (BCM_FAILURE(rv)) {
    599             goto cleanup;
    600         }
    601 
    602         /* HW config is different with config property */
    603         if (!(flag & _TD3_MMU_PSTATS_ENABLE) ||
    604             !(flag & _TD3_MMU_PSTATS_PKT_MOD)) {
    605             LOG_ERROR(BSL_LS_SOC_COMMON,
    606                       (BSL_META_U(unit,
    607                                   "WARMBOOT ERROR.\n"
    608                                   "Current buffer stats mode is not pstats.\n")));
    609             rv = BCM_E_INIT;
    610             goto cleanup;
    611         }
    612 
    613         if (flag & _TD3_MMU_PSTATS_HWM_MOD) {
    614             PSTATS_CTRL(unit).stat_mode = 1;
    615             if (flag & _TD3_MMU_PSTATS_RESET_ON_READ) {
    616                 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 1;
    617             } else {
    618                 PSTATS_CTRL(unit).hw_cor_in_max_use_count = 0;
    619             }
    620         } else {
    621             PSTATS_CTRL(unit).stat_mode = 0;
    622             PSTATS_CTRL(unit).hw_cor_in_max_use_count = 0;
    623         }
    624 
    625         config = soc_property_get(unit, spn_BUFFER_STATS_COLLECT_MODE, 0);
    626         if (config != PSTATS_CTRL(unit).stat_mode) {
    627             LOG_WARN(BSL_LS_SOC_COMMON,
    628                      (BSL_META_U(unit,
    629                                  "WARMBOOT WARNING.\n"
    630                                  "Config mode %d. HW mode %d.\n"),
    631                                  config, PSTATS_CTRL(unit).stat_mode));
    632         }
    633 
    634         flag |= _TD3_MMU_PSTATS_SYNC | _TD3_MMU_PSTATS_MOR_EN;
    635 
    636         /* Reset pstats mode in warmboot */
    637         rv = soc_trident3_mmu_pstats_mode_set(unit, flag);
    638         if (BCM_FAILURE(rv)) {
    639             goto cleanup;
    640         }
    641     } else
    642 #endif
    643     {
    644         PSTATS_CTRL(unit).stat_mode =
    645                 soc_property_get(unit, spn_BUFFER_STATS_COLLECT_MODE, 0);
    646         if ((PSTATS_CTRL(unit).stat_mode == 1) &&
    647             soc_property_get(unit, "oob_pstats_hw_cor_en", 1)) {
    648             PSTATS_CTRL(unit).hw_cor_in_max_use_count = 1;
    649         }
    650 
    651         /* call soc function */
    652         flag = _TD3_MMU_PSTATS_ENABLE |
    653                _TD3_MMU_PSTATS_PKT_MOD |
    654                _TD3_MMU_PSTATS_SYNC |
    655                _TD3_MMU_PSTATS_MOR_EN;
    656 
    657 
    658         if (PSTATS_CTRL(unit).stat_mode) {
    659             flag |= _TD3_MMU_PSTATS_HWM_MOD;
    660             if (PSTATS_CTRL(unit).hw_cor_in_max_use_count == 1) {
    661                 flag |= _TD3_MMU_PSTATS_RESET_ON_READ;
    662             }
    663         }
    664 
    665         rv = soc_trident3_mmu_pstats_mode_set(unit, flag);
    666         if (BCM_FAILURE(rv)) {
    667             goto cleanup;
    668         }
    669     }
    670 
    671     return BCM_E_NONE;
    672 
    673 cleanup:
    674     soc_pstats_deinit(unit);
    675     (void )bcm_td3_pstats_deinit(unit);
    676 
    677     return rv;
    678 }
    679 
    680 STATIC int
    681 _bcm_td3_pstats_session_element_check(int unit,
    682                                        bcm_pstats_session_element_t element)
    683 {
    684     bcm_gport_t                 gport;
    685     bcm_port_t                  local_port;
    686     bcm_cos_queue_t             cosq;
    687 
    688     LOG_INFO(BSL_LS_BCM_PSTATS,
    689         (BSL_META_U(unit, "pstats_session_element_check unit %d\n"), unit));
    690 
    691     if (element.type == bcmPStatsSessionUnicastQueue) {
    692         gport = element.gport;
    693         cosq = element.cosq;
    694         if (BCM_GPORT_IS_SET(gport)) {
    695             if (BCM_GPORT_IS_LOCAL(gport)) {
    696                 local_port = BCM_GPORT_LOCAL_GET(gport);
    697             } else if (BCM_GPORT_IS_MODPORT(gport)) {
    698                 BCM_IF_ERROR_RETURN(
    699                     bcm_esw_port_local_get(unit, gport, &local_port));
    700             } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    701                 return BCM_E_NONE;
    702             } else {
    703                 LOG_INFO(BSL_LS_BCM_PSTATS,
    704                     (BSL_META_U(unit, "pstats_session_element_check: "
    705                                 "gport 0x%x is illegal!\n"), gport));
    706                 return BCM_E_PARAM;
    707             }
    708         } else {
    709             local_port = gport;
    710         }
    711 
    712         if (!SOC_PORT_VALID(unit, local_port) || IS_CPU_PORT(unit, local_port)) {
    713             LOG_INFO(BSL_LS_BCM_PSTATS,
    714                 (BSL_META_U(unit, "pstats_session_element_check: "
    715                             "gport 0x%x is illegal!\n"), gport));
    716             return BCM_E_PORT;
    717         }
    718         /* cosq check when gport is a port gport */
    719         if ((cosq < 0) || (cosq >= TD3_PORT_NUM_COS(unit, local_port))) {
    720             LOG_INFO(BSL_LS_BCM_PSTATS,
    721                 (BSL_META_U(unit, "pstats_session_element_check: "
    722                             "cosq %d is illegal!\n"), cosq));
    723             return BCM_E_PARAM;
    724         }
    725     } else if ((element.type == bcmPStatsSessionIngPool) ||
    726                (element.type == bcmPStatsSessionEgrPool)) {
    727         if ((element.pool < 0) || (element.pool >= TD3_MAX_POOL_COUNT)) {
    728             LOG_INFO(BSL_LS_BCM_PSTATS,
    729                 (BSL_META_U(unit, "pstats_session_element_check: "
    730                             "pool_id %d is illegal!\n"), element.pool));
    731             return BCM_E_PARAM;
    732         }
    733     } else {
    734         LOG_INFO(BSL_LS_BCM_PSTATS,
    735             (BSL_META_U(unit, "pstats_session_element_check: "
    736                         "unknow element type %d\n"), element.type));
    737         return BCM_E_PARAM;
    738     }
    739 
    740     return BCM_E_NONE;
    741 }
    742 
    743 
    744 /*
    745  * Function:
    746  *      bcm_td3_pstats_session_create
    747  * Purpose:
    748  *      Create a PKT STAT session instance for SDK management.
    749  * Parameters:
    750  *      unit - (IN) StrataSwitch unit number.
    751  *      options - (IN) BCM_PSTATS_REPLACE: replace existing.
    752  *                     BCM_PSTATS_WITH_ID: session_id argument is given.
    753  *      array_count - (IN) Number of elements in array.
    754  *      element_array - (IN) PSTATS session element array.
    755  *      session_id - (INOUT) id of a PSTATS session created via this API.
    756  * Returns:
    757  *      BCM_E_XXX
    758  */
    759 STATIC int
    760 bcm_td3_pstats_session_create(int unit, int options, int array_count,
    761                               bcm_pstats_session_element_t  *element_array,
    762                               bcm_pstats_session_id_t *session_id)
    763 {
    764     int                         rv, i, alloc_size;
    765     bcm_pstats_session_id_t     id = 0;
    766     pstats_session_t            *cur_session = NULL;
    767 
    768     LOG_INFO(BSL_LS_BCM_PSTATS,
    769         (BSL_META_U(unit, "pstats_session_create unit %d options %d "
    770                     "array_count %d\n"), unit, options, array_count));
    771 
    772     /* element check */
    773     if ((array_count < 0) ||
    774         (array_count > TD3_MAX_ELEMENT_COUNT)) {
    775         LOG_ERROR(BSL_LS_BCM_PSTATS,
    776             (BSL_META_U(unit, "array_count %d is illegal!\n"), array_count));
    777         return BCM_E_PARAM;
    778     }
    779     if (NULL == element_array) {
    780         LOG_ERROR(BSL_LS_BCM_PSTATS,
    781             (BSL_META_U(unit, "element_array is null\n")));
    782         return BCM_E_PARAM;
    783     }
    784 
    785     for (i = 0; i < array_count; i++) {
    786         BCM_IF_ERROR_RETURN(
    787                 _bcm_td3_pstats_session_element_check(unit, element_array[i]));
    788     }
    789 
    790     if (options & BCM_PSTATS_OPTIONS_REPLACE) {
    791         /* delete original session first */
    792         id = *session_id;
    793         BCM_IF_ERROR_RETURN(_bcm_td3_pstats_session_delete(unit, id));
    794     } else if (options & BCM_PSTATS_OPTIONS_WITH_ID) {
    795         id = *session_id;
    796         if (id < PSTATS_SESSION_MIN) {
    797             LOG_ERROR(BSL_LS_BCM_PSTATS,
    798                 (BSL_META_U(unit, "input session_id %d is illegal!\n"), id));
    799             return BCM_E_PARAM;
    800         }
    801         cur_session = _bcm_td3_pstats_session_get(unit, id);
    802         if (NULL != cur_session) {
    803             LOG_INFO(BSL_LS_BCM_PSTATS,
    804                 (BSL_META_U(unit, "pstats_session_create: "
    805                             "session_id %d is existed\n"), id));
    806             return BCM_E_EXISTS;
    807         }
    808     } else {
    809         id = PSTATS_CTRL(unit).next_session_id;
    810     }
    811 
    812     /* SDK has a limitation of maxium session count */
    813     if (PSTATS_CTRL(unit).session_count >= PSTATS_SESSION_MAX) {
    814         LOG_INFO(BSL_LS_BCM_PSTATS,
    815             (BSL_META_U(unit, "pstats_session_create: "
    816                         "session count is full\n")));
    817         return BCM_E_FULL;
    818     }
    819 
    820     cur_session =
    821         (pstats_session_t*) sal_alloc(sizeof(pstats_session_t),
    822                                       "pstats session");
    823     if (NULL == cur_session) {
    824         return BCM_E_MEMORY;
    825     }
    826     sal_memset(cur_session, 0, sizeof(pstats_session_t));
    827 
    828     /* record session info */
    829     cur_session->session_id = id;
    830     cur_session->element_array_count = array_count;
    831     sal_memcpy(cur_session->element_array,
    832                element_array,
    833                array_count * sizeof(bcm_pstats_session_element_t));
    834 
    835     alloc_size = array_count * sizeof(bcm_pstats_data_t);
    836     cur_session->data_array = sal_alloc(alloc_size, "data array");
    837     if (NULL == cur_session->data_array) {
    838         rv = BCM_E_MEMORY;
    839         goto cleanup;
    840     }
    841     sal_memset(cur_session->data_array, 0, alloc_size);
    842 
    843     _bcm_td3_pstats_session_insert(unit, cur_session);
    844     _bcm_td3_pstats_session_next_id_set(unit);
    845 
    846     *session_id = id;
    847     return BCM_E_NONE;
    848 cleanup:
    849     _bcm_td3_pstats_session_cleanup(unit, cur_session);
    850     if (NULL != cur_session) {
    851         sal_free(cur_session);
    852     }
    853     return rv;
    854 }
    855 
    856 /*
    857  * Function:
    858  *      bcm_td3_pstats_session_destroy
    859  * Purpose:
    860  *      Destroy an existing PSTATS session.
    861  * Parameters:
    862  *      unit - (IN) StrataSwitch unit number.
    863  *      session_id - (IN) id of a PSTATS session created via the
    864  *                        bcm_pkt==stats_session_create
    865  * Returns:
    866  *      BCM_E_XXX
    867  */
    868 STATIC int
    869 bcm_td3_pstats_session_destroy(int unit,
    870                                bcm_pstats_session_id_t session_id)
    871 {
    872     return _bcm_td3_pstats_session_delete(unit, session_id);
    873 }
    874 
    875 /*
    876  * Function:
    877  *      bcm_td3_pstats_session_get
    878  * Purpose:
    879  *      Get an existing PSTATS session info.
    880  * Parameters:
    881  *      unit - (IN) StrataSwitch unit number.
    882  *      session_id - (IN) id of a PSTATS session created via the
    883  *                        bcm_pstats_session_create
    884  *      array_max - (IN) Maximum number of elements in array.
    885  *      element_array - (OUT) element array of a PSTATS session.
    886  *      array_count - (OUT) Number of elements in array.
    887  * Returns:
    888  *      BCM_E_XXX
    889  */
    890 STATIC int
    891 bcm_td3_pstats_session_get(int unit,
    892                            bcm_pstats_session_id_t session_id,
    893                            int array_max,
    894                            bcm_pstats_session_element_t *element_array,
    895                            int *array_count)
    896 {
    897     pstats_session_t *cur_session = NULL;
    898 
    899     LOG_INFO(BSL_LS_BCM_PSTATS,
    900         (BSL_META_U(unit, "pstats_session_get unit %d session_id %d\n"),
    901                     unit, session_id));
    902 
    903     if (NULL == element_array) {
    904         LOG_ERROR(BSL_LS_BCM_PSTATS,
    905             (BSL_META_U(unit, "element_array is null\n")));
    906         return BCM_E_PARAM;
    907     }
    908 
    909     cur_session = _bcm_td3_pstats_session_get(unit, session_id);
    910     if (NULL == cur_session) {
    911         LOG_INFO(BSL_LS_BCM_PSTATS,
    912             (BSL_META_U(unit, "pstats session %d not found\n"), session_id));
    913         return BCM_E_NOT_FOUND;
    914     }
    915 
    916     if (array_max >= cur_session->element_array_count) {
    917         *array_count = cur_session->element_array_count;
    918     } else if (array_max >= 0) {
    919         *array_count = array_max;
    920     } else {
    921         return BCM_E_PARAM;
    922     }
    923 
    924     sal_memcpy(element_array,
    925                cur_session->element_array,
    926                *array_count * sizeof(bcm_pstats_session_element_t));
    927 
    928     return BCM_E_NONE;
    929 }
    930 
    931 STATIC int
    932 _bcm_td3_pstats_session_data_update(int unit,
    933                                     bcm_pstats_session_element_t element,
    934                                     bcm_pstats_data_t *data)
    935 {
    936     bcm_gport_t                 gport;
    937     bcm_port_t                  local_port;
    938     bcm_cos_queue_t             cosq;
    939     bcm_service_pool_id_t       pool;
    940     int                         index, pen_idx = 0;
    941     int                         mode, i, xpe, pipe, startq, offset;
    942     uint8                       *total_buf;
    943     uint32                      cur_val = 0, *pre_p;
    944     void                        *pentry;
    945     soc_info_t                  *si = &SOC_INFO(unit);
    946     soc_mem_t                   mem;
    947     soc_field_t                 field;
    948 
    949     mode = PSTATS_CTRL(unit).stat_mode;
    950 
    951     if (element.type == bcmPStatsSessionUnicastQueue) {
    952         /* update ucq use counts
    953          * ucq_buf:
    954          * 0-1 each XPE has two pipes */
    955         gport = element.gport;
    956         cosq = element.cosq;
    957         BCM_IF_ERROR_RETURN(
    958             _bcm_td3_cosq_index_resolve(unit, gport, cosq,
    959                                        _BCM_TD3_COSQ_INDEX_STYLE_UCAST_QUEUE,
    960                                        &local_port, &startq, NULL));
    961         pipe = si->port_pipe[local_port];
    962 
    963         for (xpe = 0, i = 0; xpe < NUM_XPE(unit); xpe++) {
    964 
    965             if(!((si->epipe_xpe_map[pipe] >> xpe) & 1)) {
    966                 continue;
    967             }
    968             index = TD3_XPE_PIPE_INDEX(unit, xpe, pipe);
    969             if (index >= TD3_MAX_XPEPIPE) {
    970                 return BCM_E_INTERNAL;
    971             }
    972             total_buf = PSTATS_CTRL(unit).ucq_buffer[index].buf;
    973             mem = PSTATS_CTRL(unit).ucq_buffer[index].mem;
    974             /* In TD3, due to physical bank is 332 deep, when read out
    975              * index='d82, it will read out 2 valid counter at location 'd328
    976              * and 'd329, plus 2 invalid counter at location 'd330 and 'd331 */
    977             if (startq >= 330) {
    978                 startq += 2;
    979             }
    980             pen_idx = startq / 4;
    981             offset = startq % 4;
    982             pentry = soc_mem_table_idx_to_pointer(unit, mem, void*,
    983                                                   total_buf, pen_idx);
    984             cur_val = soc_mem_field32_get(unit, mem, pentry, ucq_field[offset]);
    985 
    986             pre_p = &data->use_counts_array[i];
    987             if (mode) {
    988                 if (cur_val > *pre_p) {
    989                     *pre_p = cur_val;
    990                 }
    991             } else {
    992                 *pre_p = cur_val;
    993             }
    994             i++;
    995         }
    996         data->array_count = i;
    997     } else {
    998         /* update pool use counts
    999          * pool_buf:
   1000          * xpe0-p0
   1001          */
   1002         pool = element.pool;
   1003         for (xpe = 0, i = 0; xpe < NUM_XPE(unit); xpe++) {
   1004             index = TD3_XPE_PIPE_INDEX(unit, xpe, -1);
   1005             if (index >= TD3_MAX_POOL_COUNT) {
   1006                 return BCM_E_INTERNAL;
   1007             }
   1008 
   1009             if (element.type == bcmPStatsSessionIngPool) {
   1010                 total_buf = PSTATS_CTRL(unit).ing_pool_buffer[xpe].buf;
   1011                 mem = PSTATS_CTRL(unit).ing_pool_buffer[xpe].mem;
   1012                 field = isp_field[pool];
   1013             } else if (element.type == bcmPStatsSessionEgrPool) {
   1014                 total_buf = PSTATS_CTRL(unit).egr_pool_buffer[xpe].buf;
   1015                 mem = PSTATS_CTRL(unit).egr_pool_buffer[xpe].mem;
   1016                 field = esp_field[pool];
   1017             } else {
   1018                 return BCM_E_INTERNAL;
   1019             }
   1020 
   1021             pentry = soc_mem_table_idx_to_pointer(unit, mem, void*,
   1022                                                   total_buf, pen_idx);
   1023             cur_val = soc_mem_field32_get(unit, mem, pentry, field);
   1024             pre_p = &data->use_counts_array[i];
   1025             if (mode) {
   1026                 if (cur_val > *pre_p) {
   1027                     *pre_p = cur_val;
   1028                 }
   1029             } else {
   1030                 *pre_p = cur_val;
   1031             }
   1032             i++;
   1033         }
   1034         data->array_count = i;
   1035     }
   1036 
   1037     return BCM_E_NONE;
   1038 }
   1039 
   1040 STATIC int
   1041 _bcm_td3_pstats_session_update(int unit, pstats_session_t *session)
   1042 {
   1043     bcm_pstats_session_element_t    element;
   1044     bcm_pstats_data_t               *data;
   1045     pstats_session_t                *cur_session = session;
   1046     uint8                           *total_buf;
   1047     int                             i;
   1048     void                            *pentry;
   1049     soc_mem_t                       mem;
   1050 
   1051     /* update timestamp
   1052      * if MMU_INTFO_TOD_TIMESTAMP is updated by ARM core,
   1053      * MMU_INTFO_UTC_TIMESTAMP is a utc time.
   1054      * otherwise it is a local time.
   1055      */
   1056     total_buf = PSTATS_CTRL(unit).utc_time.buf;
   1057     mem = PSTATS_CTRL(unit).utc_time.mem;
   1058     pentry = soc_mem_table_idx_to_pointer(unit, mem, void*, total_buf, 0);
   1059     cur_session->timestamp.nanoseconds =
   1060             soc_mem_field32_get(unit, mem, pentry, UTC_TIMESTAMP_NSECf);
   1061     soc_mem_field64_get(unit, mem, pentry, UTC_TIMESTAMP_SECf,
   1062                         &cur_session->timestamp.seconds);
   1063 
   1064 #ifdef BCM_PSTATS_MEASURE
   1065     if (soc_property_get(unit, "pstats_timestamp_info", 0) == 1) {
   1066         COMPILER_64_TO_32_LO(cur_session->timestamp.nanoseconds,
   1067                              PSTATS_CTRL(unit).time_cost);
   1068     }
   1069 #endif
   1070 
   1071     /* update element data */
   1072     for (i = 0; i < cur_session->element_array_count; i++) {
   1073         element = cur_session->element_array[i];
   1074         data = &cur_session->data_array[i];
   1075         BCM_IF_ERROR_RETURN(
   1076             _bcm_td3_pstats_session_data_update(unit, element, data));
   1077     }
   1078 
   1079     return BCM_E_NONE;
   1080 }
   1081 
   1082 /*
   1083  * Function:
   1084  *      _bcm_td3_pstats_hw_sync
   1085  * Purpose:
   1086  *      Start a pstats sync operation.
   1087  * Parameters:
   1088  *      unit - (IN) StrataSwitch unit number
   1089  * Returns:
   1090  *      BCM_E_XXX
   1091  */
   1092 STATIC int
   1093 _bcm_td3_pstats_hw_sync(int unit)
   1094 {
   1095     pstats_buffer_t             *pbuf;
   1096     int                         index, pipe, xpe;
   1097     soc_info_t                  *si = &SOC_INFO(unit);
   1098 #ifdef BCM_PSTATS_MEASURE
   1099     void                        *pentry;
   1100     uint64                      start_ts, end_ts;
   1101 #endif
   1102 
   1103     SOC_IF_ERROR_RETURN(soc_pstats_sync(unit));
   1104 
   1105 #ifdef BCM_PSTATS_MEASURE
   1106     /* sync local time */
   1107     pbuf = &PSTATS_CTRL(unit).local_time;
   1108     SOC_IF_ERROR_RETURN(
   1109         soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0));
   1110     pentry = soc_mem_table_idx_to_pointer(unit, pbuf->mem, void*,
   1111                                           pbuf->buf, 0);
   1112     soc_mem_field64_get(unit, pbuf->mem, pentry, TIMESTAMPf, &start_ts);
   1113 
   1114     pbuf = &PSTATS_CTRL(unit).local_time_end;
   1115     SOC_IF_ERROR_RETURN(
   1116         soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 1));
   1117     pentry = soc_mem_table_idx_to_pointer(unit, pbuf->mem, void*,
   1118                                           pbuf->buf, 0);
   1119     soc_mem_field64_get(unit, pbuf->mem, pentry, TIMESTAMPf, &end_ts);
   1120 
   1121     LOG_INFO(BSL_LS_BCM_PSTATS,
   1122              (BSL_META_U(unit, "start 0x%x%8x end 0x%x%8x\n"),
   1123              COMPILER_64_HI(start_ts), COMPILER_64_LO(start_ts),
   1124              COMPILER_64_HI(end_ts), COMPILER_64_LO(end_ts)));
   1125 
   1126     /* handle rollover */
   1127     if (COMPILER_64_LT(end_ts, start_ts)) {
   1128         uint64 wrap_amt;
   1129         int width;
   1130 
   1131         width = soc_mem_field_length(unit, MMU_INTFO_TIMESTAMPm, TIMESTAMPf);
   1132         COMPILER_64_SET(wrap_amt, 1UL << (width - 32), 0);
   1133         COMPILER_64_ADD_64(end_ts, wrap_amt);
   1134     }
   1135     COMPILER_64_DELTA(PSTATS_CTRL(unit).time_cost, start_ts, end_ts);
   1136 #endif
   1137 
   1138 
   1139     /* sync utc time */
   1140     pbuf = &PSTATS_CTRL(unit).utc_time;
   1141     SOC_IF_ERROR_RETURN(
   1142         soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0));
   1143 
   1144     /* sync uc queue */
   1145     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   1146         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   1147 
   1148             if(!((si->epipe_xpe_map[pipe] >> xpe) & 1)) {
   1149                 continue;
   1150             }
   1151             index = TD3_XPE_PIPE_INDEX(unit, xpe, pipe);
   1152             if (index >= TD3_MAX_XPEPIPE) {
   1153                 return BCM_E_INTERNAL;
   1154             }
   1155             pbuf = &PSTATS_CTRL(unit).ucq_buffer[index];
   1156             SOC_IF_ERROR_RETURN(
   1157                 soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0));
   1158         }
   1159     }
   1160 
   1161     /* sync ing pool */
   1162     for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   1163 
   1164         index = TD3_XPE_PIPE_INDEX(unit, xpe, -1);
   1165         if (index >= TD3_MAX_POOL_COUNT) {
   1166             return BCM_E_INTERNAL;
   1167         }
   1168         pbuf = &PSTATS_CTRL(unit).ing_pool_buffer[index];
   1169         SOC_IF_ERROR_RETURN(
   1170             soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0));
   1171     }
   1172 
   1173     /* sync egr pool */
   1174     for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   1175 
   1176         index = TD3_XPE_PIPE_INDEX(unit, xpe, -1);
   1177         if (index >= TD3_MAX_POOL_COUNT) {
   1178             return BCM_E_INTERNAL;
   1179         }
   1180         pbuf = &PSTATS_CTRL(unit).egr_pool_buffer[index];
   1181         SOC_IF_ERROR_RETURN(
   1182             soc_pstats_mem_get(unit, pbuf->mem, pbuf->buf, 0));
   1183     }
   1184 
   1185     return BCM_E_NONE;
   1186 }
   1187 
   1188 /*
   1189  * Function:
   1190  *      _bcm_td3_pstats_session_data_sync
   1191  * Purpose:
   1192  *      Start a pstats sync operation for a special session
   1193  * Parameters:
   1194  *      unit - (IN) StrataSwitch unit number
   1195  * Returns:
   1196  *      BCM_E_XXX
   1197  */
   1198 STATIC int
   1199 _bcm_td3_pstats_session_data_sync(int unit, pstats_session_t *session)
   1200 {
   1201     BCM_IF_ERROR_RETURN(_bcm_td3_pstats_hw_sync(unit));
   1202     BCM_IF_ERROR_RETURN(_bcm_td3_pstats_session_update(unit, session));
   1203     return BCM_E_NONE;
   1204 }
   1205 
   1206 /*
   1207  * Function:
   1208  *      bcm_td3_pstats_data_sync
   1209  * Purpose:
   1210  *      Start a pstats sync operation.
   1211  * Parameters:
   1212  *      unit - (IN) StrataSwitch unit number
   1213  * Returns:
   1214  *      BCM_E_XXX
   1215  */
   1216 STATIC int
   1217 bcm_td3_pstats_data_sync(int unit)
   1218 {
   1219     pstats_session_t    *cur_session = NULL;
   1220     sal_usecs_t         start_time = sal_time_usecs();
   1221 
   1222     BCM_IF_ERROR_RETURN(_bcm_td3_pstats_hw_sync(unit));
   1223     LOG_DEBUG(BSL_LS_SOC_COMMON,
   1224               (BSL_META_U(unit, "Time taken for pstats dma: %d usec\n"),
   1225                           SAL_USECS_SUB(sal_time_usecs(), start_time)));
   1226     cur_session = PSTATS_CTRL(unit).first_session;
   1227     while (NULL != cur_session) {
   1228         if (cur_session->enable != TRUE) {
   1229             continue;
   1230         }
   1231         BCM_IF_ERROR_RETURN(
   1232                 _bcm_td3_pstats_session_update(unit, cur_session));
   1233         cur_session = cur_session->next_session;
   1234     }
   1235     return BCM_E_NONE;
   1236 }
   1237 
   1238 /*
   1239  * Function:
   1240  *      bcm_td3_pstats_session_data_get
   1241  * Purpose:
   1242  *      Get an existing PSTATS session data.
   1243  * Parameters:
   1244  *      unit - (IN) StrataSwitch unit number
   1245  *      session_id - (IN) id of a PSTATS session created via the
   1246  *                        bcm_pstats_session_create
   1247  *      sync - (IN) Need a sync operation
   1248  *      timestamp - (OUT) time stamp info.
   1249  *      array_max - (IN) Maximum number of elements in array.
   1250  *      data - (OUT) array of use count data.
   1251  *      array_count - (OUT) Number of elements in array.
   1252  * Returns:
   1253  *      BCM_E_XXX
   1254  */
   1255 STATIC int
   1256 bcm_td3_pstats_session_data_get(int unit, bcm_pstats_session_id_t session_id,
   1257                                 int sync,
   1258                                 bcm_pstats_timestamp_t *timestamp,
   1259                                 int array_max,
   1260                                 bcm_pstats_data_t *data_array,
   1261                                 int *array_count)
   1262 {
   1263     pstats_session_t        *cur_session = NULL;
   1264     int                     mode;
   1265 
   1266     LOG_INFO(BSL_LS_BCM_PSTATS,
   1267         (BSL_META_U(unit, "pstats_session_data_get unit %d session_id %d "
   1268                     "sync %d\n"), unit, session_id, sync));
   1269 
   1270     if (NULL == data_array) {
   1271         LOG_ERROR(BSL_LS_BCM_PSTATS,
   1272             (BSL_META_U(unit, "data_array is null\n")));
   1273         return BCM_E_PARAM;
   1274     }
   1275 
   1276     mode = PSTATS_CTRL(unit).stat_mode;
   1277     cur_session = _bcm_td3_pstats_session_get(unit, session_id);
   1278     if (NULL == cur_session) {
   1279         LOG_INFO(BSL_LS_BCM_PSTATS,
   1280             (BSL_META_U(unit, "pstats_session_data_get: "
   1281                         "session_id %d is not found\n"), session_id));
   1282         return BCM_E_NOT_FOUND;
   1283     }
   1284 
   1285     if (array_max >= cur_session->element_array_count) {
   1286         *array_count = cur_session->element_array_count;
   1287     } else if (array_max >= 0) {
   1288         *array_count = array_max;
   1289     } else {
   1290         LOG_ERROR(BSL_LS_BCM_PSTATS,
   1291             (BSL_META_U(unit, "array_max %d is illegal\n"), array_max));
   1292         return BCM_E_PARAM;
   1293     }
   1294 
   1295     /* if PKT STAT mode is HWM, need to sync up all sessions */
   1296     if (TRUE == sync) {
   1297         if (mode) {
   1298             BCM_IF_ERROR_RETURN(bcm_td3_pstats_data_sync(unit));
   1299         } else {
   1300             BCM_IF_ERROR_RETURN(
   1301                     _bcm_td3_pstats_session_data_sync(unit, cur_session));
   1302         }
   1303     }
   1304 
   1305     sal_memcpy(data_array, cur_session->data_array,
   1306                *array_count * sizeof(bcm_pstats_data_t));
   1307 
   1308     sal_memcpy(timestamp, &cur_session->timestamp, sizeof(bcm_pstats_timestamp_t));
   1309 
   1310     return BCM_E_NONE;
   1311 }
   1312 
   1313 STATIC int
   1314 _bcm_td3_pstats_session_data_hw_clear(int unit, bcm_pstats_session_element_t element)
   1315 {
   1316     bcm_gport_t                 gport;
   1317     bcm_port_t                  local_port;
   1318     bcm_cos_queue_t             cosq;
   1319     bcm_service_pool_id_t       pool;
   1320     int                         index, xpe, pipe, startq;
   1321     soc_info_t                  *si = &SOC_INFO(unit);
   1322     soc_mem_t                   mem;
   1323     soc_field_t                 field;
   1324     uint32                      entry[SOC_MAX_MEM_WORDS];
   1325 
   1326     if (element.type == bcmPStatsSessionUnicastQueue) {
   1327         /* update ucq use counts
   1328          * ucq_buf:
   1329          * 0-1 each XPE has two pipes */
   1330         gport = element.gport;
   1331         cosq = element.cosq;
   1332         BCM_IF_ERROR_RETURN(
   1333             _bcm_td3_cosq_index_resolve(unit, gport, cosq,
   1334                                        _BCM_TD3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   1335                                        &local_port, &startq, NULL));
   1336         pipe = si->port_pipe[local_port];
   1337 
   1338         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   1339 
   1340             if(!((si->epipe_xpe_map[pipe] >> xpe) & 1)) {
   1341                 continue;
   1342             }
   1343             index = TD3_XPE_PIPE_INDEX(unit, xpe, pipe);
   1344             if (index >= TD3_MAX_XPEPIPE) {
   1345                 return BCM_E_INTERNAL;
   1346             }
   1347             mem = PSTATS_CTRL(unit).ucq_buffer[index].clear_mem;
   1348             SOC_IF_ERROR_RETURN(
   1349                 soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   1350             soc_mem_field32_set(unit, mem, entry, UCQ_COUNTf, 0);
   1351             SOC_IF_ERROR_RETURN(
   1352                 soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   1353         }
   1354     } else {
   1355         /* update pool use counts
   1356          * pool_buf:
   1357          * 0-3   |xpe0-p0|xpe1-p0|xpe2-p0|xpe3-p0|
   1358          */
   1359         pool = element.pool;
   1360         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   1361 
   1362             index = TD3_XPE_PIPE_INDEX(unit, xpe, -1);
   1363             if (index >= TD3_MAX_POOL_COUNT) {
   1364                 return BCM_E_INTERNAL;
   1365             }
   1366 
   1367             if (element.type == bcmPStatsSessionIngPool) {
   1368                 mem = PSTATS_CTRL(unit).ing_pool_buffer[xpe].clear_mem;
   1369                 field = isp_field[pool];
   1370             } else if (element.type == bcmPStatsSessionEgrPool) {
   1371                 mem = PSTATS_CTRL(unit).egr_pool_buffer[xpe].clear_mem;
   1372                 field = esp_field[pool];
   1373             } else {
   1374                 return BCM_E_INTERNAL;
   1375             }
   1376             SOC_IF_ERROR_RETURN(
   1377                 soc_mem_read(unit, mem, MEM_BLOCK_ALL, 0, entry));
   1378             soc_mem_field32_set(unit, mem, entry, field, 0);
   1379             SOC_IF_ERROR_RETURN(
   1380                 soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, entry));
   1381         }
   1382     }
   1383 
   1384     return BCM_E_NONE;
   1385 }
   1386 
   1387 /*
   1388  * Function:
   1389  *      bcm_pstats_session_data_clear
   1390  * Purpose:
   1391  *      Clear an existing PSTATS session hw use counts and sw use counts buffer.
   1392  * Parameters:
   1393  *      unit - (IN) StrataSwitch unit number.
   1394  *      session_id - (IN) id of a PSTATS session created via the
   1395  *                        bcm_pstats_session_create.
   1396  * Returns:
   1397  *      BCM_E_XXX
   1398  */
   1399 STATIC int
   1400 bcm_td3_pstats_session_data_clear(int unit, bcm_pstats_session_id_t session_id)
   1401 {
   1402     bcm_pstats_session_element_t    element;
   1403     pstats_session_t                *cur_session = NULL;
   1404     int                             i, need_hw_clear = 1;
   1405 
   1406     LOG_INFO(BSL_LS_BCM_PSTATS,
   1407         (BSL_META_U(unit, "pstats_session_data_clear unit %d session_id %d\n"),
   1408                     unit, session_id));
   1409 
   1410     cur_session = _bcm_td3_pstats_session_get(unit, session_id);
   1411     if (NULL == cur_session) {
   1412         LOG_INFO(BSL_LS_BCM_PSTATS,
   1413             (BSL_META_U(unit, "pstats_session_data_clear: "
   1414                         "session_id %d is not found\n"), session_id));
   1415         return BCM_E_NOT_FOUND;
   1416     }
   1417 
   1418     /* clear HW use count buffer */
   1419     if ((PSTATS_CTRL(unit).stat_mode == 1) &&
   1420         (PSTATS_CTRL(unit).hw_cor_in_max_use_count == 1)) {
   1421         /* HW clear on read is enabled, no need do hw clear */
   1422         need_hw_clear = 0;
   1423     }
   1424 
   1425     if (need_hw_clear == 1) {
   1426         for (i = 0; i < cur_session->element_array_count; i++) {
   1427             element = cur_session->element_array[i];
   1428             BCM_IF_ERROR_RETURN(
   1429                 _bcm_td3_pstats_session_data_hw_clear(unit, element));
   1430         }
   1431     }
   1432 
   1433     /* clear SW use count buffer */
   1434     sal_memset(cur_session->data_array, 0,
   1435                cur_session->element_array_count * sizeof(bcm_pstats_data_t));
   1436 
   1437     return BCM_E_NONE;
   1438 }
   1439 
   1440 /*
   1441  * Function:
   1442  *      bcm_td3_pstats_session_traverse
   1443  * Purpose:
   1444  *      Traverse through the pstats sessions and run callback at each
   1445  *      session.
   1446  * Parameters:
   1447  *      unit - (IN) StrataSwitch unit number.
   1448  *      cb - (IN) bcm_pstats_session_traverse_cb.
   1449  *      user_data - (IN) User data to be passed to callback function.
   1450  * Returns:
   1451  *      BCM_E_XXX
   1452  */
   1453 STATIC int
   1454 bcm_td3_pstats_session_traverse(int unit, bcm_pstats_session_traverse_cb cb,
   1455                                 void *user_data)
   1456 {
   1457     bcm_pstats_session_element_t    element_array[TD3_MAX_ELEMENT_COUNT];
   1458     bcm_pstats_session_id_t         session_id;
   1459     pstats_session_t                *cur_session = NULL;
   1460     int                             array_count;
   1461     int                             rv = BCM_E_NONE;
   1462 
   1463     LOG_INFO(BSL_LS_BCM_PSTATS,
   1464             (BSL_META_U(unit, "pstats_session_travers unit %d\n"), unit));
   1465 
   1466     cur_session = PSTATS_CTRL(unit).first_session;
   1467     while (NULL != cur_session) {
   1468         session_id = cur_session->session_id;
   1469         array_count = cur_session->element_array_count;
   1470         sal_memcpy(element_array, cur_session->element_array,
   1471                 array_count * sizeof(bcm_pstats_session_element_t));
   1472 
   1473         cur_session = cur_session->next_session;
   1474 
   1475         rv = cb(unit, session_id, array_count, element_array, user_data);
   1476 #ifdef BCM_CB_ABORT_ON_ERR
   1477         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   1478             return rv;
   1479         }
   1480 #else
   1481         /*
   1482          * If CB_ABORT_ON_ERR is not defined don't return error
   1483          * and continue.
   1484          */
   1485         rv = BCM_E_NONE;
   1486 #endif
   1487     }
   1488 
   1489      return rv;
   1490  }
   1491 #else /* INCLUDE_PSTATS && BCM_TRIDENT3_SUPPORT */
   1492 int bcm_esw_trident3_pstats_not_empty;
   1493 #endif /* INCLUDE_PSTATS && BCM_TRIDENT3_SUPPORT */