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

bst.c (150054B)


      1  /* 
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  *
      6  * BST - Buffer Statistics Tracking
      7  * Purpose: API to set and manage various BST resources for TH3
      8  */
      9 
     10 #include <shared/bsl.h>
     11 #include <soc/defs.h>
     12 #include <sal/core/libc.h>
     13 #include <shared/alloc.h>
     14 #include <sal/core/spl.h>
     15 #include <sal/core/boot.h>
     16 
     17 #include <soc/drv.h>
     18 #include <soc/error.h>
     19 #include <soc/ll.h>
     20 #include <soc/debug.h>
     21 #include <soc/mem.h>
     22 #include <soc/profile_mem.h>
     23 #include <soc/tomahawk3.h>
     24 #include <soc/pfc.h>
     25 
     26 #include <bcm/switch.h>
     27 #include <bcm/types.h>
     28 #include <bcm/cosq.h>
     29 #include <bcm_int/bst.h>
     30 #include <bcm_int/esw/port.h>
     31 #include <bcm_int/esw/tomahawk3.h>
     32 #include <bcm_int/esw/pfc.h>
     33 #if defined(BCM_TOMAHAWK3_SUPPORT)
     34 
     35 #define _TH3_BST_THRESHOLD_CELL_MAX 0x3ffff
     36 #define _TH3_BST_PROFILE_INIT_FLAG 2
     37 #define _TH3_BST_QUEUE_TYPE_SHIFT 16
     38 #define _TH3_BST_QUEUE_TYPE_SHIFT_MASK 0xffff
     39 #define _BCM_TH3_BST_Q_TYPE_UC 0
     40 #define _BCM_TH3_BST_Q_TYPE_MC 1
     41 #define _BCM_TH3_BST_Q_TYPE_CPU 2
     42 #define _BCM_TH3_BST_Q_TYPE_COUNT 3
     43 
     44 typedef enum _bcm_th3_bst_config_e {
     45     _bcm_th3_bst_config_tracking_mode = 0,
     46     _bcm_th3_bst_config_snapshot = 1
     47 } _bcm_th3_bst_config_t;
     48 
     49 typedef enum _bcm_th3_bst_module_e {
     50     _BCM_TH3_BST_MODULE_THDO = 0,
     51     _BCM_TH3_BST_MODULE_THDI = 1,
     52     _BCM_TH3_BST_MODULE_CFAP = 2,
     53     _BCM_TH3_BST_MODULE_THDR = 3,
     54     _BCM_TH3_BST_MODULE_COUNT =4
     55 } _bcm_th3_bst_module_t;
     56 
     57 typedef struct _bcm_th3_bst_resource_info_s {
     58    bcm_bst_stat_id_t stat_id;
     59    soc_reg_t    stat_reg;
     60    soc_mem_t    stat_mem;
     61    soc_field_t  stat_field;
     62    soc_reg_t    thd_reg;
     63    soc_mem_t    thd_mem;
     64    soc_field_t  thd_field;
     65    int idx_count;
     66    int stat_count;
     67    int thd_count;
     68 } _bcm_th3_bst_resource_info_t;
     69 
     70 extern int _bcm_bst_th3_sync_hw_snapshot(int unit, bcm_bst_stat_id_t bid,
     71                                         int port, int index);
     72 
     73 const static
     74 soc_field_t sp_fields[] = {PORTSP0_SHARED_COUNTf, PORTSP1_SHARED_COUNTf,
     75                            PORTSP2_SHARED_COUNTf, PORTSP3_SHARED_COUNTf};
     76 const static
     77 soc_field_t sp_sel_fields[] = {PORTSP0_BST_SHARED_PROFILE_SELf,
     78                                PORTSP1_BST_SHARED_PROFILE_SELf,
     79                                PORTSP2_BST_SHARED_PROFILE_SELf,
     80                                PORTSP3_BST_SHARED_PROFILE_SELf};
     81 
     82 const static
     83 soc_field_t pg_fields[] = {PG0_SHARED_COUNTf, PG1_SHARED_COUNTf,
     84                            PG2_SHARED_COUNTf, PG3_SHARED_COUNTf,
     85                            PG4_SHARED_COUNTf, PG5_SHARED_COUNTf,
     86                            PG6_SHARED_COUNTf, PG7_SHARED_COUNTf};
     87 
     88 const static
     89 soc_field_t pg_sel_fields[] = {PG0_BST_SHARED_PROFILE_SELf,
     90                                PG1_BST_SHARED_PROFILE_SELf,
     91                                PG2_BST_SHARED_PROFILE_SELf,
     92                                PG3_BST_SHARED_PROFILE_SELf,
     93                                PG4_BST_SHARED_PROFILE_SELf,
     94                                PG5_BST_SHARED_PROFILE_SELf,
     95                                PG6_BST_SHARED_PROFILE_SELf,
     96                                PG7_BST_SHARED_PROFILE_SELf};
     97 
     98 const static
     99 soc_field_t pg_hdrm_fields[] = {PG0_BST_STAT_HDRMf, PG1_BST_STAT_HDRMf,
    100                                 PG2_BST_STAT_HDRMf, PG3_BST_STAT_HDRMf,
    101                                 PG4_BST_STAT_HDRMf, PG5_BST_STAT_HDRMf,
    102                                 PG6_BST_STAT_HDRMf, PG7_BST_STAT_HDRMf};
    103 
    104 const static
    105 soc_field_t pg_hdrm_sel_fields[] = {PG0_BST_HDRM_PROFILE_SELf,
    106                                     PG1_BST_HDRM_PROFILE_SELf,
    107                                     PG2_BST_HDRM_PROFILE_SELf,
    108                                     PG3_BST_HDRM_PROFILE_SELf,
    109                                     PG4_BST_HDRM_PROFILE_SELf,
    110                                     PG5_BST_HDRM_PROFILE_SELf,
    111                                     PG6_BST_HDRM_PROFILE_SELf,
    112                                     PG7_BST_HDRM_PROFILE_SELf};
    113 
    114 const static
    115 soc_field_t uc_portsp_fields[] = {SP0_BST_PORT_SHARED_COUNTf,
    116                                   SP1_BST_PORT_SHARED_COUNTf,
    117                                   SP2_BST_PORT_SHARED_COUNTf,
    118                                   SP3_BST_PORT_SHARED_COUNTf};
    119 const static
    120 soc_field_t uc_portsp_sel_fields[] = {BST_PORTSP0_WM_SHARED_THRESHOLD_SELf,
    121                                   BST_PORTSP1_WM_SHARED_THRESHOLD_SELf,
    122                                   BST_PORTSP2_WM_SHARED_THRESHOLD_SELf,
    123                                   BST_PORTSP3_WM_SHARED_THRESHOLD_SELf};
    124 
    125 STATIC int _bcm_bst_th3_sbusdma_desc_sync(int unit);
    126 STATIC int _bcm_bst_th3_sbusdma_desc_init(int unit);
    127 STATIC int _bcm_bst_th3_sbusdma_desc_deinit(int unit);
    128 
    129 
    130 STATIC int
    131 _bcm_bst_th3_byte_to_cell(int unit, uint32 bytes)
    132 {
    133     return (bytes + (_TH3_MMU_BYTES_PER_CELL - 1))/_TH3_MMU_BYTES_PER_CELL;
    134 }
    135 
    136 STATIC int
    137 _bcm_bst_th3_cell_to_byte(int unit, uint32 cells)
    138 {
    139     return cells * _TH3_MMU_BYTES_PER_CELL;
    140 }
    141 
    142 STATIC uint32
    143 _bcm_bst_th3_profile_reg_id_get(int unit, bcm_bst_stat_id_t bid, int index) {
    144     if(bcmBstStatIdQueueTotal == bid) {
    145         return (index >> _TH3_BST_QUEUE_TYPE_SHIFT);
    146     }
    147     return 0;
    148 }
    149 
    150 STATIC int
    151 _bcm_th3_bst_bid_gport_cosq_param_check(int unit, bcm_bst_stat_id_t bid,
    152         bcm_gport_t gport, bcm_cos_queue_t cosq) {
    153     soc_info_t *si = &SOC_INFO(unit);
    154     int port_num_ucq, port;
    155 
    156     if (bid == bcmBstStatIdDevice) {
    157         /*port,queue based param checks invalid for Device*/
    158         return BCM_E_NONE;
    159     }
    160     if ((bid == bcmBstStatIdHeadroomPool) ||
    161         (bid == bcmBstStatIdIngPool) ||
    162         (bid == bcmBstStatIdPortPool) ||
    163         (bid == bcmBstStatIdPriGroupShared) ||
    164         (bid == bcmBstStatIdPriGroupHeadroom)) {
    165         if (cosq >= _TH3_MMU_NUM_PG) {
    166             return BCM_E_PARAM;
    167         }
    168     }
    169 
    170     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    171         /* Passed cosq is multicast. Cannot be used for unicast Bids */
    172         if ((bid == bcmBstStatIdUcast) ||
    173            (bid == bcmBstStatIdEgrPool) ||
    174            (bid == bcmBstStatIdEgrPortPoolSharedUcast)) {
    175            return BCM_E_PARAM;
    176         }
    177     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    178         /* Passed cosq is unicast. Cannot be used for multicast Bids */
    179         if ((bid == bcmBstStatIdMcast) ||
    180             (bid == bcmBstStatIdEgrMCastPool) ||
    181             (bid == bcmBstStatIdEgrPortPoolSharedMcast)) {
    182             return BCM_E_PARAM;
    183         }
    184     } else {
    185         if (gport == -1) {
    186             return BCM_E_NONE;
    187         }
    188         /* GPORT is of local port type */
    189         BCM_IF_ERROR_RETURN(
    190                 _bcm_th3_cosq_localport_resolve(unit, gport, &port));
    191         if (cosq < BCM_COS_INVALID) {
    192             return BCM_E_PARAM;
    193         }
    194         if (cosq == BCM_COS_INVALID) {
    195             return BCM_E_NONE;
    196         }
    197         if (IS_CPU_PORT(unit, port)) {
    198             port_num_ucq = 0;
    199             if (cosq >= SOC_TH3_NUM_CPU_QUEUES) {
    200                 return BCM_E_PARAM;
    201             }
    202         } else {
    203             port_num_ucq = si->port_num_uc_cosq[port];
    204             if (cosq >= SOC_TH3_NUM_GP_QUEUES) {
    205                 return BCM_E_PARAM;
    206             }
    207         }
    208         if (cosq < port_num_ucq) {
    209             /* Passed cosq is unicast. Cannot be used for multicast Bids */
    210             if ((bid == bcmBstStatIdMcast) ||
    211                 (bid == bcmBstStatIdEgrMCastPool) ||
    212                 (bid == bcmBstStatIdEgrPortPoolSharedMcast)) {
    213                 return BCM_E_PARAM;
    214             }
    215         } else {
    216             /* Passed cosq is multicast. Cannot be used for unicast Bids */
    217              if ((bid == bcmBstStatIdUcast) ||
    218                 (bid == bcmBstStatIdEgrPool) ||
    219                 (bid == bcmBstStatIdEgrPortPoolSharedUcast)) {
    220                 return BCM_E_PARAM;
    221             }
    222         }
    223     }
    224     return BCM_E_NONE;
    225 }
    226 
    227 STATIC int _bcm_bst_field_ids_retrieve(int unit, bcm_bst_stat_id_t bid,
    228         bcm_gport_t gport, bcm_cos_queue_t cosq, int *field_idx, int *num_fields) {
    229 
    230     int idx, pool, local_port;
    231 
    232     if ((field_idx == NULL) || (num_fields == NULL)) {
    233         return BCM_E_PARAM;
    234     }
    235     BCM_IF_ERROR_RETURN(
    236             _bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
    237     switch (bid) {
    238         case bcmBstStatIdPortPool:
    239             if(cosq == BCM_COS_INVALID) {
    240                 *num_fields = _TH3_MMU_NUM_POOL;
    241                 for (idx = 0; idx < _TH3_MMU_NUM_POOL; idx ++) {
    242                     field_idx[idx] = idx;
    243                 }
    244             } else {
    245                 BCM_IF_ERROR_RETURN(
    246                     _bcm_th3_cosq_ingress_sp_get_by_pg(unit, local_port,
    247                                                         cosq, &pool));
    248                 field_idx[0] = pool;
    249                 *num_fields = 1;
    250             }
    251             break;
    252         case bcmBstStatIdPriGroupShared:
    253         case bcmBstStatIdPriGroupHeadroom:
    254             if(cosq == BCM_COS_INVALID) {
    255                 *num_fields = _TH3_MMU_NUM_PG;
    256                 for (idx = 0; idx < _TH3_MMU_NUM_PG; idx ++) {
    257                     field_idx[idx] = idx;
    258                 }
    259             } else {
    260                 field_idx[0] = cosq;
    261                 *num_fields = 1;
    262             }
    263             break;
    264         case bcmBstStatIdEgrPortPoolSharedUcast:
    265             if(cosq == BCM_COS_INVALID) {
    266                 *num_fields = _TH3_MMU_NUM_POOL;
    267                 for (idx = 0; idx < _TH3_MMU_NUM_POOL; idx ++) {
    268                     field_idx[idx] = idx;
    269                 }
    270             } else {
    271                 BCM_IF_ERROR_RETURN(
    272                     _bcm_th3_cosq_egress_sp_get (unit, gport, cosq, &pool, NULL));
    273                 field_idx[0] = pool;
    274                 *num_fields = 1;
    275             }
    276             break;
    277         default:
    278             return BCM_E_PARAM;
    279     }
    280     return BCM_E_NONE;
    281 }
    282 
    283 /*
    284  * Function:
    285  *    _bcm_th3_bst_tracking_enable_set
    286  * Purpose:
    287  *   Enable/Disable BST tracking.
    288  * Parameters:
    289  *     unit       - (IN) unit number
    290  *     arg  - (IN)  enable/disable config
    291  *     operation - (IN) operation type
    292  * Returns:
    293  *     BCM_E_XXX
    294  */
    295 
    296 STATIC int
    297 _bcm_th3_bst_tracking_enable_set(int unit, int arg,
    298                             _bcm_bst_thread_oper_t operation)
    299 {
    300 #define _BCM_BST_TH3_GLB_TRACKING_EN 0xff
    301 
    302     soc_reg_t reg;
    303     uint32 rval;
    304     _bcm_bst_cmn_unit_info_t *bst_info;
    305     reg = MMU_GLBCFG_BST_TRACKING_ENABLEr;
    306 
    307     bst_info = _BCM_UNIT_BST_INFO(unit);
    308     if (!bst_info) {
    309         return BCM_E_INIT;
    310     }
    311 
    312     rval = arg ? _BCM_BST_TH3_GLB_TRACKING_EN : 0;
    313     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, REG_PORT_ANY, rval));
    314 
    315     if (operation == _bcmBstThreadOperExternal) {
    316         bst_info->bst_tracking_enable = arg;
    317         if (arg) {
    318             BCM_IF_ERROR_RETURN(_bcm_bst_sync_thread_start(unit));
    319         } else {
    320             BCM_IF_ERROR_RETURN(_bcm_bst_sync_thread_stop(unit));
    321         }
    322     } else {
    323         /* Set Enable Flag to True/False, to Run/Pause the Thread
    324          * respectively. Wont Kill the thread.
    325          */
    326         _BCM_BST_SYNC_THREAD_ENABLE_SET(unit, arg ? TRUE : FALSE);
    327     }
    328 #undef _BCM_BST_TH3_GLB_TRACKING_EN
    329     return BCM_E_NONE;
    330 }
    331 
    332 /*
    333  * Function:
    334  *    _bcm_th3_bst_config_set
    335  * Purpose:
    336  *    Set BST config for different modules.
    337  * Parameters:
    338  *     unit       - (IN) unit number
    339  *     arg  - (IN)  tracking mode config
    340  *                  bit[0]:THDO, bit[1]: THDI, bit[2]: CFAP
    341  *     type - (IN) bst config type
    342  * Returns:
    343  *     BCM_E_XXX
    344  */
    345 STATIC int
    346 _bcm_th3_bst_config_set(int unit, int arg, _bcm_th3_bst_config_t type)
    347 {
    348     int i;
    349     uint32 rval, mode, glb_rval;
    350     _bcm_bst_cmn_unit_info_t *bst_info;
    351     soc_reg_t reg, glb_reg;
    352     soc_field_t field = INVALIDf;
    353     soc_reg_t blk_regs[] = {MMU_THDO_BST_CONFIGr, MMU_THDI_BSTCONFIGr,
    354                         MMU_CFAP_BSTCONFIGr, MMU_THDR_QE_BST_CONFIGr};
    355     soc_field_t blk_fields[2][4] = {
    356               {TRACKING_MODEf, TRACKING_MODEf, TRACKING_MODEf, TRACK_MODEf},
    357               {SNAPSHOT_ENf, SNAPSHOT_ENf, SNAPSHOT_ENf, HW_SNAPSHOT_ENf} };
    358     soc_field_t glb_fields[] = {
    359                         ACTION_EN_THDO0f, ACTION_EN_THDO1f,
    360                         ACTION_EN_THDI0f, ACTION_EN_THDI1f,
    361                         ACTION_EN_CFAP0f, ACTION_EN_CFAP1f,
    362                         ACTION_EN_THDR0f, ACTION_EN_THDR1f};
    363     soc_info_t *si = &SOC_INFO(unit);
    364     uint32 itm_map = si->itm_map;
    365     int itm, inst;
    366 
    367     bst_info = _BCM_UNIT_BST_INFO(unit);
    368 
    369     if (!bst_info) {
    370         return BCM_E_INIT;
    371     }
    372     glb_reg = MMU_GLBCFG_BST_SNAPSHOT_ACTION_ENr;
    373     switch (type) {
    374         case _bcm_th3_bst_config_tracking_mode:
    375             bst_info->track_mode = arg;
    376             break;
    377         case _bcm_th3_bst_config_snapshot:
    378             bst_info->snapshot_mode = arg;
    379             break;
    380         default:
    381             return BCM_E_PARAM;
    382     }
    383     for (i = _BCM_TH3_BST_MODULE_THDO; i < _BCM_TH3_BST_MODULE_COUNT; i++) {
    384         field = blk_fields[type][i];
    385         mode = 0;
    386         if (type == _bcm_th3_bst_config_snapshot) {
    387             if (arg & (0x1 << i)) {
    388                 mode = 0x1;
    389             }
    390         } else {
    391             if (arg) {
    392                 mode = 1;
    393             } else {
    394                 mode = 0;
    395             }
    396         }
    397         reg = blk_regs[i];
    398         for (itm = 0; itm < NUM_ITM(unit); itm++) {
    399             if (itm_map & (1 << itm)) {
    400                 if ((itm == 1) && (i == _BCM_TH3_BST_MODULE_THDO)) {
    401                     continue;
    402                 }
    403                 inst = itm | SOC_REG_ADDR_INSTANCE_MASK;
    404                 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0,
    405                             &rval));
    406                 soc_reg_field_set(unit, reg, &rval, field, mode);
    407 
    408                 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0,
    409                             rval));
    410             }
    411         }
    412 
    413 
    414         if(type == _bcm_th3_bst_config_snapshot) {
    415             glb_rval = 0;
    416             /* config GLOBAL snapshot action register */
    417             SOC_IF_ERROR_RETURN(soc_reg32_get(unit, glb_reg,
    418                                 REG_PORT_ANY, 0, &glb_rval));
    419             soc_reg_field_set(unit, glb_reg, &glb_rval,
    420                                    glb_fields[_TH3_ITMS_PER_DEV * i], mode);
    421             soc_reg_field_set(unit, glb_reg, &glb_rval,
    422                                    glb_fields[_TH3_ITMS_PER_DEV * i + 1], mode);
    423             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, glb_reg,
    424                                 REG_PORT_ANY, 0, glb_rval));
    425 
    426         }
    427     }
    428 
    429     return BCM_E_NONE;
    430 }
    431 
    432 /*
    433  * Function:
    434  *    _bcm_th3_bst_resource_init
    435  * Purpose:
    436  *   BST Stat resouce init (initialize a SW structure) for a given Stat ID.
    437  * Parameters:
    438  *     unit       - (IN) unit number
    439  *     type  - (IN)  BST stat ID
    440  * Returns:
    441  *     BCM_E_XXX
    442  */
    443 STATIC int
    444 _bcm_th3_bst_resource_init(int unit, bcm_bst_stat_id_t type)
    445 {
    446 
    447     _bcm_bst_resource_info_t *pres;
    448     int idx_count, i;
    449     /* stat count and thd count need not be same.
    450      * stat_count - Acc Type of stat are Non Dup, hence stat is for all ACC type
    451      * thd_count - Acc Type of Thd are Dup(except CFAP), hence 1 copy.
    452      */
    453     int total_stat_count, total_thd_count;
    454     soc_mem_t stat_mem = INVALIDm, child_mem = INVALIDm,
    455               thd_sel_mem = INVALIDm;
    456 
    457     soc_reg_t stat_reg = INVALIDr, thd_reg = INVALIDr, prof_reg = INVALIDr;
    458 
    459     soc_reg_t q_thd_regs[_BCM_TH3_BST_Q_TYPE_COUNT] = {
    460                                 MMU_THDO_QUE_TOT_BST_THRESHOLDr,
    461                                 MMU_THDO_MC_QUEUE_TOT_BST_THRESHOLDr,
    462                                 MMU_THDO_MC_CPU_QUEUE_TOT_BST_THRESHOLDr
    463                             };
    464     soc_field_t stat_field = INVALIDf, thd_field = INVALIDf,
    465                 thd_sel_field = INVALIDf, prof_field = INVALIDf;
    466 
    467     int granularity = 1;
    468     uint32 pipe_map;
    469     /* get active pipe bitmap */
    470     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
    471 
    472     switch (type) {
    473         case bcmBstStatIdDevice:
    474             /* bcmBstStatIdDevice */
    475             pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdDevice);
    476             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    477             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_RES_DEV);
    478             pres->num_instance = NUM_ITM(unit);
    479             pres->num_field = 1;
    480             idx_count = 1;
    481             stat_mem = INVALIDm;
    482             stat_reg = MMU_CFAP_BSTSTATr;
    483             stat_field = CNTf;
    484 
    485             /* Threshold info count and Resource allocation */
    486             granularity = 1;
    487             total_thd_count = NUM_ITM(unit) * idx_count;
    488             _BCM_BST_THRESHOLD_INFO(pres, INVALIDm, MMU_CFAP_BSTTHRSr,
    489                                                 BST_THRESHOLDf, granularity);
    490             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, "bst cfap");
    491             /* Stat info count and Resource allocation */
    492             total_stat_count = total_thd_count; /* No per pipe copy */
    493             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    494             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, "bst cfap");
    495             pres->index_min = 0;
    496             pres->index_max = total_stat_count - 1;
    497             break;
    498         case bcmBstStatIdHeadroomPool:
    499             /* bcmBstStatIdHeadroomPool */
    500             pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdHeadroomPool);
    501             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    502             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_RES_ING);
    503             pres->num_instance = NUM_ITM(unit);
    504             pres->num_field = 1;
    505             /* There are 4 HDRM POOL per ITM */
    506             idx_count = _TH3_MMU_NUM_POOL;
    507             stat_mem = INVALIDm;
    508             stat_reg = MMU_THDI_BST_HDRM_POOL_CNTr;
    509             stat_field = HDRM_POOL_CNTf;
    510             /* Threshold info count and Resource allocation */
    511             granularity = 1;
    512             total_thd_count = idx_count;
    513             _BCM_BST_THRESHOLD_INFO(pres, INVALIDm, MMU_THDI_BST_HDRM_POOLr,
    514                                            BST_HDRM_POOL_THRESHf, granularity);
    515             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count,
    516                                                       "bst ing headroom pool");
    517             /* Stat info count and Resource allocation */
    518             total_stat_count = NUM_ITM(unit) * total_thd_count;
    519             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    520             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count,
    521                                             "bst ing headroom pool");
    522             pres->index_min = 0;
    523             pres->index_max = total_stat_count - 1;
    524             break;
    525         case bcmBstStatIdIngPool:
    526             /* bcmBstStatIdIngPool */
    527             pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdIngPool);
    528             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    529             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_RES_ING);
    530             pres->num_instance = NUM_ITM(unit);
    531             pres->num_field = 1;
    532             idx_count = _TH3_MMU_NUM_POOL;
    533             stat_mem = INVALIDm;
    534             stat_reg = MMU_THDI_BST_SP_SHARED_CNTr;
    535             stat_field = SP_SHARED_CNTf;
    536 
    537             /* Threshold info count and Resource allocation */
    538             granularity = 1;
    539             total_thd_count = idx_count;
    540             _BCM_BST_THRESHOLD_INFO(pres, INVALIDm,
    541                                     MMU_THDI_BST_SP_SHAREDr,
    542                                     BST_SP_SHARED_THRESHf, granularity);
    543             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, "bst ing pool");
    544             /* Stat info count and Resource allocation */
    545             total_stat_count = NUM_ITM(unit) * total_thd_count;
    546             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    547             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, "bst ing pool");
    548             pres->index_min = 0;
    549             pres->index_max = total_stat_count - 1;
    550             break;
    551         case bcmBstStatIdPortPool:
    552             pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdPortPool);
    553             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    554             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID |
    555                                              _BCM_BST_CMN_RES_F_PIPED |
    556                                              _BCM_BST_CMN_RES_F_RES_ING);
    557             _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_ALL(unit));
    558             pres->num_instance = NUM_PIPE(unit);
    559             stat_mem = MMU_THDI_PORTSP_BSTm;
    560             stat_reg = INVALIDr;
    561             /* multiple fields are hanlded by _BCM_BST_STAT_FIELD_INFO */
    562             stat_field = INVALIDf;
    563 
    564 
    565             /* Get the mem attributes(Max idx) from the first child,
    566              * which could be used for other instances.
    567              */
    568             child_mem = SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit, stat_mem, 0, 0);
    569             idx_count = soc_mem_index_max(unit, child_mem) + 1;
    570 
    571             /* Threshold profile selection info count and Resource allocation */
    572             granularity = 1;
    573             total_thd_count = NUM_PIPE(unit) * idx_count * _TH3_MMU_NUM_POOL;
    574             thd_sel_mem = MMU_THDI_PORT_BST_CONFIGm;
    575             thd_sel_field = INVALIDf;
    576             for (i = 0; i < NUM_PIPE(unit); i++) {
    577                 /* pipe is active */
    578                 if (pipe_map & (1 << i)) {
    579                     _BCM_BST_THRESHOLD_INFO_N(pres,
    580                         SOC_MEM_UNIQUE_ACC_PIPE(unit, thd_sel_mem, i),
    581                                     INVALIDr, thd_sel_field, granularity, i);
    582                 }
    583             }
    584             /* Threshold profile count and Resource allocation */
    585             prof_reg = MMU_THDI_BST_PORTSP_SHARED_PROFILEr;
    586             prof_field = BST_PORTSP_SHARED_THRESHf;
    587             _BCM_BST_PROFILE_INFO(pres, INVALIDm, prof_reg, prof_field);
    588             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, "bst port pool");
    589 
    590             /* Stat info count and Resource allocation */
    591             total_stat_count =  total_thd_count;
    592             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    593             for(i = 0; i < _TH3_MMU_NUM_POOL; i++) {
    594                 _BCM_BST_STAT_FIELD_INFO(pres, sp_fields[i], i);
    595                 _BCM_BST_THD_FIELD_INFO(pres, sp_sel_fields[i], i);
    596             }
    597             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, "bst port pool");
    598             pres->index_min = 0;
    599             pres->index_max = total_stat_count - 1;
    600             break;
    601         case bcmBstStatIdPriGroupShared:
    602             pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdPriGroupShared);
    603             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    604             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID |
    605                                              _BCM_BST_CMN_RES_F_PIPED |
    606                                              _BCM_BST_CMN_RES_F_RES_ING);
    607             _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_ALL(unit));
    608 
    609             pres->num_instance = NUM_PIPE(unit);
    610             stat_mem = MMU_THDI_PORT_PG_SHARED_BSTm;
    611             stat_reg = INVALIDr;
    612             stat_field = INVALIDf;
    613             child_mem = SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit, stat_mem, 0, 0);
    614             idx_count = soc_mem_index_max(unit, child_mem) + 1;
    615 
    616             /* Threshold sel info count and Resource allocation */
    617             granularity = 1;
    618             total_thd_count = idx_count * NUM_PIPE(unit) * _TH3_MMU_NUM_PG;
    619             thd_sel_mem = MMU_THDI_PORT_BST_CONFIGm;
    620             thd_sel_field = INVALIDf;
    621             for (i = 0; i < NUM_PIPE(unit); i++) {
    622                 /* pipe is active */
    623                 if (pipe_map & (1 << i)) {
    624                     _BCM_BST_THRESHOLD_INFO_N(pres,
    625                                      SOC_MEM_UNIQUE_ACC(unit, thd_sel_mem)[i],
    626                                        INVALIDr, thd_sel_field, granularity, i);
    627                 }
    628             }
    629             /* Threshold profile info count and Resource allocation*/
    630             prof_reg = MMU_THDI_BST_PG_SHARED_PROFILEr;
    631             prof_field = BST_PG_SHARED_THRESHf;
    632             _BCM_BST_PROFILE_INFO(pres, INVALIDm, prof_reg, prof_field);
    633             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, "bst pg");
    634             for(i = 0; i < _TH3_MMU_NUM_PG; i++) {
    635                 _BCM_BST_STAT_FIELD_INFO(pres, pg_fields[i], i);
    636                 _BCM_BST_THD_FIELD_INFO(pres, pg_sel_fields[i], i);
    637             }
    638             /* Stat info count and Resource allocation */
    639             /* Stat res - THDI_PORT_PG_BST : (Num Ports (20/pipe) * 8 pipes) * 8(PGs) */
    640             total_stat_count = total_thd_count;
    641             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    642             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, "bst pg");
    643             pres->index_min = 0;
    644             pres->index_max = total_stat_count - 1;
    645             break;
    646         case bcmBstStatIdPriGroupHeadroom:
    647             pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdPriGroupHeadroom);
    648             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    649             pres->num_instance = NUM_PIPE(unit);
    650             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID |
    651                                              _BCM_BST_CMN_RES_F_PIPED |
    652                                              _BCM_BST_CMN_RES_F_RES_ING);
    653             _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_ALL(unit));
    654             stat_mem = MMU_THDI_PORT_PG_HDRM_BSTm;
    655             stat_reg = INVALIDr;
    656             stat_field = INVALIDf;
    657             child_mem = SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit, stat_mem, 0, 0);
    658             idx_count = soc_mem_index_max(unit, child_mem) + 1;
    659 
    660             /* Threshold sel info count and Resource allocation */
    661             granularity = 1;
    662             total_thd_count = idx_count * NUM_PIPE(unit) * _TH3_MMU_NUM_PG;
    663             thd_sel_mem = MMU_THDI_PORT_BST_CONFIGm;
    664             thd_field = INVALIDf;
    665             for (i = 0; i < NUM_PIPE(unit); i++) {
    666                 /* pipe is active */
    667                 if (pipe_map & (1 << i)) {
    668                     _BCM_BST_THRESHOLD_INFO_N(pres,
    669                                 SOC_MEM_UNIQUE_ACC(unit, thd_sel_mem)[i],
    670                                       INVALIDr, thd_sel_field, granularity, i);
    671                 }
    672             }
    673 
    674             /*Threshold profile info count and Resource allocation */
    675             prof_reg = MMU_THDI_BST_PG_HDRM_PROFILEr;
    676             prof_field = BST_PG_HDRM_THRESHf;
    677             _BCM_BST_PROFILE_INFO(pres, INVALIDm, prof_reg, prof_field);
    678             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count, "bst pg hdrm");
    679             for(i = 0; i < _TH3_MMU_NUM_PG; i++) {
    680                 _BCM_BST_STAT_FIELD_INFO(pres, pg_hdrm_fields[i], i);
    681                 _BCM_BST_THD_FIELD_INFO(pres, pg_hdrm_sel_fields[i], i);
    682             }
    683             /* Stat info count and Resource allocation */
    684             /* Stat res - THDI_PORT_PG_BST : (Num Ports (20/pipe) * 8 pipes) * 8(PGs) */
    685             total_stat_count = total_thd_count;
    686             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    687             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count, "bst pg hdrm");
    688             pres->index_min = 0;
    689             pres->index_max = total_stat_count - 1;
    690             break;
    691         case bcmBstStatIdEgrPool:
    692             pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdEgrPool);
    693             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    694             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_RES_EGR);
    695             pres->num_instance = NUM_ITM(unit);
    696             pres->num_field = 1;
    697             idx_count = _TH3_MMU_NUM_POOL;
    698             pres->threshold_adj = -1;
    699             stat_mem = INVALIDm;
    700             stat_reg = MMU_THDO_UC_POOL_BST_COUNTr;
    701             stat_field = BST_COUNTf;
    702 
    703             /* Threshold info count and Resource allocation */
    704             granularity = 1;
    705             total_thd_count = idx_count;
    706             thd_reg = MMU_THDO_SP_SHR_BST_THRESHOLDr;
    707             thd_field = BST_STATf;
    708             _BCM_BST_THRESHOLD_INFO(pres, INVALIDm, thd_reg,
    709                                                 thd_field, granularity);
    710             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count,
    711                                                             "bst egr pool");
    712             /* Stat info count and Resource allocation */
    713             total_stat_count = NUM_ITM(unit) * total_thd_count;
    714             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    715             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count,
    716                                                             "bst egr pool");
    717             pres->index_min = 0;
    718             pres->index_max = total_stat_count - 1;
    719 
    720             break;
    721         case bcmBstStatIdEgrMCastPool:
    722             pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdEgrMCastPool);
    723             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    724             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_RES_EGR);
    725             pres->num_instance = NUM_ITM(unit);
    726             pres->num_field = 1;
    727             idx_count = _TH3_MMU_NUM_POOL;
    728             pres->threshold_adj = -1;
    729             stat_mem = INVALIDm;
    730             stat_reg = MMU_THDO_MC_POOL_BST_COUNTr;
    731             stat_field = BST_COUNTf;
    732 
    733             /* Threshold info count and Resource allocation */
    734             granularity = 1;
    735             total_thd_count = idx_count;
    736             thd_reg = MMU_THDO_MC_CQE_SP_BST_THRESHOLDr;
    737             thd_field = BST_STATf;
    738             _BCM_BST_THRESHOLD_INFO(pres, INVALIDm, thd_reg,
    739                                                 thd_field, granularity);
    740             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count,
    741                                                             "bst egr mcpool");
    742             /* Stat info count and Resource allocation */
    743             total_stat_count =  NUM_ITM(unit) * total_thd_count;
    744             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    745             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count,
    746                                                             "bst egr mcpool");
    747             pres->index_min = 0;
    748             pres->index_max = total_stat_count - 1;
    749             break;
    750         case bcmBstStatIdEgrPortPoolSharedMcast:
    751              pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdEgrPortPoolSharedMcast);
    752             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    753             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID |
    754                                              _BCM_BST_CMN_RES_F_RES_EGR);
    755             _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_ALL(unit));
    756             pres->num_instance = NUM_ITM(unit);
    757             pres->num_field = 1;
    758             stat_mem = MMU_THDO_BST_SHARED_PORTSP_MCm;
    759             stat_reg = INVALIDr;
    760             stat_field = SHARED_COUNTf;
    761 
    762             /* Get the mem attributes(Max idx) from the first child,
    763              * which could be used for other instances.
    764              * Note: In TH3, ITM 0 instance valid for all memories(Ing/Egr).
    765              */
    766             child_mem = SOC_MEM_UNIQUE_ACC_ITM(unit, stat_mem, 0);
    767             idx_count = soc_mem_index_max(unit, child_mem) + 1;
    768 
    769             /* Threshold info count and Resource allocation */
    770             granularity = 1;
    771             total_thd_count = idx_count;
    772             thd_sel_mem = MMU_THDO_CONFIG_PORTSP_MCm;
    773             thd_sel_field = BST_PORTSP_WM_MC_CQE_THRESHOLD_SELf;
    774 
    775             _BCM_BST_THRESHOLD_INFO(pres, thd_sel_mem,
    776                                     INVALIDr, thd_sel_field, granularity);
    777 
    778 
    779             prof_reg = MMU_THDO_MC_CQE_PRT_SP_BST_THRESHOLDr;
    780             prof_field = BST_STATf;
    781             _BCM_BST_PROFILE_INFO(pres, INVALIDm, prof_reg, prof_field);
    782             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count,
    783                                              "bst egr port pool shared mcast");
    784             /* Stat info count and Resource allocation */
    785             total_stat_count = NUM_ITM(unit) * total_thd_count;
    786             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    787             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count,
    788                                         "bst egr port pool shared mcast");
    789             pres->index_min = 0;
    790             pres->index_max = total_stat_count - 1;
    791             break;
    792         case bcmBstStatIdEgrPortPoolSharedUcast:
    793             pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdEgrPortPoolSharedUcast);
    794             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    795             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID |
    796                                              _BCM_BST_CMN_RES_F_RES_EGR);
    797             _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_PORT_ALL(unit));
    798             pres->num_instance = NUM_ITM(unit);
    799             stat_mem = MMU_THDO_BST_SHARED_PORTm;
    800             stat_reg = INVALIDr;
    801             stat_field = INVALIDf;
    802 
    803             /* Get the mem attributes(Max idx) from the first child,
    804              * which could be used for other instances.
    805              * Note: In TH3, ITM 0 instance valid for all memories(Ing/Egr).
    806              */
    807             child_mem = SOC_MEM_UNIQUE_ACC_ITM(unit, stat_mem, 0);
    808             idx_count = soc_mem_index_max(unit, child_mem) + 1;
    809 
    810             /* Threshold info count and Resource allocation */
    811             granularity = 1;
    812             total_thd_count = idx_count * _TH3_MMU_NUM_POOL;
    813             thd_sel_mem = MMU_THDO_CONFIG_PORT_UC0m;
    814             thd_sel_field = INVALIDf;
    815             _BCM_BST_THRESHOLD_INFO(pres, thd_sel_mem,
    816                                         INVALIDr, thd_sel_field, granularity);
    817 
    818             prof_reg = MMU_THDO_PRT_SP_SHR_BST_THRESHOLDr;
    819             prof_field = BST_STATf;
    820             for(i = 0; i < _TH3_MMU_NUM_POOL; i++) {
    821                 _BCM_BST_THD_FIELD_INFO(pres, uc_portsp_sel_fields[i], i);
    822                 _BCM_BST_STAT_FIELD_INFO(pres, uc_portsp_fields[i], i);
    823             }
    824             _BCM_BST_PROFILE_INFO(pres, INVALIDm, prof_reg, prof_field);
    825             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count,
    826                                              "bst egr port pool shared ucast");
    827             /* Stat info count and Resource allocation */
    828             total_stat_count = NUM_ITM(unit) * total_thd_count;
    829             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    830             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count,
    831                                         "bst egr port pool shared ucast");
    832             pres->index_min = 0;
    833             pres->index_max = total_stat_count - 1;
    834             break;
    835         case bcmBstStatIdQueueTotal:
    836             pres = _BCM_BST_RESOURCE(unit, bcmBstStatIdQueueTotal);
    837             _BCM_BST_STAT_THRESHOLD_INFO_INIT(pres);
    838             _BCM_BST_RESOURCE_FLAG_SET(pres, _BCM_BST_CMN_RES_F_PROFILEID |
    839                                              _BCM_BST_CMN_RES_F_RES_EGR);
    840             _BCM_BST_RESOURCE_PBMP_SET(pres, PBMP_PORT_ALL(unit));
    841             pres->num_instance = NUM_ITM(unit);
    842             pres->num_field = 1;
    843             stat_mem = MMU_THDO_BST_TOTAL_QUEUEm;
    844             stat_reg = INVALIDr;
    845             stat_field = BST_QUEUE_TOTAL_COUNTf;
    846 
    847             /* Get the mem attributes(Max idx) from the first child,
    848              * which could be used for other instances.
    849              * Note: In TH3, ITM 0 instance valid for all memories(Ing/Egr).
    850              */
    851             child_mem = SOC_MEM_UNIQUE_ACC_ITM(unit, stat_mem, 0);
    852             idx_count = soc_mem_index_max(unit, child_mem) + 1;
    853 
    854             /* Threshold info count and Resource allocation */
    855             granularity = 1;
    856             total_thd_count = idx_count;
    857             thd_sel_mem = MMU_THDO_QUEUE_CONFIGm;
    858             thd_sel_field = BST_Q_WM_TOTAL_THRESHOLD_SELf;
    859             _BCM_BST_THRESHOLD_INFO(pres, thd_sel_mem,
    860                                         INVALIDr, thd_sel_field, granularity);
    861 
    862 
    863             prof_field = BST_STATf;
    864             for(i = 0; i < _BCM_TH3_BST_Q_TYPE_COUNT; i++) {
    865                 prof_reg = q_thd_regs[i];
    866                 _BCM_BST_PROFILE_INFO_N(pres, INVALIDm, prof_reg,
    867                                                             prof_field, i);
    868 
    869             }
    870             pres->num_profile_reg = i;
    871             _BCM_BST_RESOURCE_THRESHOLD_INIT(pres, total_thd_count,
    872                                              "bst queue total use count");
    873             /* Stat info count and Resource allocation */
    874             total_stat_count = NUM_ITM(unit) * total_thd_count;
    875             _BCM_BST_STAT_INFO(pres, stat_mem, stat_reg, stat_field);
    876             _BCM_BST_RESOURCE_STAT_INIT(pres, total_stat_count,
    877                                         "bst egr port pool shared ucast");
    878             pres->index_min = 0;
    879             pres->index_max = total_stat_count - 1;
    880             break;
    881 
    882         default:
    883             return BCM_E_PARAM;
    884     }
    885     return BCM_E_NONE;
    886 }
    887 
    888 /*
    889  * Function:
    890  *    _bcm_th3_bst_control_set
    891  * Purpose:
    892  *   Set BST global control.
    893  * Parameters:
    894  *     unit       - (IN) unit number
    895  *     type  - (IN)  control type
    896  *     arg   - (IN)  control value
    897  *     operation   - (IN) operation origin, i.e. internal or external
    898  * Returns:
    899  *     BCM_E_XXX
    900  */
    901 
    902 STATIC int
    903 _bcm_th3_bst_control_set(int unit, bcm_switch_control_t type, int arg,
    904                         _bcm_bst_thread_oper_t operation)
    905 {
    906     if(arg < 0) {
    907         return BCM_E_PARAM;
    908     }
    909 
    910     switch (type) {
    911         case bcmSwitchBstEnable:
    912             BCM_IF_ERROR_RETURN
    913                 (_bcm_th3_bst_tracking_enable_set(unit, arg, operation));
    914             break;
    915         case bcmSwitchBstTrackingMode:
    916             BCM_IF_ERROR_RETURN(
    917                 _bcm_th3_bst_config_set(unit, arg,
    918                             _bcm_th3_bst_config_tracking_mode));
    919             break;
    920         case bcmSwitchBstSnapshotEnable:
    921             BCM_IF_ERROR_RETURN(
    922                 _bcm_th3_bst_config_set(unit, arg, _bcm_th3_bst_config_snapshot));
    923 
    924             break;
    925 
    926         default:
    927             return BCM_E_PARAM;
    928     }
    929     return BCM_E_NONE;
    930 }
    931 
    932 /*
    933  * Function:
    934  *    _bcm_th3_bst_control_get
    935  * Purpose:
    936  *   Get BST global control configuration.
    937  * Parameters:
    938  *     unit       - (IN) unit number
    939  *     type  - (IN)  control type
    940  *     arg   - (OUT)  control value
    941  * Returns:
    942  *     BCM_E_XXX
    943  */
    944 
    945 STATIC int
    946 _bcm_th3_bst_control_get(int unit, bcm_switch_control_t type, int *arg)
    947 {
    948     _bcm_bst_cmn_unit_info_t *bst_info;
    949     bst_info = _BCM_UNIT_BST_INFO(unit);
    950     if (!bst_info) {
    951         return BCM_E_INIT;
    952     }
    953 
    954     switch (type) {
    955         case bcmSwitchBstEnable:
    956             /*HW register MMU_GLBCFG_BST_TRACKING_ENABLE cannot be used to
    957              * retrieve this as the value can be modified by hardware when HW
    958              * snapshot action enable is set*/
    959             *arg = bst_info->bst_tracking_enable;
    960             break;
    961         case bcmSwitchBstTrackingMode:
    962             *arg = bst_info->track_mode;
    963             break;
    964         case bcmSwitchBstSnapshotEnable:
    965             *arg = bst_info->snapshot_mode;
    966             break;
    967         default:
    968             return BCM_E_PARAM;
    969     }
    970     return BCM_E_NONE;
    971 }
    972 
    973 
    974 /*
    975  * Function:
    976  *    _bcm_th3_bst_control_get
    977  * Purpose:
    978  *  Enable/disable BST HW interrupt.
    979  * Parameters:
    980  *     unit       - (IN) unit number
    981  *     enable  - (IN)  Enable config
    982  * Returns:
    983  *     BCM_E_XXX
    984  */
    985 
    986 STATIC int
    987 _bcm_bst_th3_intr_enable_set(int unit, int enable)
    988 {
    989     int i;
    990     uint32 rval;
    991     uint64 rval64;
    992     soc_reg_t reg = INVALIDr;
    993     soc_reg_t regs_intr[_BCM_TH3_BST_MODULE_COUNT] =
    994                         {MMU_THDO_BST_CPU_INT_ENr, MMU_THDI_CPU_INT_ENr,
    995                              MMU_CFAP_INT_ENr, MMU_THDR_QE_CPU_INT_ENr};
    996     soc_field_t fields_intr[_BCM_TH3_BST_MODULE_COUNT] =
    997                                     {BSTf, BST_TRIGf, BST_TRIGf, BSTf};
    998 
    999     if (!soc_property_get(unit, spn_POLLED_IRQ_MODE, 0)) {
   1000         /* Enable interrupt at base level module THDI/THDO/THDR/CFAP */
   1001         for(i = _BCM_TH3_BST_MODULE_THDO; i < _BCM_TH3_BST_MODULE_COUNT; i++) {
   1002             rval = 0;
   1003             reg = regs_intr[i];
   1004             if(reg == MMU_CFAP_INT_ENr) {
   1005                 SOC_IF_ERROR_RETURN(
   1006                     soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64));
   1007                 soc_reg64_field32_set(unit, reg, &rval64,
   1008                                                 fields_intr[i], enable);
   1009                 SOC_IF_ERROR_RETURN(
   1010                     soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval64));
   1011                 continue;
   1012             };
   1013             SOC_IF_ERROR_RETURN(
   1014                     soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
   1015             soc_reg_field_set(unit, reg, &rval, fields_intr[i], enable);
   1016             SOC_IF_ERROR_RETURN(
   1017                     soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
   1018         }
   1019     }
   1020     return BCM_E_NONE;
   1021 }
   1022 
   1023 STATIC int
   1024 _bcm_th3_set_hw_intr_cb(int unit)
   1025 {
   1026     BCM_IF_ERROR_RETURN(soc_th3_set_bst_callback(unit, &_bcm_bst_hw_event_cb));
   1027     return BCM_E_NONE;
   1028 }
   1029 
   1030 
   1031 STATIC int
   1032 _bcm_bst_th3_intr_to_resources(int unit, uint32 *flags)
   1033 {
   1034     uint32 flags_tr = 0;
   1035     uint32 inst, itm_map, pipe_map;
   1036     uint32 fval = 0;
   1037     uint32 rval, rval32_type, rval32_status;
   1038     int index[_bcmResourceMaxCount] = {-1};
   1039     int res[_bcmResourceMaxCount] = {-1}, res_ct = 0;
   1040     int bid_detect[_bcmResourceMaxCount] = {0};
   1041     soc_field_t fld = INVALIDf;
   1042     soc_reg_t reg_type = INVALIDr, reg_status = INVALIDr;
   1043     int i, pipe, itm = 0;
   1044     soc_info_t *si;
   1045 
   1046     si = &SOC_INFO(unit);
   1047     _bcm_bst_th3_intr_enable_set(unit, 0);
   1048     LOG_VERBOSE(BSL_LS_BCM_COSQ,
   1049                 (BSL_META_U(unit,
   1050                             "BST interrupt handler: unit=%d flags=0x%x\n"),
   1051                  unit, *flags));
   1052     itm_map = si->itm_map;
   1053     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   1054 
   1055     /* _bcmResourceDevice */
   1056     BCM_IF_ERROR_RETURN(READ_MMU_CFAP_BSTSTATr(unit, &rval));
   1057     if (soc_reg_field_get(unit, MMU_CFAP_BSTSTATr, rval, CNTf)) {
   1058         if (SOC_REG_IS_VALID(unit, MMU_CFAP_INT_STATr)) {
   1059             /* For CFAP, it use MMU_CFAP_INT_STATr to indicate the bst
   1060              * interruptbut not use a trigger status register.
   1061              * MMU_CFAP_INT_STATr would be cleared in SER handler, so
   1062              * we check _bcmResourceDevice every time here. */
   1063             index[res_ct] = 0;
   1064             res[res_ct++] = _bcmResourceDevice;
   1065         }
   1066     }
   1067 
   1068     /* THDI Status/Triggers per-pipe */
   1069     reg_type = MMU_THDI_BST_TRIGGER_STATUS_TYPEr;
   1070     reg_status = THDI_BST_TRIGGER_STATUS_32r;
   1071     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   1072         if (!(pipe_map & (1U << pipe))) {
   1073             continue;
   1074         }
   1075         inst = pipe | SOC_REG_ADDR_INSTANCE_MASK;
   1076         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg_type, inst, 0, &rval32_type));
   1077         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg_status, inst, 0, &rval32_status));
   1078 
   1079         /* _bcmResourceIngPool */
   1080         fval = soc_reg_field_get(unit, reg_type, rval32_type, SP_SHARED_TRIGGERf);
   1081         if (fval && !bid_detect[_bcmResourceIngPool]) {
   1082             fld = SP_SHARED_TRIGGER_STATUSf;
   1083             index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld);
   1084             res[res_ct++] = _bcmResourceIngPool;
   1085             bid_detect[_bcmResourceIngPool] = 1;
   1086         }
   1087 
   1088         /* _bcmResourcePortPool */
   1089         fval = soc_reg_field_get(unit, reg_type, rval32_type,
   1090                                  PORTSP_SHARED_TRIGGERf);
   1091         if (fval && !bid_detect[_bcmResourcePortPool]) {
   1092             fld = PORTSP_SHARED_TRIGGER_STATUSf;
   1093             index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld);
   1094             res[res_ct++] = _bcmResourcePortPool;
   1095             bid_detect[_bcmResourcePortPool] = 1;
   1096         }
   1097 
   1098         /* _bcmResourcePriGroupShared */
   1099         fval = soc_reg_field_get(unit, reg_type, rval32_type,
   1100                                  PG_SHARED_TRIGGERf);
   1101         if (fval && !bid_detect[_bcmResourcePriGroupShared]) {
   1102             fld = PG_SHARED_TRIGGER_STATUSf;
   1103             index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld);
   1104             res[res_ct++] = _bcmResourcePriGroupShared;
   1105             bid_detect[_bcmResourcePriGroupShared] = 1;
   1106         }
   1107 
   1108         /* _bcmResourcePriGroupHeadroom */
   1109         fval = soc_reg_field_get(unit, reg_type, rval32_type,
   1110                                  PG_HDRM_TRIGGERf);
   1111 
   1112         if (fval && !bid_detect[_bcmResourcePriGroupHeadroom]) {
   1113             fld = PG_HDRM_TRIGGER_STATUSf;
   1114             index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld);
   1115             res[res_ct++] = _bcmResourcePriGroupHeadroom;
   1116             bid_detect[_bcmResourcePriGroupHeadroom] = 1;
   1117         }
   1118 
   1119         /* _bcmResourceHeadroomPool */
   1120         fval = soc_reg_field_get(unit, reg_type, rval32_type,
   1121                                  HEADROOM_POOL_TRIGGERf);
   1122 
   1123         if (fval && !bid_detect[_bcmResourceHeadroomPool]) {
   1124             fld = HEADROOM_POOL_TRIGGER_STATUSf;
   1125             index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld);
   1126             res[res_ct++] = _bcmResourceHeadroomPool;
   1127             bid_detect[_bcmResourceHeadroomPool] = 1;
   1128         }
   1129         rval32_type = 0;
   1130         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg_type, inst, 0, rval32_type));
   1131         rval32_status = 0;
   1132         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg_status, inst, 0, rval32_status));
   1133     }
   1134 
   1135 
   1136     /* THDO Status/Triggers */
   1137     /* MC egr pool and MC egr port-pool ID are stored in reg_status,
   1138      * the rest of info is stored in reg_type
   1139     */
   1140     reg_type = MMU_THDO_BST_STATr;
   1141     reg_status = MMU_THDO_BST_STAT1r;
   1142     rval = 0;
   1143     for (itm = 0; itm < NUM_ITM(unit); itm++) {
   1144         if (!(itm_map & (1U << itm))) {
   1145             continue;
   1146         }
   1147         inst = itm | SOC_REG_ADDR_INSTANCE_MASK;
   1148         BCM_IF_ERROR_RETURN
   1149             (soc_reg32_get(unit, reg_type, inst, 0, &rval32_type));
   1150         BCM_IF_ERROR_RETURN(
   1151                 soc_reg32_get(unit, reg_status, inst, 0, &rval32_status));
   1152         /* _bcmResourceEgrPool */
   1153         fval = soc_reg_field_get(unit, reg_type, rval32_type,
   1154                                      MMU_THDO_SP_SHR_BST_TRIGf);
   1155 
   1156         if (fval && !bid_detect[_bcmResourceEgrPool]) {
   1157             fld = MMU_THDO_SP_SHR_BST_IDf;
   1158             index[res_ct] = soc_reg_field_get(unit, reg_type, rval32_type, fld);
   1159             res[res_ct++] = _bcmResourceEgrPool;
   1160             bid_detect[_bcmResourceEgrPool] = 1;
   1161         }
   1162 
   1163         /* _bcmResourceEgrMCastPool */
   1164         fval = soc_reg_field_get(unit, reg_type, rval32_type,
   1165                                      MMU_THDO_MC_CQE_SP_BST_TRIGf);
   1166 
   1167         if (fval && !bid_detect[_bcmResourceEgrMCastPool]) {
   1168             fld = MMU_THDO_MC_CQE_SP_BST_IDf;
   1169             index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld);
   1170             res[res_ct++] = _bcmResourceEgrMCastPool;
   1171             bid_detect[_bcmResourceEgrMCastPool] = 1;
   1172         }
   1173 
   1174         /* _bcmResourceBstStatIdQueueTotal */
   1175         fval = soc_reg_field_get(unit, reg_type, rval32_type,
   1176                                      MMU_THDO_QUE_TOT_BST_TRIGf);
   1177 
   1178         if (fval && !bid_detect[_bcmResourceBstStatIdQueueTotal]) {
   1179             fld = MMU_THDO_QUE_TOT_BST_IDf;
   1180             index[res_ct] = soc_reg_field_get(unit, reg_type, rval32_type, fld);
   1181             res[res_ct++] = _bcmResourceBstStatIdQueueTotal;
   1182             bid_detect[_bcmResourceBstStatIdQueueTotal] = 1;
   1183         }
   1184 
   1185         /* _bcmResourceEgrPortPoolSharedMcast*/
   1186         fval = soc_reg_field_get(unit, reg_type, rval32_type,
   1187                                      MMU_THDO_MC_CQE_PRT_SP_BST_TRIGf);
   1188 
   1189         if (fval && !bid_detect[_bcmResourceEgrPortPoolSharedMcast]) {
   1190             fld = MMU_THDO_MC_CQE_PRT_SP_BST_IDf;
   1191             index[res_ct] = soc_reg_field_get(unit, reg_status, rval32_status, fld);
   1192             res[res_ct++] = _bcmResourceEgrPortPoolSharedMcast;
   1193             bid_detect[_bcmResourceEgrPortPoolSharedMcast] = 1;
   1194         }
   1195 
   1196         /* _bcmResourceEgrPortPoolSharedUcast*/
   1197         fval = soc_reg_field_get(unit, reg_type, rval32_type,
   1198                                      MMU_THDO_PRT_SP_SHR_BST_TRIGf);
   1199         if (fval && !bid_detect[_bcmResourceEgrPortPoolSharedUcast]) {
   1200             fld = MMU_THDO_PRT_SP_SHR_BST_IDf;
   1201             index[res_ct] = soc_reg_field_get(unit, reg_type, rval32_type, fld);
   1202             res[res_ct++] = _bcmResourceEgrPortPoolSharedUcast;
   1203             bid_detect[_bcmResourceEgrPortPoolSharedUcast] = 1;
   1204         }
   1205         rval32_type = 0;
   1206         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg_type, inst, 0, rval32_type));
   1207         rval32_status = 0;
   1208         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg_status, inst, 0, rval32_status));
   1209     }
   1210     if (res_ct == 0) {
   1211         _bcm_bst_th3_intr_enable_set(unit, 1);
   1212         /* No resource to fetch */
   1213         return BCM_E_NONE;
   1214     }
   1215 
   1216     for (i = 0; i < res_ct; i++) {
   1217         BCM_IF_ERROR_RETURN(
   1218             _bcm_bst_th3_sync_hw_snapshot(unit, res[i], -1, index[i]));
   1219     }
   1220 
   1221     *flags = flags_tr;
   1222     _bcm_bst_th3_intr_enable_set(unit, 1);
   1223     return BCM_E_NONE;
   1224 }
   1225 
   1226 
   1227 /*
   1228  * Function:
   1229  *   bcm_bst_th3_hw_stat_clear
   1230  * Purpose:
   1231  *  Clear specified BST stat in HW.
   1232  * Parameters:
   1233  *     unit       - (IN) unit number
   1234  *     resInfo  - (IN)  resource info sturcture.
   1235  *     bid   - (IN) BST stat ID.
   1236  *     buffer - (IN) buffer(ITM) id.
   1237  *     port   - (IN) local port number.
   1238  *     index  - (IN) stat index
   1239  * Returns:
   1240  *     BCM_E_XXX
   1241  */
   1242 
   1243 int
   1244 bcm_bst_th3_hw_stat_clear(int unit, _bcm_bst_resource_info_t *resInfo,
   1245                 bcm_bst_stat_id_t bid, bcm_cosq_buffer_id_t buffer,
   1246                                                     int port, int index,
   1247                                                     int cosq)
   1248 {
   1249     _bcm_bst_cmn_unit_info_t *bst_info;
   1250     int rv = BCM_E_NONE;
   1251     uint32 rval;
   1252     soc_mem_t base_mem = INVALIDm, mem = INVALIDm;
   1253     soc_reg_t reg;
   1254     int min_hw_idx, max_hw_idx, idx;
   1255     int inst, stats_per_inst;
   1256     int num_entries, mem_wsz;
   1257     int num_field, field_idx;
   1258     void *pentry;
   1259     char *dmabuf;
   1260     uint32 mmu_inst_map = 0;
   1261     int field_ids[_TH3_MMU_NUM_PG];
   1262     int num, hw_idx;
   1263     int enable = 0;
   1264 
   1265     if (bid < _BCM_BST_RESOURCE_MIN || bid >= _BCM_BST_RESOURCE_MAX) {
   1266         return BCM_E_PARAM;
   1267     }
   1268 
   1269     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   1270         return BCM_E_INIT;
   1271     }
   1272     if (bst_info->port_to_mmu_inst_map) {
   1273         (void) bst_info->port_to_mmu_inst_map(unit, bid, port,
   1274             &mmu_inst_map);
   1275     }
   1276 
   1277     if (bst_info->control_get) {
   1278         bst_info->control_get(unit, bcmSwitchBstEnable, &enable);
   1279     }
   1280     if (enable && bst_info->control_set) {
   1281         bst_info->control_set(unit, bcmSwitchBstEnable, 0,
   1282                 _bcmBstThreadOperInternal);
   1283     }
   1284 
   1285     if (!mmu_inst_map) {
   1286         rv = BCM_E_PARAM;
   1287         goto restore;
   1288     }
   1289 
   1290     if (index == -1) {
   1291         min_hw_idx = resInfo->index_min;
   1292         max_hw_idx = ((resInfo->index_max + 1) / resInfo->num_instance) - 1;
   1293     } else {
   1294         min_hw_idx = max_hw_idx = index;
   1295     }
   1296 
   1297     for (inst = 0; inst < resInfo->num_instance; inst++) {
   1298         if (!(mmu_inst_map & (1 << inst))) {
   1299             continue;
   1300         }
   1301         if ((base_mem = resInfo->stat_mem[0]) != INVALIDm) {
   1302             /* All BST memories are either IPIPE based or ITM based in TH3*/
   1303             if((resInfo->flags & _BCM_BST_CMN_RES_F_PIPED)) {
   1304                 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, inst);
   1305             } else {
   1306                 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, inst);
   1307             }
   1308             if(mem == INVALIDm) {
   1309                 rv = BCM_E_INTERNAL;
   1310                 goto restore;
   1311             }
   1312 
   1313             if (index == -1) {
   1314                 /* clear all entries in the memory */
   1315                 num_entries = soc_mem_index_count(unit, mem);
   1316                 mem_wsz = sizeof(uint32) * soc_mem_entry_words(unit, mem);
   1317 
   1318                 dmabuf = soc_cm_salloc(unit, num_entries * mem_wsz, "bst dmabuf");
   1319                 if (dmabuf == NULL) {
   1320                     rv = BCM_E_MEMORY;
   1321                     goto restore;
   1322                 }
   1323 
   1324                 if (soc_mem_read_range(unit, mem, MEM_BLOCK_ALL,
   1325                                         soc_mem_index_min(unit, mem),
   1326                                         soc_mem_index_max(unit, mem),
   1327                                         dmabuf)) {
   1328                     soc_cm_sfree(unit, dmabuf);
   1329                     rv = BCM_E_INTERNAL;
   1330                     goto restore;
   1331                 }
   1332 
   1333                 /* Clear stat counter if requested */
   1334                 for (idx = min_hw_idx; idx <= max_hw_idx; idx++) {
   1335                     if (resInfo->stat_field != INVALIDf) {
   1336                         pentry = soc_mem_table_idx_to_pointer(unit, mem, void*,
   1337                                                           dmabuf, idx);
   1338                         soc_mem_field32_set(unit, mem, pentry,
   1339                                 resInfo->stat_field, 0);
   1340                     } else {
   1341                         /* Multiple fields case */
   1342                         num_field = resInfo->num_field;
   1343                         hw_idx = idx / num_field;
   1344                         pentry = soc_mem_table_idx_to_pointer(unit, mem, void*,
   1345                                                           dmabuf, hw_idx);
   1346                         for (field_idx = 0; field_idx < num_field; field_idx++)
   1347                             {
   1348                                  soc_mem_field32_set(unit, mem, pentry,
   1349                                    resInfo->stat_fields[field_idx], 0);
   1350                             }
   1351                     }
   1352                 }
   1353 
   1354                 if (soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
   1355                                         soc_mem_index_min(unit, mem),
   1356                                         soc_mem_index_max(unit, mem),
   1357                                         dmabuf)) {
   1358                     soc_cm_sfree(unit, dmabuf);
   1359                     rv = BCM_E_INTERNAL;
   1360                     goto restore;
   1361                 }
   1362                 soc_cm_sfree(unit, dmabuf);
   1363             } else {
   1364                 /* Clear a specific index */
   1365                 uint32 entry[SOC_MAX_MEM_WORDS];
   1366 
   1367                 if(resInfo->stat_field != INVALIDf) {
   1368                     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, entry);
   1369                     if (rv) {
   1370                         goto restore;
   1371                     }
   1372                     soc_mem_field32_set(unit, mem, entry,
   1373                                         resInfo->stat_field, 0);
   1374                     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry);
   1375                     if (rv) {
   1376                         goto restore;
   1377                     }
   1378                 } else {
   1379                     /*multiple field case */
   1380                     num_field = resInfo->num_field;
   1381                     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, entry);
   1382                     if (rv) {
   1383                         goto restore;
   1384                     }
   1385                     rv = _bcm_bst_field_ids_retrieve(unit, bid, port, cosq,
   1386                                 field_ids, &num);
   1387                     if (rv) {
   1388                         goto restore;
   1389                     }
   1390                     if (num > num_field) {
   1391                         rv = BCM_E_INTERNAL;
   1392                         goto restore;
   1393                     }
   1394                     for (idx = 0; idx < num; idx++) {
   1395                         field_idx = field_ids[idx];
   1396                         soc_mem_field32_set(unit, mem, entry,
   1397                                    resInfo->stat_fields[field_idx], 0);
   1398                     }
   1399                     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry);
   1400                     if (rv) {
   1401                         goto restore;
   1402                     }
   1403 
   1404                 }
   1405             }
   1406 
   1407         } else if ((reg = resInfo->stat_reg[0]) != INVALIDr) {
   1408             int stat_idx = 0;
   1409             stats_per_inst = resInfo->num_stat_pp / resInfo->num_instance;
   1410 
   1411             /* Clear stat counters */
   1412             for (idx = min_hw_idx; idx <= max_hw_idx; idx++) {
   1413                 int l_inst;
   1414                 rval = 0;
   1415                 if (stats_per_inst) {
   1416                     l_inst = inst | SOC_REG_ADDR_INSTANCE_MASK;
   1417                     stat_idx = idx % stats_per_inst;
   1418                 } else {
   1419                     l_inst = REG_PORT_ANY;
   1420                     stat_idx = idx;
   1421                 }
   1422                 rv = soc_reg32_get(unit, reg, l_inst, stat_idx, &rval);
   1423                 if (rv) {
   1424                     goto restore;
   1425                 }
   1426                 /* no stat_reg has multiple fields in TH3*/
   1427                 soc_reg_field_set(unit, reg, &rval, resInfo->stat_field, 0);
   1428                 rv = soc_reg32_set(unit, reg, l_inst, stat_idx, rval);
   1429                 if (rv) {
   1430                     goto restore;
   1431                 }
   1432             }
   1433 
   1434         } /* if valid reg */
   1435     } /* for each instance */
   1436 
   1437 restore:
   1438     if (enable && bst_info->control_set) {
   1439         bst_info->control_set(unit, bcmSwitchBstEnable, enable,
   1440                 _bcmBstThreadOperInternal);
   1441     }
   1442 
   1443     return rv;
   1444 }
   1445 
   1446 /*
   1447  * Function:
   1448  *   _bcm_bst_th3_sync_resource_stat
   1449  * Purpose:
   1450  *  Sync a stat count at a specific index.
   1451  * Parameters:
   1452  *     unit       - (IN) unit number.
   1453  *     resInfo  - (IN)  resource info sturcture.
   1454  *     idx      - (IN) index of SW stat.
   1455  *     val  - (IN) value to sync.
   1456  * Returns:
   1457  *     BCM_E_XXX
   1458  */
   1459 STATIC int
   1460 _bcm_bst_th3_sync_resource_stat(
   1461     int unit,
   1462     _bcm_bst_resource_info_t *resInfo,
   1463     uint32 idx,
   1464     uint32  val)
   1465 {
   1466     _bcm_bst_cmn_unit_info_t *bst_info;
   1467     int hwm_mode;
   1468     if(resInfo == NULL) {
   1469         return BCM_E_PARAM;
   1470     }
   1471 
   1472     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   1473         return BCM_E_INIT;
   1474     }
   1475     if (idx > resInfo->index_max) {
   1476         return BCM_E_INTERNAL;
   1477     }
   1478 
   1479     hwm_mode = bst_info->track_mode;
   1480      if (hwm_mode) {
   1481         /* BST tracking is in Peak mode.
   1482          * Hence store the watermark value only.
   1483          */
   1484         if (resInfo->p_stat[idx] < val) {
   1485             resInfo->p_stat[idx] = val;
   1486         }
   1487     } else {
   1488         resInfo->p_stat[idx] = val;
   1489     }
   1490 
   1491     return BCM_E_NONE;
   1492 }
   1493 
   1494 /*
   1495  * Function:
   1496  *   _bcm_bst_th3_sync_hw_snapshot
   1497  * Purpose:
   1498  *  Sync all HW BST stat counts to SW copy for a given Stat ID.
   1499  * Parameters:
   1500  *     unit       - (IN) unit number.
   1501  *     bid  - (IN)  BST stat ID.
   1502  *     port, index  - (IN) not used in the function, the function signature
   1503  *           is defined in a way such that it is consistent with the function
   1504  *           pointer required by bst_info->hw_stat_snapshot
   1505  * Returns:
   1506  *     BCM_E_XXX
   1507  */
   1508 
   1509 int
   1510 _bcm_bst_th3_sync_hw_snapshot(int unit, bcm_bst_stat_id_t bid,
   1511                              int port, int index)
   1512 {
   1513     _bcm_bst_cmn_unit_info_t *bst_info;
   1514     _bcm_bst_resource_info_t *resInfo;
   1515     int num_entries, mem_wsz;
   1516     int i, j, idx, idx_offset, thd_idx;
   1517     int inst;
   1518     int stats_per_inst = 0; /* stats per mem instance(itm) */
   1519     void *pentry;
   1520     char *dmabuf;
   1521     uint32 rval, temp_val;
   1522     soc_mem_t mem, base_mem;
   1523     soc_reg_t reg;
   1524     bcm_gport_t gport;
   1525     bcm_cos_queue_t cosq;
   1526     uint32 pipe_map, itm_map;
   1527     soc_info_t *si = &SOC_INFO(unit);
   1528     int enable = 0;
   1529     int rv = BCM_E_NONE;
   1530 
   1531     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   1532         return BCM_E_INIT;
   1533     }
   1534     if (bst_info->control_get) {
   1535         bst_info->control_get(unit, bcmSwitchBstEnable, &enable);
   1536     }
   1537     if (enable && bst_info->control_set) {
   1538         bst_info->control_set(unit, bcmSwitchBstEnable, 0,
   1539                 _bcmBstThreadOperInternal);
   1540     }
   1541 
   1542     /* sync all the stats */
   1543     if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   1544         bid = bcmBstStatIdQueueTotal;
   1545     }
   1546     resInfo = _BCM_BST_RESOURCE(unit, bid);
   1547     if (resInfo == NULL) {
   1548         rv = BCM_E_PARAM;
   1549         goto restore;
   1550     }
   1551 
   1552     base_mem = resInfo->stat_mem[0];
   1553     reg = resInfo->stat_reg[0];
   1554 
   1555     /* get active pipe bitmap & itmbitmap */
   1556     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   1557     itm_map = si->itm_map;
   1558 
   1559     if (reg != INVALIDr) {
   1560         int stat_idx = 0;
   1561         stats_per_inst = resInfo->num_stat_pp / resInfo->num_instance;
   1562 
   1563         for (idx = 0; idx < resInfo->num_stat_pp; idx++) {
   1564             rval = 0;
   1565             if (stats_per_inst) {
   1566                 inst = idx / stats_per_inst;
   1567                 inst = inst | SOC_REG_ADDR_INSTANCE_MASK;
   1568                 stat_idx = idx % stats_per_inst;
   1569             } else {
   1570                 inst = REG_PORT_ANY;
   1571                 stat_idx = idx;
   1572                 stats_per_inst = 1;
   1573             }
   1574 
   1575             idx_offset = idx;
   1576             if(resInfo->stat_field != INVALIDf) {
   1577                 rv = soc_reg32_get(unit, reg, inst, stat_idx, &rval);
   1578                 if (rv) {
   1579                     goto restore;
   1580                 }
   1581                 temp_val = soc_reg_field_get(unit, reg, rval,
   1582                                                     resInfo->stat_field);
   1583                 rv = _bcm_bst_th3_sync_resource_stat(unit, resInfo,
   1584                                                     idx_offset, temp_val);
   1585                 if (rv) {
   1586                     goto restore;
   1587                 }
   1588             } else {
   1589                 /* register have multiple fields*/
   1590                 rv = BCM_E_INTERNAL;
   1591                 goto restore;
   1592             }
   1593 
   1594             /* Check if there exists threshold for a resource
   1595              * continue if we don't have one */
   1596             if (resInfo->p_threshold == NULL) {
   1597                 continue;
   1598             }
   1599 
   1600             thd_idx = idx;
   1601             if ((bid != bcmBstStatIdDevice) &&
   1602                     (!(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED))) {
   1603                 /* Bids which have duplicate access */
   1604                 thd_idx = stat_idx;
   1605             }
   1606             /* coverity[copy_paste_error : FALSE] */
   1607             if (resInfo->p_threshold[thd_idx] &&
   1608                 (resInfo->p_stat[idx_offset] >=
   1609                  (resInfo->p_threshold[thd_idx] * resInfo->threshold_gran)
   1610                 )) {
   1611                 /* Generate SOC EVENT */
   1612                 if (bst_info->handlers.reverse_resolve_index) {
   1613                     /* reverse map the inedx to port/cos pair */
   1614                     bst_info->handlers.reverse_resolve_index(unit, bid,
   1615                                                              port, idx_offset,
   1616                                                              &gport, &cosq);
   1617                     soc_event_generate(unit, SOC_SWITCH_EVENT_MMU_BST_TRIGGER,
   1618                                        bid, gport, cosq);
   1619 
   1620                 }
   1621             }
   1622 
   1623         }
   1624     } else if (base_mem != INVALIDm) {
   1625         int min_idx = 0, max_idx = 0;
   1626         int instance_offset = 0; /* offset per pipe or per (ITM) */
   1627 
   1628         /* Get the mem attributes(Max idx) from the first child,
   1629          * which could be used for other instances.
   1630          * Note: In TH3, ITM 0/Pipe 0 instance valid for all memories(Ing/Egr).
   1631          */
   1632         if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) {
   1633 
   1634             mem = SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit, base_mem, 0, 0);
   1635         }else {
   1636             mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, 0);
   1637         }
   1638         if (mem == INVALIDm) {
   1639             rv = BCM_E_PARAM;
   1640             goto restore;
   1641         }
   1642         stats_per_inst = (resInfo->index_max + 1) / resInfo->num_instance;
   1643         min_idx = soc_mem_index_min(unit, mem);
   1644         max_idx = soc_mem_index_max(unit, mem);
   1645         num_entries = max_idx + 1;
   1646 
   1647         mem_wsz = sizeof(uint32) * soc_mem_entry_words(unit, mem);
   1648 
   1649         dmabuf = soc_cm_salloc(unit, num_entries * mem_wsz, "bst dmabuf");
   1650         if (dmabuf == NULL) {
   1651             rv = BCM_E_MEMORY;
   1652             goto restore;
   1653         }
   1654         /* num_instance is equal to the number of pipes if memory is per-pipe,
   1655          * or the number of ITMs otherwise*/
   1656         for (i = 0; i < resInfo->num_instance; i++) {
   1657             instance_offset = 0;
   1658             gport = BCM_GPORT_INVALID;
   1659             cosq = -1;
   1660             instance_offset = stats_per_inst * i;
   1661             if((resInfo->flags & _BCM_BST_CMN_RES_F_PIPED)) {
   1662                 if (!(pipe_map & (1 << i))) {
   1663                     continue;
   1664                 }
   1665                 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, i);
   1666 
   1667             } else {
   1668                 if (!(itm_map & (1 << i))) {
   1669                     continue;
   1670                 }
   1671                 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, i);
   1672             }
   1673             if(mem == INVALIDm) {
   1674                 rv = BCM_E_INTERNAL;
   1675                 goto restore;
   1676             }
   1677 
   1678             if (soc_mem_read_range(unit, mem, MEM_BLOCK_ALL,
   1679                                     min_idx, max_idx, dmabuf)) {
   1680                 soc_cm_sfree(unit, dmabuf);
   1681                 rv = BCM_E_INTERNAL;
   1682                 goto restore;
   1683             }
   1684 
   1685             for (idx = 0; idx <= max_idx; idx++) {
   1686                 idx_offset = idx + instance_offset;
   1687                 pentry = soc_mem_table_idx_to_pointer(unit, mem, void*,
   1688                                                       dmabuf,
   1689                                                       idx);
   1690                 if(resInfo->stat_field != INVALIDf) {
   1691                     idx_offset = idx + instance_offset;
   1692                     temp_val = soc_mem_field32_get(unit, mem, pentry,
   1693                                                         resInfo->stat_field);
   1694                     rv = _bcm_bst_th3_sync_resource_stat(unit, resInfo,
   1695                                                      idx_offset, temp_val);
   1696                     if (rv) {
   1697                         soc_cm_sfree(unit, dmabuf);
   1698                         goto restore;
   1699                     }
   1700 
   1701                     /* In TH3, stat count and thd count need not be same as in
   1702                      * previous chips(check init). This is due to different
   1703                      * AccType for Stat and Threshold.
   1704                      * Stats - usually NON-DUP Acc Type
   1705                      * Threshold - usually DUP Acc Type
   1706                      * Hence threshold index might only exist for 1 instance
   1707                      * and applicable to all.
   1708                      */
   1709                     thd_idx = idx_offset;
   1710                     if ((bid != bcmBstStatIdDevice) &&
   1711                             ((!(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED)))) {
   1712                         /* Bids which have duplicate access across ITM */
   1713                         thd_idx = idx_offset % stats_per_inst;
   1714                     }
   1715                     if (resInfo->p_threshold[thd_idx] &&
   1716                         (resInfo->p_stat[idx_offset] >=
   1717                          (resInfo->p_threshold[thd_idx]) * resInfo->threshold_gran)) {
   1718                         /* Generate SOC EVENT */
   1719                         if (bst_info->handlers.reverse_resolve_index) {
   1720                             /* reverse map the inedx to port/cos pair */
   1721                             bst_info->handlers.reverse_resolve_index
   1722                                            (unit, bid, port, thd_idx,
   1723                                                                  &gport, &cosq);
   1724                             soc_event_generate(unit, SOC_SWITCH_EVENT_MMU_BST_TRIGGER,
   1725                                                bid, gport, cosq);
   1726 
   1727                         }
   1728                     }
   1729                 } else {
   1730                     for(j = 0; j < resInfo->num_field; j++) {
   1731                         idx_offset = (idx * (resInfo->num_field))
   1732                                                     + instance_offset + j;
   1733                         temp_val = soc_mem_field32_get(unit, mem,
   1734                                             pentry, resInfo->stat_fields[j]);
   1735                         rv = _bcm_bst_th3_sync_resource_stat(unit, resInfo,
   1736                                                   idx_offset , temp_val);
   1737                         if (rv) {
   1738                             soc_cm_sfree(unit, dmabuf);
   1739                             goto restore;
   1740                         }
   1741                         /* In TH3, stat count and thd count need not be same as in
   1742                          * previous chips(check init). This is due to different
   1743                          * AccType for Stat and Threshold.
   1744                          * Stats - usually NON-DUP Acc Type
   1745                          * Threshold - usually DUP Acc Type
   1746                          * Hence threshold index might only exist for 1 instance
   1747                          * and applicable to all.
   1748                          */
   1749                         if (!(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED)) {
   1750                             thd_idx = (idx * resInfo->num_field) + j;
   1751                         } else {
   1752                             thd_idx = idx_offset;
   1753                         }
   1754                         if (resInfo->p_threshold[thd_idx] &&
   1755                             (resInfo->p_stat[idx_offset] >=
   1756                              (resInfo->p_threshold[thd_idx]) * resInfo->threshold_gran)) {
   1757                             /* Generate SOC EVENT */
   1758                             if (bst_info->handlers.reverse_resolve_index) {
   1759                                 /* reverse map the inedx to port/cos pair */
   1760                                 bst_info->handlers.reverse_resolve_index
   1761                                                (unit, bid, port, thd_idx,
   1762                                                                      &gport, &cosq);
   1763                                 soc_event_generate(unit, SOC_SWITCH_EVENT_MMU_BST_TRIGGER,
   1764                                                    bid, gport, cosq);
   1765 
   1766                             }
   1767                         }
   1768 
   1769                     }
   1770 
   1771                 }
   1772 
   1773             }
   1774 
   1775         }
   1776         soc_cm_sfree(unit, dmabuf);
   1777     }
   1778 restore:
   1779     if (enable && bst_info->control_set) {
   1780         bst_info->control_set(unit, bcmSwitchBstEnable, enable,
   1781                 _bcmBstThreadOperInternal);
   1782     }
   1783 
   1784     return rv;
   1785 }
   1786 
   1787 /*
   1788  * Function:
   1789  *   _bst_th3_port_to_mmu_inst_map_get
   1790  * Purpose:
   1791  *  Function to return the corresponding ITM instance for a given gport.
   1792  *  for per-pipe register/memory, instance -> pipe
   1793  *  otherwise, instance -> ITM
   1794  * Parameters:
   1795  *     unit       - (IN) unit number.
   1796  *     bid  - (IN)  BST stat ID.
   1797  *     gport - (IN) gport number.
   1798  *     mmu_inst_map  (OUT) instance map.
   1799  * Returns:
   1800  *     BCM_E_XXX
   1801  */
   1802 
   1803 int _bst_th3_port_to_mmu_inst_map_get(int unit, bcm_bst_stat_id_t bid,
   1804                                      bcm_gport_t gport, uint32 *mmu_inst_map)
   1805 {
   1806     soc_info_t *si = &SOC_INFO(unit);
   1807     _bcm_bst_resource_info_t *resInfo;
   1808     bcm_port_t local_port;
   1809     int pipe;
   1810     uint32 pipe_map;
   1811     resInfo = _BCM_BST_RESOURCE(unit, bid);
   1812     if ((resInfo == NULL) || (!_BCM_BST_RESOURCE_VALID(resInfo))) {
   1813         return BCM_E_PARAM;
   1814     }
   1815 
   1816     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   1817     if(gport == -1) {
   1818         if (resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) {
   1819             *mmu_inst_map = pipe_map;
   1820         } else {
   1821             *mmu_inst_map = si->itm_map;
   1822         }
   1823         return BCM_E_NONE;
   1824     }
   1825     BCM_IF_ERROR_RETURN(
   1826             _bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   1827 
   1828     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   1829 
   1830     if (resInfo->flags & _BCM_BST_CMN_RES_F_RES_ING) {
   1831         if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) {
   1832             *mmu_inst_map = 1U << pipe;
   1833             *mmu_inst_map &= pipe_map;
   1834         } else {
   1835             *mmu_inst_map = si->ipipe_itm_map[pipe];
   1836             *mmu_inst_map &= si->itm_map;
   1837         }
   1838     } else {
   1839         /* For Global and EGR resource, return all instances (ITMs)*/
   1840         *mmu_inst_map = si->itm_map;
   1841     }
   1842 
   1843     return BCM_E_NONE;
   1844 }
   1845 
   1846 
   1847 /*
   1848  * Function:
   1849  *   bcm_th3_cosq_bst_stat_clear
   1850  * Purpose:
   1851  *  Clear speficied BST stat.
   1852  * Parameters:
   1853  *     unit       - (IN) unit number.
   1854  *     gport - (IN) gport number.
   1855  *     cosq  - (IN) cosq number.
   1856  *     buffer - (IN) buffer(ITM) ID.
   1857  *     bid    - (IN) BST stat ID.
   1858  * Returns:
   1859  *     BCM_E_XXX
   1860  */
   1861 int
   1862 bcm_th3_cosq_bst_stat_clear(int unit, bcm_gport_t gport,
   1863                          bcm_cos_queue_t cosq, bcm_cosq_buffer_id_t buffer,
   1864                                                       bcm_bst_stat_id_t bid)
   1865 
   1866 {
   1867     _bcm_bst_cmn_unit_info_t *bst_info;
   1868     _bcm_bst_resource_info_t *resInfo;
   1869     int bcm_rv = BCM_E_NONE;
   1870     _bcm_bst_cb_ret_t rv;
   1871     void *cb_data = NULL;
   1872     int rcb = 0;
   1873     int start_hw_index = 0, end_hw_index = 0, pipe;
   1874     int hw_index;
   1875 
   1876     if (bid < _BCM_BST_RESOURCE_MIN || bid >= _BCM_BST_RESOURCE_MAX) {
   1877         return BCM_E_PARAM;
   1878     }
   1879     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   1880         return BCM_E_INIT;
   1881     }
   1882 
   1883     if (bst_info->handlers.resolve_index == NULL) {
   1884         return BCM_E_UNAVAIL;
   1885     }
   1886 
   1887     BCM_IF_ERROR_RETURN(
   1888             _bcm_th3_bst_bid_gport_cosq_param_check(unit, bid, gport, cosq));
   1889 
   1890     if (bcmBstStatIdUcast == bid || bcmBstStatIdMcast == bid) {
   1891         bid = bcmBstStatIdQueueTotal;
   1892     }
   1893     resInfo = _BCM_BST_RESOURCE(unit, bid);
   1894     if ((resInfo == NULL) || (!_BCM_BST_RESOURCE_VALID(resInfo))) {
   1895         return BCM_E_PARAM;
   1896     }
   1897 
   1898     sal_mutex_take(bst_info->bst_reslock, sal_mutex_FOREVER);
   1899     if (gport == -1) {
   1900         /* Clear all stat counters in the buffer*/
   1901         (void) bcm_bst_th3_hw_stat_clear(unit, resInfo, bid, buffer,
   1902                                                                 gport, -1, cosq);
   1903     } else {
   1904         /* Clear stat counter for given port, cos */
   1905         rv = bst_info->handlers.resolve_index(unit, gport, cosq, bid, &pipe,
   1906                             &start_hw_index, &end_hw_index, &rcb,
   1907                             &cb_data, &bcm_rv);
   1908         if (rv != _BCM_BST_RV_ERROR) {
   1909             for (hw_index = start_hw_index; hw_index <= end_hw_index; hw_index++)
   1910             {
   1911                 (void) bcm_bst_th3_hw_stat_clear(unit, resInfo, bid, buffer,
   1912                                                       gport, hw_index,
   1913                                                       cosq);
   1914             }
   1915         }
   1916     }
   1917 
   1918     if (gport == -1) {
   1919         bcm_port_t local_port;
   1920         PBMP_PORT_ITER(unit, local_port) {
   1921                 bcm_rv = bcm_bst_th3_sw_stat_clear(unit, local_port,
   1922                                                          cosq, buffer, bid);
   1923             if (BCM_FAILURE(bcm_rv)) {
   1924                 break;
   1925             }
   1926         }
   1927     } else {
   1928         {
   1929             bcm_rv = bcm_bst_th3_sw_stat_clear(unit, gport, cosq, buffer, bid);
   1930         }
   1931     }
   1932     sal_mutex_give(bst_info->bst_reslock);
   1933 
   1934     return bcm_rv;
   1935 
   1936 }
   1937 
   1938 /*
   1939  * Function:
   1940  *   bcm_th3_cosq_bst_stat_multi_get
   1941  * Purpose:
   1942  *  Get multiple BST stat counts.
   1943  * Parameters:
   1944  *     unit       - (IN) unit number.
   1945  *     gport - (IN) gport number.
   1946  *     cosq  - (IN) cosq number.
   1947  *     options - (IN) BST stat read options,
   1948  *                   used for setting clear-or-read FLAG.
   1949  *     max_values - (IN) size of BST stat ID array.
   1950  *     id_list    - (IN) BST stat ID array.
   1951  *     pvalues    - (OUT) BST stat count array.
   1952  * Returns:
   1953  *     BCM_E_XXX
   1954  */
   1955 int
   1956 bcm_th3_cosq_bst_stat_multi_get(int unit,
   1957                                bcm_gport_t gport,
   1958                                bcm_cos_queue_t cosq,
   1959                                uint32 options,
   1960                                int max_values,
   1961                                bcm_bst_stat_id_t *id_list,
   1962                                uint64 *pvalues)
   1963 {
   1964     int i;
   1965 
   1966     for (i = 0; i < max_values; i++) {
   1967 
   1968         BCM_IF_ERROR_RETURN(bcm_th3_cosq_bst_stat_get(unit, gport, cosq,
   1969                                     BCM_COSQ_BUFFER_ID_INVALID, id_list[i],
   1970                                                        options, &pvalues[i]));
   1971     }
   1972     return BCM_E_NONE;
   1973 }
   1974 
   1975 /*
   1976  * Function:
   1977  *   _bcm_th3_bst_sw_index_get
   1978  * Purpose:
   1979  *  Retrieve SW datastructure index corresponding to HW indes for a bid.
   1980  * Parameters:
   1981  *     unit       - (IN) unit number.
   1982  *     gport - (IN) gport number.
   1983  *     cosq  - (IN) cosq number.
   1984  *     bid   - (IN) BST ID.
   1985  *     hw_index     - (IN) Hardware index.
   1986  *     num_sw_entries - (OUT) Number of software entries corresponding to the
   1987  *     hardware entry
   1988  *     sw_index_arr  - (OUT) List of software indices corresponding to the HW
   1989  *     index
   1990  * Returns:
   1991  *     BCM_E_XXX
   1992  */
   1993 STATIC int
   1994 _bcm_th3_bst_sw_index_get (int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   1995         bcm_bst_stat_id_t bid, int hw_index, int *num_sw_entries, int *sw_index_arr)
   1996 {
   1997 
   1998     int cosq_loop_id;
   1999     int local_port, pool = -1;
   2000     int pool_start, pool_end;
   2001 
   2002     if ((num_sw_entries == NULL) || (sw_index_arr == NULL)) {
   2003         return BCM_E_PARAM;
   2004     }
   2005 
   2006     BCM_IF_ERROR_RETURN(
   2007             _bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   2008        switch(bid) {
   2009             case bcmBstStatIdEgrPortPoolSharedUcast:
   2010                 /* Retrieve the service pools mapped to given gport,cosq*/
   2011                 BCM_IF_ERROR_RETURN(
   2012                     _bcm_th3_cosq_egress_sp_get (unit, gport, cosq, &pool_start,
   2013                         &pool_end));
   2014                 *num_sw_entries = (pool_end - pool_start) + 1;
   2015                 cosq_loop_id = 0;
   2016                 for (pool = pool_start; pool <= pool_end; pool++) {
   2017                     sw_index_arr[cosq_loop_id] =
   2018                             (hw_index * _TH3_MMU_NUM_POOL) + pool;
   2019                     cosq_loop_id++;
   2020                 }
   2021                 break;
   2022             case bcmBstStatIdPriGroupShared:
   2023             case bcmBstStatIdPriGroupHeadroom:
   2024                 if (cosq == BCM_COS_INVALID) {
   2025                     *num_sw_entries = _TH3_MMU_NUM_PG;
   2026                     for (cosq_loop_id = 0; cosq_loop_id < _TH3_MMU_NUM_PG;
   2027                             cosq_loop_id++) {
   2028                         sw_index_arr[cosq_loop_id] =
   2029                             (hw_index * _TH3_MMU_NUM_PG) + cosq_loop_id;
   2030                     }
   2031                 } else {
   2032                     *num_sw_entries = 1;
   2033                     sw_index_arr[0] = (hw_index * _TH3_MMU_NUM_PG) + cosq;
   2034                 }
   2035                 break;
   2036             case bcmBstStatIdPortPool:
   2037                 if (cosq == BCM_COS_INVALID) {
   2038                     *num_sw_entries = _TH3_MMU_NUM_POOL;
   2039                     for (pool = 0; pool < _TH3_MMU_NUM_POOL;
   2040                             pool++) {
   2041                         sw_index_arr[pool] =
   2042                             (hw_index * _TH3_MMU_NUM_POOL) + pool;
   2043                     }
   2044 
   2045                 } else {
   2046                     *num_sw_entries = 1;
   2047                     /* Retrieve Pool mapped to given PG of the port*/
   2048                     BCM_IF_ERROR_RETURN(
   2049                             _bcm_th3_cosq_ingress_sp_get_by_pg(unit, local_port,
   2050                                                         cosq, &pool));
   2051                     sw_index_arr[0] = (hw_index * _TH3_MMU_NUM_POOL) + pool;
   2052                 }
   2053                 break;
   2054             default:
   2055                 *num_sw_entries = 1;
   2056                 sw_index_arr[0] = hw_index;
   2057                 break;
   2058         }
   2059     return BCM_E_NONE;
   2060 }
   2061 /*
   2062  * Function:
   2063  *   bcm_bst_th3_sw_stat_clear
   2064  * Purpose:
   2065  *  Clear specific BST stat counts in SW.
   2066  * Parameters:
   2067  *     unit       - (IN) unit number.
   2068  *     gport - (IN) gport number.
   2069  *     cosq  - (IN) cosq number.
   2070  *     buffer - (IN) ITM id.
   2071  *     bid    - (IN) BST stat ID.
   2072   * Returns:
   2073  *     BCM_E_XXX
   2074  */
   2075 
   2076 int
   2077 bcm_bst_th3_sw_stat_clear(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   2078                        bcm_cosq_buffer_id_t buffer, bcm_bst_stat_id_t bid)
   2079 {
   2080     _bcm_bst_cmn_unit_info_t *bst_info;
   2081     _bcm_bst_resource_info_t *resInfo;
   2082     _bcm_bst_cb_ret_t rv;
   2083     void *cb_data = NULL;
   2084     int bcm_rv, rcb = 0, index;
   2085     int start_hw_index = 0, end_hw_index = 0, pipe;
   2086     uint32 mmu_inst_map = 0;
   2087     int entries_per_inst, inst_offset, inst;
   2088     int num_sw_entries, loop_idx, sw_index;
   2089      /*max number of sw entries per hw index is 8 (number of PGS)*/
   2090     int sw_idx_arr[_TH3_MMU_NUM_PG] = {-1, -1, -1, -1, -1, -1, -1, -1};
   2091 
   2092     if (bid < _BCM_BST_RESOURCE_MIN || bid >= _BCM_BST_RESOURCE_MAX) {
   2093         return BCM_E_PARAM;
   2094     }
   2095 
   2096     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   2097         return BCM_E_INIT;
   2098     }
   2099 
   2100     if (bst_info->handlers.resolve_index == NULL) {
   2101         return BCM_E_UNAVAIL;
   2102     }
   2103 
   2104     do {
   2105         rv = bst_info->handlers.resolve_index(unit, gport, cosq, bid, &pipe,
   2106                     &start_hw_index, &end_hw_index, &rcb, &cb_data, &bcm_rv);
   2107         if (bcm_rv) {
   2108             return bcm_rv;
   2109         }
   2110 
   2111         if (bcmBstStatIdUcast == bid || bcmBstStatIdMcast == bid) {
   2112             bid = bcmBstStatIdQueueTotal;
   2113         }
   2114         resInfo = _BCM_BST_RESOURCE(unit, bid);
   2115         if (resInfo == NULL) {
   2116             return BCM_E_PARAM;
   2117         }
   2118 
   2119         entries_per_inst = (resInfo->index_max + 1) / resInfo->num_instance;
   2120         if (bst_info->port_to_mmu_inst_map) {
   2121             (void)bst_info->port_to_mmu_inst_map(unit, bid, gport,
   2122                                                  &mmu_inst_map);
   2123         }
   2124         if (!mmu_inst_map) {
   2125             return BCM_E_PARAM;
   2126         }
   2127 
   2128         /* When a resource has more than one instance, clear all
   2129          * applicable instances.
   2130          */
   2131         for (index = start_hw_index; index <= end_hw_index; index++) {
   2132             for (inst = 0; inst < resInfo->num_instance; inst++) {
   2133                 if (mmu_inst_map & (1 << inst)) {
   2134                     inst_offset = inst * entries_per_inst;
   2135                     /* retrieve the sw entries mapped to each hw index*/
   2136                     BCM_IF_ERROR_RETURN(
   2137                         _bcm_th3_bst_sw_index_get(unit, gport, cosq, bid,
   2138                              index, &num_sw_entries, sw_idx_arr));
   2139                     if (num_sw_entries > resInfo->num_field) {
   2140                         return BCM_E_INTERNAL;
   2141                     }
   2142                     for (loop_idx = 0; loop_idx < num_sw_entries; loop_idx++) {
   2143                         if (sw_idx_arr[loop_idx] != -1) {
   2144                             sw_index = sw_idx_arr[loop_idx] + inst_offset;
   2145                             if (sw_index > resInfo->index_max) {
   2146                                 return BCM_E_INTERNAL;
   2147                             }
   2148                             resInfo->p_stat[sw_index] = 0;
   2149                         }
   2150                     }
   2151                  }
   2152              }
   2153          }
   2154 
   2155     } while (rv == _BCM_BST_RV_RETRY);
   2156     return BCM_E_NONE;
   2157 }
   2158 
   2159 /*
   2160  * Function:
   2161  *   bcm_th3_cosq_bst_stat_get
   2162  * Purpose:
   2163  *  Get a specific BST stat count saved in SW.
   2164  * Parameters:
   2165  *     unit       - (IN) unit number.
   2166  *     gport - (IN) gport number.
   2167  *     cosq  - (IN) cosq number.
   2168  *     buffer - (IN) ITM id.
   2169  *     bid    - (IN) BST stat ID.
   2170  *     options - (IN) BST stat read options,
   2171  *                   used for setting clear-or-read FLAG.
   2172  *     pvalue    - (OUT) BST stat count.
   2173  * Returns:
   2174  *     BCM_E_XXX
   2175  */
   2176 int
   2177 bcm_th3_cosq_bst_stat_get(
   2178     int unit,
   2179     bcm_gport_t gport,
   2180     bcm_cos_queue_t cosq,
   2181     bcm_cosq_buffer_id_t buffer,
   2182     bcm_bst_stat_id_t bid,
   2183     uint32 options,
   2184     uint64 *pvalue)
   2185 
   2186 {
   2187     _bcm_bst_cmn_unit_info_t *bst_info;
   2188     _bcm_bst_resource_info_t *resInfo;
   2189     _bcm_bst_cb_ret_t rv;
   2190     void *cb_data = NULL;
   2191     int bcm_rv, rcb = 0, ii, inst, entries_per_inst;
   2192     int start_hw_index = 0, end_hw_index = 0, pipe = 0;
   2193     uint32 mmu_inst_map = 0;
   2194     int temp_stat , max_stat;
   2195     int num_sw_entries, loop_idx, sw_index;
   2196      /*max number of sw entries per hw index is 8 (number of PGS)*/
   2197     int sw_idx_arr[_TH3_MMU_NUM_PG] = {-1, -1, -1, -1, -1, -1, -1, -1};
   2198 
   2199 
   2200     if (bid < _BCM_BST_RESOURCE_MIN || bid >= _BCM_BST_RESOURCE_MAX) {
   2201         return BCM_E_PARAM;
   2202     }
   2203 
   2204     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   2205         return BCM_E_INIT;
   2206     }
   2207 
   2208     if (bst_info->handlers.resolve_index == NULL) {
   2209         return BCM_E_UNAVAIL;
   2210     }
   2211     COMPILER_64_ZERO(*pvalue);
   2212 
   2213     BCM_IF_ERROR_RETURN(
   2214             _bcm_th3_bst_bid_gport_cosq_param_check(unit, bid, gport, cosq));
   2215 
   2216     do {
   2217         rv = bst_info->handlers.resolve_index(unit, gport, cosq, bid, &pipe,
   2218                     &start_hw_index, &end_hw_index, &rcb, &cb_data, &bcm_rv);
   2219         if (bcm_rv) {
   2220             return bcm_rv;
   2221         }
   2222         if (bcmBstStatIdUcast == bid || bcmBstStatIdMcast == bid) {
   2223             bid = bcmBstStatIdQueueTotal;
   2224         }
   2225         resInfo = _BCM_BST_RESOURCE(unit, bid);
   2226         if ((resInfo == NULL) || (!_BCM_BST_RESOURCE_VALID(resInfo))) {
   2227             return BCM_E_PARAM;
   2228         }
   2229 
   2230         entries_per_inst = (resInfo->index_max + 1) / resInfo->num_instance;
   2231         if (bst_info->port_to_mmu_inst_map) {
   2232             (void) bst_info->port_to_mmu_inst_map(unit, bid, gport,
   2233                                                  &mmu_inst_map);
   2234         }
   2235         
   2236         if (!mmu_inst_map) {
   2237             return BCM_E_PARAM;
   2238         }
   2239         /* When a resource has more than one instance, find the max value
   2240          * of all applicable instances and return the Max value.
   2241          */
   2242         for (ii = start_hw_index; ii <= end_hw_index; ii++) {
   2243             temp_stat = 0;
   2244             max_stat = 0;
   2245             for (inst = 0; inst < resInfo->num_instance; inst++) {
   2246                 /* read only the specific buffer */
   2247                 if (mmu_inst_map & (1 << inst)) {
   2248                     /* retrieve the sw entries mapped to each hw index*/
   2249                     BCM_IF_ERROR_RETURN(
   2250                         _bcm_th3_bst_sw_index_get(unit, gport, cosq, bid,
   2251                              ii, &num_sw_entries, sw_idx_arr));
   2252                     if (num_sw_entries > resInfo->num_field) {
   2253                         return BCM_E_INTERNAL;
   2254                     }
   2255                     for (loop_idx = 0; loop_idx < num_sw_entries; loop_idx++) {
   2256                         if (sw_idx_arr[loop_idx] != -1) {
   2257                             sw_index = sw_idx_arr[loop_idx] +
   2258                                 (inst * entries_per_inst);
   2259                             temp_stat = resInfo->p_stat[sw_index];
   2260                             if (temp_stat > max_stat) {
   2261                                 max_stat = temp_stat;
   2262                             }
   2263                         }
   2264                     }
   2265                 }
   2266             }
   2267             COMPILER_64_ADD_32(*pvalue, max_stat);
   2268         }
   2269 
   2270     } while (rv == _BCM_BST_RV_RETRY);
   2271 
   2272     bcm_rv = BCM_E_NONE;
   2273 
   2274     if (options & BCM_COSQ_STAT_CLEAR) {
   2275         int need_hw_stat_clear = 1;
   2276         int mode = bst_info->track_mode;
   2277 
   2278         sal_mutex_take(bst_info->bst_reslock, sal_mutex_FOREVER);
   2279         if ((mode == 1) &&
   2280                 (bst_info->hw_cor_in_max_use_count == 1)) {
   2281             /* no need hw stat clear */
   2282             need_hw_stat_clear = 0;
   2283         }
   2284         if(need_hw_stat_clear) {
   2285              (void) bcm_bst_th3_hw_stat_clear(unit, resInfo, bid, buffer,
   2286                                                     gport, start_hw_index, cosq);
   2287         }
   2288         bcm_rv = bcm_bst_th3_sw_stat_clear(unit, gport, cosq, buffer, bid);
   2289         sal_mutex_give(bst_info->bst_reslock);
   2290     }
   2291 
   2292 
   2293     return bcm_rv;
   2294 }
   2295 
   2296 /*
   2297  * Function:
   2298  *   bcm_bst_th3_index_resolve
   2299  * Purpose:
   2300  *  Resolve the index range for a specific resource based on gport and cosq.
   2301  * Parameters:
   2302  *     unit       - (IN) unit number.
   2303  *     gport - (IN) gport number.
   2304  *     cosq  - (IN) cosq number.
   2305  *     bid    - (IN) BST stat ID.
   2306  *     pipe -  (OUT) pipe number.
   2307  *     start_hw_index - (OUT) start of index range.
   2308  *     end_hw_index - (OUT) end of index range.
   2309  *     rcb_data, cb_data    - (OUT) NOT used.
   2310  *     bcm_rv - (OUT) error status indicator.
   2311  * Returns:
   2312  *     _BCM_BST_RV_*
   2313  */
   2314 
   2315 _bcm_bst_cb_ret_t
   2316 bcm_bst_th3_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   2317                           bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index,
   2318                           int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv)
   2319 {
   2320     int local_port, mmu_lport, mmu_chip_port;
   2321     soc_info_t *si = &SOC_INFO(unit);
   2322 
   2323     *bcm_rv = _bcm_th3_cosq_localport_resolve(unit, gport, &local_port);
   2324 
   2325     if (BCM_E_NONE != (*bcm_rv)) {
   2326         return _BCM_BST_RV_ERROR;
   2327     }
   2328 
   2329     mmu_lport = soc_th3_mmu_local_port_num(unit, local_port);
   2330     mmu_chip_port = soc_th3_mmu_chip_port_num(unit, local_port);
   2331     *pipe = si->port_pipe[local_port];
   2332     switch (bid) {
   2333         case bcmBstStatIdDevice:
   2334             *start_hw_index = *end_hw_index = 0;
   2335             *bcm_rv = BCM_E_NONE;
   2336             return _BCM_BST_RV_OK;
   2337         case bcmBstStatIdHeadroomPool:
   2338             if(cosq == BCM_COS_INVALID) {
   2339                 *start_hw_index = 0;
   2340                 *end_hw_index = _TH3_MMU_NUM_POOL - 1;
   2341                 *bcm_rv = BCM_E_NONE;
   2342                 return _BCM_BST_RV_OK;
   2343             }
   2344             *bcm_rv = _bcm_th3_cosq_ingress_hdrm_pool_get_by_pg(unit, gport,
   2345                                                     cosq, start_hw_index);
   2346             *end_hw_index = *start_hw_index;
   2347             if(*bcm_rv != BCM_E_NONE) {
   2348                 return _BCM_BST_RV_ERROR;
   2349             }
   2350             break;
   2351         case bcmBstStatIdIngPool:
   2352             if(cosq == BCM_COS_INVALID) {
   2353                 *start_hw_index = 0;
   2354                 *end_hw_index = _TH3_MMU_NUM_POOL - 1;
   2355                 *bcm_rv = BCM_E_NONE;
   2356                 return _BCM_BST_RV_OK;
   2357             }
   2358             *bcm_rv = _bcm_th3_cosq_ingress_sp_get_by_pg(unit, gport,
   2359                                                     cosq, start_hw_index);
   2360             *end_hw_index = *start_hw_index;
   2361             if(*bcm_rv != BCM_E_NONE) {
   2362                 return _BCM_BST_RV_ERROR;
   2363             }
   2364             break;
   2365         case bcmBstStatIdPortPool:
   2366             *start_hw_index = mmu_lport;
   2367             *end_hw_index = mmu_lport;
   2368             break;
   2369         case bcmBstStatIdPriGroupShared:
   2370         case bcmBstStatIdPriGroupHeadroom:
   2371             *start_hw_index = mmu_lport;
   2372             *end_hw_index = mmu_lport;
   2373             break;
   2374         case bcmBstStatIdEgrPool:
   2375         case bcmBstStatIdEgrMCastPool:
   2376             if(_bcm_th3_cosq_egress_sp_get(unit, gport, cosq, start_hw_index,
   2377                                       end_hw_index)) {
   2378                 *bcm_rv = BCM_E_PARAM;
   2379                 return _BCM_BST_RV_ERROR;
   2380             }
   2381             *bcm_rv = BCM_E_NONE;
   2382             return _BCM_BST_RV_OK;
   2383         case bcmBstStatIdEgrPortPoolSharedMcast:
   2384             if(_bcm_th3_cosq_egress_sp_get(unit, gport, cosq, start_hw_index,
   2385                                       end_hw_index)) {
   2386                 *bcm_rv = BCM_E_PARAM;
   2387                 return _BCM_BST_RV_ERROR;
   2388             }
   2389             *start_hw_index = mmu_chip_port * _TH3_MMU_NUM_POOL + *start_hw_index;
   2390             *end_hw_index = mmu_chip_port * _TH3_MMU_NUM_POOL + *end_hw_index;
   2391             break;
   2392         case bcmBstStatIdEgrPortPoolSharedUcast:
   2393             *start_hw_index = mmu_chip_port;
   2394             *end_hw_index = mmu_chip_port;
   2395             break;
   2396         case bcmBstStatIdUcast:
   2397             if (IS_CPU_PORT(unit, local_port)) {
   2398                 *bcm_rv = BCM_E_PARAM;
   2399                 return _BCM_BST_RV_ERROR;
   2400             }
   2401             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   2402                 *bcm_rv = _bcm_th3_cosq_index_resolve(unit, gport, cosq,
   2403                                          _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   2404                                          &local_port, start_hw_index, NULL);
   2405                 if (cosq == -1) {
   2406                     *end_hw_index = *start_hw_index +
   2407                         si->port_num_uc_cosq[local_port] - 1;
   2408                 } else {
   2409                     *end_hw_index = *start_hw_index;
   2410                 }
   2411             } else {
   2412                 /*cosq ibput passed in {port, cosq} format is treated as MMUQ
   2413                  * number*/
   2414                 if (cosq == -1) {
   2415                     *start_hw_index = si->port_uc_cosq_base[local_port];
   2416                     *end_hw_index = *start_hw_index +
   2417                         si->port_num_uc_cosq[local_port] - 1;
   2418                 } else {
   2419                     *start_hw_index = si->port_uc_cosq_base[local_port] + cosq;
   2420                     *end_hw_index = *start_hw_index;
   2421                 }
   2422             }
   2423             if (*bcm_rv != BCM_E_NONE) {
   2424                 return _BCM_BST_RV_ERROR;
   2425             }
   2426             break;
   2427         case bcmBstStatIdMcast:
   2428             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2429                 *bcm_rv = _bcm_th3_cosq_index_resolve(unit, gport, cosq,
   2430                                          _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   2431                                          &local_port, start_hw_index, NULL);
   2432                 if (cosq == -1) {
   2433                     *end_hw_index = *start_hw_index +
   2434                         si->port_num_cosq[local_port] - 1;
   2435                 } else {
   2436                     *end_hw_index = *start_hw_index;
   2437                 }
   2438             } else {
   2439                 /*cosq input passed in {port, cosq} format is treated as MMUQ
   2440                  * number*/
   2441                 if (cosq == -1) {
   2442                     *start_hw_index = si->port_cosq_base[local_port];
   2443                     *end_hw_index = *start_hw_index +
   2444                         si->port_num_cosq[local_port] - 1;
   2445                 } else {
   2446                     *start_hw_index = si->port_cosq_base[local_port] +
   2447                         (cosq - si->port_num_uc_cosq[local_port]);
   2448                     *end_hw_index = *start_hw_index;
   2449                 }
   2450             }
   2451             if (*bcm_rv != BCM_E_NONE) {
   2452                 return _BCM_BST_RV_ERROR;
   2453             }
   2454             break;
   2455         case bcmBstStatIdQueueTotal:
   2456             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   2457                 *bcm_rv = _bcm_th3_cosq_index_resolve(unit, gport, cosq,
   2458                                          _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   2459                                          &local_port, start_hw_index, NULL);
   2460                 if (cosq == -1) {
   2461                     *end_hw_index = *start_hw_index + _bcm_th3_get_num_ucq(unit) - 1;
   2462                 } else {
   2463                     *end_hw_index = *start_hw_index;
   2464                 }
   2465             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2466                 *bcm_rv = _bcm_th3_cosq_index_resolve(unit, gport, cosq,
   2467                                          _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   2468                                          &local_port, start_hw_index, NULL);
   2469                 if (cosq == -1) {
   2470                     *end_hw_index = *start_hw_index + _bcm_th3_get_num_mcq(unit) - 1;
   2471                 } else {
   2472                     *end_hw_index = *start_hw_index;
   2473                 }
   2474 
   2475             } else {
   2476                 /*cosq ibput passed in {port, cosq} format is treated as MMUQ
   2477                  * number*/
   2478                 if (cosq == -1) {
   2479                     if (!IS_CPU_PORT(unit, local_port)) {
   2480                         *start_hw_index = si->port_uc_cosq_base[local_port];
   2481                         *end_hw_index = *start_hw_index +
   2482                             si->port_num_uc_cosq[local_port] +
   2483                             si->port_num_cosq[local_port] - 1;
   2484                     } else {
   2485                         *start_hw_index = si->port_cosq_base[local_port];
   2486                         *end_hw_index = *start_hw_index +
   2487                             si->port_num_cosq[local_port] - 1;
   2488                     }
   2489                 } else {
   2490                     if (!IS_CPU_PORT(unit, local_port)) {
   2491                         *start_hw_index = si->port_uc_cosq_base[local_port]
   2492                             + cosq;
   2493                     } else {
   2494                         *start_hw_index = si->port_cosq_base[local_port] + cosq;
   2495                     }
   2496                     *end_hw_index = *start_hw_index;
   2497                 }
   2498             }
   2499             if (*bcm_rv != BCM_E_NONE) {
   2500                 return _BCM_BST_RV_ERROR;
   2501             }
   2502             break;
   2503         default:
   2504             *bcm_rv = BCM_E_PARAM;
   2505             return _BCM_BST_RV_ERROR;
   2506     }
   2507     *bcm_rv = BCM_E_NONE;
   2508     return _BCM_BST_RV_OK;
   2509 }
   2510 
   2511 /*
   2512  * Function:
   2513  *   _bcm_th3_bst_profile_read_mem_range
   2514  * Purpose:
   2515  *  Set/Get a specific threshold profile/value memory range in HW for a given resource.
   2516  * Parameters:
   2517  *     unit   - (IN) unit number.
   2518  *     flags  - (IN) flags for read or write
   2519  *     bid    - (IN) BST stat ID.
   2520  *     inst   - (IN) inst number (pipe number or ITM number).
   2521  *     buffer - (OUT) memory buffer
   2522  * Returns:
   2523  *     _BCM_BST_RV_*
   2524  */
   2525 
   2526 STATIC int
   2527 _bcm_th3_bst_profile_mem_range(int unit, int flags, bcm_bst_stat_id_t bid,
   2528                                 int inst, uint8 **buffer)
   2529 {
   2530     _bcm_bst_resource_info_t *resInfo;
   2531     soc_mem_t mem = INVALIDm;
   2532     int idx_min, idx_max;
   2533 
   2534     if (buffer == NULL) {
   2535         return BCM_E_PARAM;
   2536     }
   2537 
   2538     if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   2539         bid = bcmBstStatIdQueueTotal;
   2540     }
   2541     resInfo = _BCM_BST_RESOURCE(unit, bid);
   2542     if(resInfo == NULL || !(resInfo->valid)) {
   2543         return BCM_E_BADID;
   2544     }
   2545     if(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID) {
   2546         if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) {
   2547             mem = resInfo->threshold_mem[inst];
   2548         } else {
   2549             mem = resInfo->threshold_mem[0];
   2550         }
   2551     } else {
   2552         /* this function doesn't support registers.  Only memory range */
   2553         return BCM_E_PARAM;
   2554     }
   2555 
   2556     if(mem != INVALIDm) {
   2557         idx_min = soc_mem_index_min(unit, mem);
   2558         idx_max = soc_mem_index_max(unit, mem);
   2559 
   2560         if(flags & BST_OP_GET) {
   2561             *buffer = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, mem),
   2562                                           "profile_read_mem_range");
   2563             if (*buffer == NULL) {
   2564                 return BCM_E_MEMORY;
   2565             }
   2566             /* Calling function will free up memory */
   2567             BCM_IF_ERROR_RETURN(soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   2568                             idx_min, idx_max, *buffer));
   2569         } else if (flags & BST_OP_SET) {
   2570             /* Calling function will free up memory */
   2571             BCM_IF_ERROR_RETURN(soc_mem_write_range(unit, mem, MEM_BLOCK_ALL,
   2572                         idx_min, idx_max, *buffer));
   2573         }
   2574     } else {
   2575         return BCM_E_PARAM;
   2576     }
   2577     return BCM_E_NONE;
   2578 }
   2579 
   2580 /*
   2581  * Function:
   2582  *   _bcm_th3_bst_profile_op_mem_buffer
   2583  * Purpose:
   2584  *  Set/Get a specific threshold profile/value in buffer for a given memory.
   2585  * Parameters:
   2586  *     unit       - (IN) unit number.
   2587  *     flags  - (IN) operation type, i.e. GET or SET.
   2588  *     bid    - (IN) BST stat ID.
   2589  *     inst -  (IN) inst number (pipe number or ITM number).
   2590  *     sw_index - (IN) memory-entry index
   2591  *     buffer - (IN) RAM buffer to read/write from/to
   2592  *     resval - (IN) for SET, (OUT) for GET
   2593  * Returns:
   2594  *     _BCM_BST_RV_*
   2595  */
   2596 STATIC int
   2597 _bcm_th3_bst_profile_op_mem_buffer(int unit, int flags, bcm_bst_stat_id_t bid,
   2598                                 int inst, int sw_index, uint8 * buffer, uint32 *resval)
   2599 {
   2600     _bcm_bst_resource_info_t *resInfo;
   2601     int num_field, idx_min, idx_max;
   2602     soc_mem_t mem = INVALIDm;
   2603     soc_field_t field;
   2604     int hw_index = sw_index;
   2605     uint32 *entry;
   2606     if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   2607         bid = bcmBstStatIdQueueTotal;
   2608     }
   2609     resInfo = _BCM_BST_RESOURCE(unit, bid);
   2610     if(resInfo == NULL || !(resInfo->valid)) {
   2611         return BCM_E_BADID;
   2612     }
   2613     if(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID) {
   2614         if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) {
   2615             mem = resInfo->threshold_mem[inst];
   2616         } else {
   2617             mem = resInfo->threshold_mem[0];
   2618         }
   2619     } else {
   2620         /* This function only supports memory, not registers */
   2621         return BCM_E_PARAM;
   2622     }
   2623 
   2624     if(mem != INVALIDm) {
   2625         if((field = resInfo->threshold_field) == INVALIDf) {
   2626             /*  multiple sel field within one mem_entry */
   2627             num_field = resInfo->num_field;
   2628             field = resInfo->thd_fields[sw_index % num_field];
   2629             hw_index = sw_index / num_field;
   2630         }
   2631         /* Sanity check */
   2632         idx_min = soc_mem_index_min(unit, mem);
   2633         idx_max = soc_mem_index_max(unit, mem);
   2634         if (hw_index < idx_min || hw_index > idx_max) {
   2635             return BCM_E_PARAM;
   2636         }
   2637 
   2638         /* Get a pointer to the entry in the memory buffer */
   2639         entry = soc_mem_table_idx_to_pointer(unit, mem, uint32 *, buffer,
   2640                         hw_index);
   2641         if(flags & BST_OP_GET) {
   2642             *resval = soc_mem_field32_get(unit, mem, entry, field);
   2643         } else if (flags & BST_OP_SET){
   2644            soc_mem_field32_set(unit, mem, entry, field, *resval);
   2645         }
   2646 
   2647     } else {
   2648         return BCM_E_PARAM;
   2649     }
   2650     return BCM_E_NONE;
   2651 }
   2652 
   2653 
   2654 /*
   2655  * Function:
   2656  *   _bcm_th3_bst_profile_op
   2657  * Purpose:
   2658  *  Set/Get a specific threshold profile/value in HW for a given resource.
   2659  * Parameters:
   2660  *     unit       - (IN) unit number.
   2661  *     flags  - (IN) operation type, i.e. GET or SET.
   2662  *     bid    - (IN) BST stat ID.
   2663  *     inst -  (OUT) inst number (pipe number or ITM number).
   2664  *     sw_index - (IN) register/memory-entry index
   2665  *     resval - (IN) for SET, (OUT) for GET
   2666  * Returns:
   2667  *     _BCM_BST_RV_*
   2668  */
   2669 
   2670 STATIC int
   2671 _bcm_th3_bst_profile_op(int unit, int flags, bcm_bst_stat_id_t bid,
   2672                                 int inst, int sw_index, uint32 *resval)
   2673 {
   2674     _bcm_bst_resource_info_t *resInfo;
   2675     int i, num_field;
   2676     soc_mem_t mem = INVALIDm;
   2677     soc_reg_t reg = INVALIDr;
   2678     soc_field_t field = INVALIDf;
   2679     int hw_index = sw_index;
   2680     uint32 entry[SOC_MAX_MEM_WORDS], rval;
   2681     if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   2682         bid = bcmBstStatIdQueueTotal;
   2683     }
   2684     resInfo = _BCM_BST_RESOURCE(unit, bid);
   2685     if(resInfo == NULL || !(resInfo->valid)) {
   2686         return BCM_E_BADID;
   2687     }
   2688     if(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID) {
   2689         if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) {
   2690             mem = resInfo->threshold_mem[inst];
   2691         } else {
   2692             mem = resInfo->threshold_mem[0];
   2693         }
   2694     } else {
   2695         reg = resInfo->threshold_reg[0];
   2696         field = resInfo->threshold_field;
   2697     }
   2698 
   2699     if(mem != INVALIDm) {
   2700         if((field = resInfo->threshold_field) == INVALIDf) {
   2701             /*  multiple sel field within one mem_entry */
   2702             num_field = resInfo->num_field;
   2703             field = resInfo->thd_fields[sw_index % num_field];
   2704             hw_index = sw_index / num_field;
   2705         }
   2706         BCM_IF_ERROR_RETURN(
   2707                 soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, entry));
   2708         if(flags & BST_OP_GET) {
   2709             *resval = soc_mem_field32_get(unit, mem, entry, field);
   2710         } else if (flags & BST_OP_SET){
   2711            soc_mem_field32_set(unit, mem, entry, field, *resval);
   2712            BCM_IF_ERROR_RETURN(
   2713                 soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, entry));
   2714         }
   2715 
   2716     } else if (reg != INVALIDr) {
   2717 
   2718         if(bid == bcmBstStatIdDevice) {
   2719             if(inst == -1) {
   2720                 for(i = 0; i < NUM_ITM(unit); i++) {
   2721                     uint32 temp;
   2722                     inst = i | SOC_REG_ADDR_INSTANCE_MASK;
   2723                     SOC_IF_ERROR_RETURN(
   2724                             soc_reg32_get(unit, reg, inst,
   2725                                                         hw_index, &rval));
   2726                     if(flags & BST_OP_GET) {
   2727                         temp = soc_reg_field_get(unit, reg, rval, field);
   2728                         if(temp > *resval) {
   2729                             *resval = temp;
   2730                         }
   2731 
   2732                     } else if (flags & BST_OP_SET) {
   2733 
   2734                         soc_reg_field_set(unit, reg, &rval, field, *resval);
   2735                         SOC_IF_ERROR_RETURN(
   2736                              soc_reg32_set(unit, reg, inst, hw_index, rval));
   2737                     }
   2738                 }
   2739             }
   2740             else {
   2741                  inst = inst | SOC_REG_ADDR_INSTANCE_MASK;
   2742                  SOC_IF_ERROR_RETURN(
   2743                     soc_reg32_get(unit, reg, inst, hw_index, &rval));
   2744                  if(flags & BST_OP_GET) {
   2745                     *resval = soc_reg_field_get(unit, reg, rval, field);
   2746                  } else if (flags & BST_OP_SET) {
   2747                     soc_reg_field_set(unit, reg, &rval, field, *resval);
   2748                     SOC_IF_ERROR_RETURN(
   2749                             soc_reg32_set(unit, reg, inst, hw_index, rval));
   2750                  }
   2751             }
   2752         } else {
   2753             SOC_IF_ERROR_RETURN(
   2754                     soc_reg32_get(unit, reg, REG_PORT_ANY, hw_index, &rval));
   2755              if(flags & BST_OP_GET) {
   2756                 *resval = soc_reg_field_get(unit, reg, rval, field);
   2757              } else if(flags & BST_OP_SET){
   2758                 soc_reg_field_set(unit, reg, &rval, field, *resval);
   2759                 SOC_IF_ERROR_RETURN(
   2760                     soc_reg32_set(unit, reg, REG_PORT_ANY, hw_index, rval));
   2761              }
   2762         }
   2763     }
   2764     return BCM_E_NONE;
   2765 }
   2766 
   2767 
   2768 /* Function:
   2769  *  _bst_th3_cmn_profile_get_hw
   2770  * Purpose:
   2771  * Get threshold of specified bid from pipe and sw_index for profile_based
   2772  * threshold, get threshold from itm and sw_index for non-profile based
   2773  * threshold.
   2774  * Parameters:
   2775  *     unit       - (IN) unit number.
   2776  *     pipe    - (IN) pipe number.
   2777  *     itm  - (IN) ITM number.
   2778  *     sw_index - (IN) register/memory-entry index
   2779  *     bid    - (IN) BST stat ID.
   2780  *     profile - (OUT) pointer to threshold struct.
   2781 */
   2782 STATIC int
   2783 _bst_th3_cmn_profile_get_hw(int unit, int pipe, int itm, int sw_index,
   2784                             bcm_bst_stat_id_t bid,
   2785                             bcm_cosq_bst_profile_t *profile)
   2786 {
   2787     _bcm_bst_cmn_unit_info_t *bst_info;
   2788     _bcm_bst_resource_info_t *resInfo;
   2789     uint32 val, rval, reg_id;
   2790     soc_reg_t reg;
   2791     soc_field_t field;
   2792 
   2793     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   2794         return BCM_E_INIT;
   2795     }
   2796     if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   2797         bid = bcmBstStatIdQueueTotal;
   2798     }
   2799     resInfo = _BCM_BST_RESOURCE(unit, bid);
   2800     if (resInfo == NULL || !resInfo->valid) {
   2801         return BCM_E_PARAM;
   2802     }
   2803     val = 0;
   2804     if(!(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID)) {
   2805         /* non-profile based threshold, val is # of cells */
   2806         BCM_IF_ERROR_RETURN(
   2807                 _bcm_th3_bst_profile_op(unit, BST_OP_GET, bid, itm, sw_index,
   2808                                              &val));
   2809         profile->byte = bst_info->to_byte(unit, val);
   2810     } else {
   2811         /* profile-based threshold, val is the profile index */
   2812             reg_id = _bcm_bst_th3_profile_reg_id_get(unit, bid, sw_index);
   2813             reg = resInfo->profile_reg[reg_id];
   2814             sw_index &= _TH3_BST_QUEUE_TYPE_SHIFT_MASK;
   2815         BCM_IF_ERROR_RETURN(
   2816                 _bcm_th3_bst_profile_op(unit, BST_OP_GET, bid, pipe, sw_index,
   2817                                                                &val));
   2818         field = resInfo->profile_field;
   2819         if(reg != INVALIDr) {
   2820             SOC_IF_ERROR_RETURN(
   2821                     soc_reg32_get(unit, reg, REG_PORT_ANY, val, &rval));
   2822             val = soc_reg_field_get(unit, reg, rval, field);
   2823             profile->byte = bst_info->to_byte(unit, val);
   2824 
   2825         } else {
   2826             return BCM_E_INIT;
   2827         }
   2828 
   2829     }
   2830 
   2831     return BCM_E_NONE;
   2832 }
   2833 
   2834 /* Function:
   2835  *  _bst_th3_cmn_profile_set_hw
   2836  * Purpose:
   2837  * Set threshold of specified bid from pipe and sw_index for profile_based
   2838  * thresholds, set threshold from itm and sw_index for non-profile based
   2839  * thresholds.
   2840  * Parameters:
   2841  *     unit       - (IN) unit number.
   2842  *     pipe    - (IN) pipe number.
   2843  *     itm  - (IN) ITM number.
   2844  *     sw_index - (IN) register/memory-entry index
   2845  *     bid    - (IN) BST stat ID.
   2846  *     profile - (IN) pointer to threshold struct.
   2847  *     p_profile - (OUT) allocated profile index.
   2848 */
   2849 
   2850 /*
   2851  * Usage of itm (all BST threshold profile are duplicated except CFAP):
   2852  *   -1:    all ITMs related to the pipe with same value, reg[i] = profile[0]
   2853  *  0-1 :   ITM num, applicable only for bid = bcmBstStatIdDevice
   2854  *  _TH3_BST_PROFILE_INIT_FLAG   for BST profile init only
   2855  */
   2856 
   2857 STATIC int
   2858 _bst_th3_cmn_profile_set_hw(int unit, int pipe, int itm, int sw_index,
   2859                             bcm_bst_stat_id_t bid,
   2860                             bcm_cosq_bst_profile_t *profile,
   2861                             uint32 *p_profile)
   2862 {
   2863     uint32 cell;
   2864     uint32 profile_index, old_profile_index, reg_id;
   2865     int inst, inst_offset;
   2866     uint64 rval;
   2867     uint64 *prval[1];
   2868     _bcm_bst_cmn_unit_info_t *bst_info;
   2869     _bcm_bst_resource_info_t *resInfo;
   2870     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   2871         return BCM_E_INIT;
   2872     }
   2873     if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   2874         bid = bcmBstStatIdQueueTotal;
   2875     }
   2876     resInfo = _BCM_BST_RESOURCE(unit, bid);
   2877     if(resInfo == NULL || resInfo->valid == 0) {
   2878         return BCM_E_INIT;
   2879     }
   2880     if (profile->byte > bst_info->max_bytes) {
   2881         return BCM_E_PARAM;
   2882     }
   2883     cell = bst_info->to_cell(unit, profile->byte);
   2884     inst_offset = (resInfo->index_max + 1) / (resInfo->num_instance);
   2885 
   2886     reg_id = _bcm_bst_th3_profile_reg_id_get(unit, bid, sw_index);
   2887 
   2888     sw_index &= _TH3_BST_QUEUE_TYPE_SHIFT_MASK;
   2889     /*update sw thd */
   2890     if(sw_index >= 0) {
   2891         if(resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) {
   2892             /* for per-piped thresh, only update the specfic pipe */
   2893             resInfo->p_threshold[sw_index + pipe * inst_offset] = cell;
   2894         } else {
   2895             /* ITM based threshold */
   2896             if (bid == bcmBstStatIdDevice) {
   2897                 for(inst = 0; inst < resInfo->num_instance; inst++) {
   2898                     /*update both ITMs for threhsolds of unique access type */
   2899                     resInfo->p_threshold[sw_index + inst * inst_offset] = cell;
   2900                 }
   2901             } else {
   2902                 /*For trhehsolds in ITM with duplicate access type, upadate only
   2903                  * ITM 0*/
   2904                 resInfo->p_threshold[sw_index] = cell;
   2905             }
   2906         }
   2907     }
   2908     if(!(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID)) {
   2909         /* non-profile based threshold */
   2910         BCM_IF_ERROR_RETURN(
   2911                 _bcm_th3_bst_profile_op(unit, BST_OP_SET, bid, itm, sw_index,
   2912                                                           &cell));
   2913         return BCM_E_NONE;
   2914     }
   2915     /* add new profile */
   2916     profile_index = old_profile_index = -1;
   2917 
   2918     if (resInfo->profile_r[reg_id]) {
   2919         COMPILER_64_ZERO(rval);
   2920         soc_reg64_field32_set(unit, resInfo->profile_reg[reg_id], &rval,
   2921                                             resInfo->profile_field, cell);
   2922         prval[0] = &rval;
   2923         SOC_IF_ERROR_RETURN(soc_profile_reg_add
   2924                                     (unit, resInfo->profile_r[reg_id],
   2925                                                 prval, 1, &profile_index));
   2926     }
   2927     if(profile_index != -1)
   2928     {
   2929         /* get old profile ID */
   2930         BCM_IF_ERROR_RETURN(
   2931                 _bcm_th3_bst_profile_op(unit, BST_OP_GET, bid, pipe, sw_index,
   2932                                                  &old_profile_index));
   2933 
   2934         if(old_profile_index != profile_index) {
   2935             /* attach new profile */
   2936             BCM_IF_ERROR_RETURN(
   2937                 _bcm_th3_bst_profile_op(unit, BST_OP_SET, bid, pipe, sw_index,
   2938                                                         &profile_index));
   2939            /* delete old profile */
   2940            if(itm != _TH3_BST_PROFILE_INIT_FLAG) {
   2941                 if(resInfo->profile_r[reg_id]) {
   2942                     SOC_IF_ERROR_RETURN
   2943                         (soc_profile_reg_delete(unit, resInfo->profile_r[reg_id],
   2944                                                      old_profile_index));
   2945                 }
   2946            }
   2947         }
   2948         if(p_profile) {
   2949             *p_profile = profile_index;
   2950         }
   2951     }
   2952 
   2953     return BCM_E_NONE;
   2954 }
   2955 
   2956 /* Function:
   2957  *  _bst_th3_cmn_profile_set
   2958  * Purpose:
   2959  * Set threshold of specified bid from gport/cosq/ITM 
   2960  * Parameters:
   2961  *     unit       - (IN) unit number.
   2962  *     pipe    - (IN) pipe number.
   2963  *     itm  - (IN) ITM number.
   2964  *     sw_index - (IN) register/memory-entry index
   2965  *     bid    - (IN) BST stat ID.
   2966  *     profile - (IN) pointer to threshold struct.
   2967  */
   2968 /*BST threshold configuration is Unique only for bcmBstStatIdDevice in TH3*/
   2969 int
   2970 _bcm_th3_bst_cmn_profile_set (int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   2971         int buffer, bcm_bst_stat_id_t bid, bcm_cosq_bst_profile_t *profile)
   2972 {
   2973     _bcm_bst_cmn_unit_info_t *bst_info;
   2974     _bcm_bst_cb_ret_t rv;
   2975     void *cb_data = NULL;
   2976     int bcm_rv, ii, rcb = 0, pipe;
   2977     int start_hw_index = 0, end_hw_index = 0;
   2978     _bcm_bst_resource_info_t *resInfo;
   2979     int sw_idx_loop, num_sw_entries, sw_index;
   2980     int sw_idx_arr[_TH3_MMU_NUM_PG] = {-1, -1, -1, -1, -1, -1, -1, -1};
   2981     soc_info_t *si = &SOC_INFO(unit);
   2982     int local_port, index;
   2983 
   2984     /* Parameter check */
   2985     if (bid < bcmBstStatIdInvalid || bid >= bcmBstStatIdMaxCount) {
   2986         return BCM_E_PARAM;
   2987     }
   2988 
   2989     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   2990         return BCM_E_INIT;
   2991     }
   2992 
   2993     BCM_IF_ERROR_RETURN(
   2994             _bcm_th3_bst_bid_gport_cosq_param_check(unit, bid, gport, cosq));
   2995 
   2996     if (profile == NULL) {
   2997         return BCM_E_PARAM;
   2998     }
   2999 
   3000     if (bst_info->handlers.resolve_index == NULL) {
   3001         return BCM_E_UNAVAIL;
   3002     }
   3003 
   3004     do {
   3005         rv = bst_info->handlers.resolve_index(unit, gport, cosq, bid, &pipe,
   3006                     &start_hw_index, &end_hw_index, &rcb, &cb_data, &bcm_rv);
   3007         if (bcm_rv) {
   3008             return bcm_rv;
   3009         }
   3010         if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   3011             bid = bcmBstStatIdQueueTotal;
   3012         }
   3013         resInfo = _BCM_BST_RESOURCE(unit, bid);
   3014         if ((resInfo == NULL) || (!_BCM_BST_RESOURCE_VALID(resInfo))) {
   3015             return BCM_E_PARAM;
   3016         }
   3017 
   3018         for (ii = start_hw_index; ii <= end_hw_index; ii++) {
   3019             BCM_IF_ERROR_RETURN(
   3020                         _bcm_th3_bst_sw_index_get(unit, gport, cosq, bid,
   3021                              ii, &num_sw_entries, sw_idx_arr));
   3022             if (num_sw_entries > resInfo->num_field) {
   3023                         return BCM_E_INTERNAL;
   3024             }
   3025             for (sw_idx_loop = 0; sw_idx_loop < num_sw_entries;
   3026                 sw_idx_loop ++) {
   3027                 sw_index = sw_idx_arr[sw_idx_loop];
   3028                 if (sw_index != -1) {
   3029                     if (bid == bcmBstStatIdQueueTotal) {
   3030                         BCM_IF_ERROR_RETURN(
   3031                                 _bcm_th3_cosq_localport_resolve(unit, gport,
   3032                                     &local_port));
   3033                         if (IS_CPU_PORT(unit, local_port)) {
   3034                             index = sw_index |
   3035                                 (_BCM_TH3_BST_Q_TYPE_CPU <<
   3036                                  _TH3_BST_QUEUE_TYPE_SHIFT);
   3037                         } else {
   3038                             if (sw_index < si->port_cosq_base[local_port]) {
   3039                                 /*Unicast queue of port*/
   3040                                 index = sw_index |
   3041                                     (_BCM_TH3_BST_Q_TYPE_UC <<
   3042                                     _TH3_BST_QUEUE_TYPE_SHIFT);
   3043                             } else {
   3044                                 /*Multicast queue of port*/
   3045                                 index = sw_index |
   3046                                     (_BCM_TH3_BST_Q_TYPE_MC <<
   3047                                     _TH3_BST_QUEUE_TYPE_SHIFT);
   3048                             }
   3049                         }
   3050                             BCM_IF_ERROR_RETURN(
   3051                                 _bst_th3_cmn_profile_set_hw(unit, pipe, buffer,
   3052                                     index, bid, profile, NULL));
   3053                     } else {
   3054                         BCM_IF_ERROR_RETURN(
   3055                             _bst_th3_cmn_profile_set_hw(unit, pipe, buffer,
   3056                                 sw_index, bid, profile, NULL));
   3057                     }
   3058                 }
   3059             }
   3060         }
   3061 
   3062     } while (rv == _BCM_BST_RV_RETRY);
   3063     return BCM_E_NONE;
   3064 }
   3065 
   3066 /* Function:
   3067  *  _bst_th3_cmn_profile_get
   3068  * Purpose:
   3069  * Get threshold of specified bid from gport/cosq/ITM 
   3070  * Parameters:
   3071  *     unit       - (IN) unit number.
   3072  *     pipe    - (IN) pipe number.
   3073  *     itm  - (IN) ITM number.
   3074  *     sw_index - (IN) register/memory-entry index
   3075  *     bid    - (IN) BST stat ID.
   3076  *     profile - (OUT) pointer to threshold struct.
   3077  */
   3078 int
   3079 _bcm_th3_bst_cmn_profile_get (int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   3080         int buffer, bcm_bst_stat_id_t bid, bcm_cosq_bst_profile_t *profile)
   3081 {
   3082         _bcm_bst_cmn_unit_info_t *bst_info;
   3083     void *cb_data = NULL;
   3084     int bcm_rv, rcb = 0, pipe;
   3085     int start_hw_index = 0, end_hw_index = 0;
   3086     _bcm_bst_resource_info_t *resInfo;
   3087     int sw_idx_loop, num_sw_entries, sw_index;
   3088     int sw_idx_arr[_TH3_MMU_NUM_PG] = {-1, -1, -1, -1, -1, -1, -1, -1};
   3089     soc_info_t *si = &SOC_INFO(unit);
   3090     int local_port, index;
   3091 
   3092     /* Parameter check */
   3093     if (bid < bcmBstStatIdInvalid || bid >= bcmBstStatIdMaxCount) {
   3094         return BCM_E_PARAM;
   3095     }
   3096 
   3097     BCM_IF_ERROR_RETURN(
   3098             _bcm_th3_bst_bid_gport_cosq_param_check(unit, bid, gport, cosq));
   3099 
   3100     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   3101         return BCM_E_INIT;
   3102     }
   3103 
   3104 
   3105     if (profile == NULL) {
   3106         return BCM_E_PARAM;
   3107     }
   3108 
   3109     if (bst_info->handlers.resolve_index == NULL) {
   3110         return BCM_E_UNAVAIL;
   3111     }
   3112 
   3113     bst_info->handlers.resolve_index(unit, gport, cosq, bid, &pipe,
   3114                 &start_hw_index, &end_hw_index, &rcb, &cb_data, &bcm_rv);
   3115     if (bcm_rv) {
   3116         return bcm_rv;
   3117     }
   3118 
   3119     if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   3120         bid = bcmBstStatIdQueueTotal;
   3121     }
   3122 
   3123     resInfo = _BCM_BST_RESOURCE(unit, bid);
   3124     if ((resInfo == NULL) || (!_BCM_BST_RESOURCE_VALID(resInfo))) {
   3125         return BCM_E_PARAM;
   3126     }
   3127     BCM_IF_ERROR_RETURN(
   3128             _bcm_th3_bst_sw_index_get(unit, gport, cosq, bid,
   3129                              start_hw_index, &num_sw_entries, sw_idx_arr));
   3130     if (num_sw_entries > resInfo->num_field) {
   3131         return BCM_E_INTERNAL;
   3132     }
   3133     for (sw_idx_loop = 0; sw_idx_loop < num_sw_entries;
   3134         sw_idx_loop ++) {
   3135         sw_index = sw_idx_arr[sw_idx_loop];
   3136         if (sw_index != -1) {
   3137             if (bid == bcmBstStatIdQueueTotal) {
   3138                 BCM_IF_ERROR_RETURN(
   3139                         _bcm_th3_cosq_localport_resolve(unit, gport,
   3140                             &local_port));
   3141                 if (IS_CPU_PORT(unit, local_port)) {
   3142                     index = sw_index |
   3143                         (_BCM_TH3_BST_Q_TYPE_CPU <<
   3144                          _TH3_BST_QUEUE_TYPE_SHIFT);
   3145                 } else {
   3146                     if (sw_index < si->port_cosq_base[local_port]) {
   3147                         /*Unicast queue of port*/
   3148                         index = sw_index |
   3149                             (_BCM_TH3_BST_Q_TYPE_UC <<
   3150                             _TH3_BST_QUEUE_TYPE_SHIFT);
   3151                     } else {
   3152                         /*Multicast queue of port*/
   3153                         index = sw_index |
   3154                             (_BCM_TH3_BST_Q_TYPE_MC <<
   3155                             _TH3_BST_QUEUE_TYPE_SHIFT);
   3156                     }
   3157                 }
   3158                     BCM_IF_ERROR_RETURN(
   3159                         _bst_th3_cmn_profile_get_hw(unit, pipe, buffer,
   3160                             index, bid, profile));
   3161             } else {
   3162                 BCM_IF_ERROR_RETURN(
   3163                     _bst_th3_cmn_profile_get_hw(unit, pipe, buffer,
   3164                         sw_index, bid, profile));
   3165             }
   3166             /* return after 1st valid get */
   3167             return BCM_E_NONE;
   3168         }
   3169     }
   3170 
   3171 
   3172     return BCM_E_NONE;
   3173 }
   3174 
   3175 
   3176 /* Function:
   3177  *  _bst_th3_profile_init
   3178  * Purpose:
   3179  *  Threshold Profile init.
   3180  *     unit       - (IN) unit number.
   3181 */
   3182 
   3183 STATIC int
   3184 _bst_th3_profile_init(int unit)
   3185 {
   3186 
   3187     _bcm_bst_cmn_unit_info_t *bst_info;
   3188     _bcm_bst_resource_info_t *resInfo;
   3189     bcm_bst_stat_id_t bid;
   3190     bcm_cosq_bst_profile_t profile;
   3191     int i, ei, index_max, wb, inst;
   3192     uint32 profile_index;
   3193     soc_reg_t p_reg;
   3194     int num_reg;
   3195 
   3196     uint8 ** bid_inst_buffer = NULL;
   3197     int rv = BCM_E_NONE;
   3198     uint16 dev_id;
   3199     uint8  rev_id;
   3200 
   3201     soc_cm_get_id(unit, &dev_id, &rev_id);
   3202     wb = SOC_WARM_BOOT(unit) ? 1 : 0;
   3203     bst_info = _BCM_UNIT_BST_INFO(unit);
   3204     profile.byte = bst_info->max_bytes;
   3205 
   3206     _BCM_BST_RESOURCE_ITER(bst_info, bid) {
   3207         resInfo = _BCM_BST_RESOURCE(unit, bid);
   3208 
   3209         if (!(resInfo->flags & _BCM_BST_CMN_RES_F_PROFILEID)) {
   3210             continue;
   3211         }
   3212         if ((bid == bcmBstStatIdUcast) || (bid == bcmBstStatIdMcast)) {
   3213             continue;
   3214         }
   3215 
   3216         if (wb) {
   3217             /* create an array of uint8 * to bring in each memory instance of resInfo
   3218              * below */
   3219             bid_inst_buffer = (uint8 **)sal_alloc(resInfo->num_instance * sizeof(uint8 *),
   3220                                             "bid_inst_buffer");
   3221             if (bid_inst_buffer == NULL) {
   3222                 rv = BCM_E_MEMORY;
   3223                 goto cleanup;
   3224             }
   3225             sal_memset(bid_inst_buffer, 0, resInfo->num_instance * sizeof(uint8 *));
   3226         }
   3227         if(bid == bcmBstStatIdQueueTotal) {
   3228             num_reg = resInfo->num_profile_reg;
   3229         } else {
   3230             num_reg = 1;
   3231         }
   3232         /* create profiles */
   3233         resInfo->profile_m = NULL;
   3234         for (i = 0; i < _BCM_MAX_PROFILES; i ++) {
   3235             resInfo->profile_r[i] = NULL;
   3236         }
   3237         for(i = 0; i < num_reg; i++) {
   3238             p_reg = resInfo->profile_reg[i];
   3239             if (resInfo->profile_mem != INVALIDm) {
   3240                 /* currently no profile_mem for TH3 BST*/
   3241                rv = BCM_E_INTERNAL;
   3242                goto cleanup;
   3243 
   3244             } else if (p_reg != INVALIDr) {
   3245                     soc_profile_reg_t_init(&resInfo->iprofile_r[i]);
   3246                     rv = soc_profile_reg_create
   3247                                      (unit, &p_reg, 1, &resInfo->iprofile_r[i]);
   3248                     if (BCM_FAILURE(rv)) {
   3249                         goto cleanup;
   3250                     }
   3251 
   3252                     resInfo->profile_r[i] = &resInfo->iprofile_r[i];
   3253             }
   3254 
   3255             /* init profiles reference */
   3256             index_max = (resInfo->index_max + 1) / resInfo->num_instance;
   3257             for(inst = 0; inst < resInfo->num_instance; inst++) {
   3258                 if (dev_id == BCM56983_DEVICE_ID) {
   3259                     /* For 56983 SKU, check if the bid is per itm or per pipe
   3260                        so if it is per pipe, skip the invalid pipes 2, 3, 4,
   3261                        5. For ITM, we skip ITM 1
   3262                     */
   3263                     if (resInfo->num_instance == 8) {
   3264                         if (inst == 2 || inst == 3 || inst == 4 || inst == 5) {
   3265                             continue;
   3266                         }
   3267                     } else {
   3268                         if (inst == 1) {
   3269                             continue;
   3270                         }
   3271                     }
   3272                 }
   3273                 if (wb) {
   3274                     /* if the memory range is empty, read memory range to fill
   3275                      * it in */
   3276                     if (bid_inst_buffer[inst] == NULL) {
   3277                         rv = _bcm_th3_bst_profile_mem_range(unit, BST_OP_GET, bid, inst,
   3278                                                 &bid_inst_buffer[inst]);
   3279                         if (BCM_FAILURE(rv)) {
   3280                             goto cleanup;
   3281                         }
   3282                     }
   3283                 }
   3284                 for (ei = 0; ei < index_max; ei ++) {
   3285                     /* get profile index */
   3286                     if (wb) {
   3287                         /* retrieve profile_index from HW during warmboot*/
   3288                         rv = _bcm_th3_bst_profile_op_mem_buffer(unit, BST_OP_GET | BST_OP_THD,
   3289                             bid, inst, ei, bid_inst_buffer[inst], &profile_index);
   3290 
   3291                         if (BCM_FAILURE(rv)) {
   3292                             goto cleanup;
   3293                         }
   3294                     } else if (ei == 0) {
   3295                         if(bid == bcmBstStatIdQueueTotal) {
   3296                             rv = _bst_th3_cmn_profile_set_hw
   3297                                     (unit, inst, _TH3_BST_PROFILE_INIT_FLAG,
   3298                                   ei | (i << _TH3_BST_QUEUE_TYPE_SHIFT),
   3299                                             bid, &profile, &profile_index);
   3300                             if (BCM_FAILURE(rv)) {
   3301                                 goto cleanup;
   3302                             }
   3303                         } else {
   3304 
   3305                             rv = _bst_th3_cmn_profile_set_hw
   3306                                     (unit, inst, _TH3_BST_PROFILE_INIT_FLAG,
   3307                                             ei, bid, &profile, &profile_index);
   3308                             if (BCM_FAILURE(rv)) {
   3309                                 goto cleanup;
   3310                             }
   3311                         }
   3312                         /* Continue the above for loop, no cleanup necessary */
   3313                         continue;
   3314                     }
   3315                     /* add reference */
   3316                     if (resInfo->profile_r[i]) {
   3317                         rv = soc_profile_reg_reference(unit,
   3318                                         resInfo->profile_r[i], profile_index, 1);
   3319                         if (BCM_FAILURE(rv)) {
   3320                             goto cleanup;
   3321                         }
   3322                     }
   3323                     /* update sw thd */
   3324                     if(i == 0) {
   3325                         if ((resInfo->flags & _BCM_BST_CMN_RES_F_PIPED) ||
   3326                                 (bid == bcmBstStatIdDevice)) {
   3327                                     resInfo->p_threshold[ei + inst * index_max] =
   3328                                         bst_info->to_cell(unit, profile.byte);
   3329                         } else {
   3330                             resInfo->p_threshold[ei] =
   3331                                 bst_info->to_cell(unit, profile.byte);
   3332                         }
   3333                     }
   3334                     if(profile_index != 0) {
   3335 
   3336                         /* attach reference, for performance issues, execute
   3337                          *  only when it differs from HW default*/
   3338                         if (wb) {
   3339                             rv = _bcm_th3_bst_profile_op_mem_buffer(unit, BST_OP_SET,
   3340                                 bid, inst, ei, bid_inst_buffer[inst], &profile_index);
   3341                         } else {
   3342                             rv = _bcm_th3_bst_profile_op(unit, BST_OP_SET, bid, inst, ei,
   3343                                                &profile_index);
   3344                         }
   3345                         if (BCM_FAILURE(rv)) {
   3346                             goto cleanup;
   3347                         }
   3348                     }
   3349                 }
   3350                 if (wb) {
   3351                     /* Write out the memeory buffer to hardware since we're done with
   3352                      * this instance of the profile */
   3353                     if (bid_inst_buffer[inst]) {
   3354                         rv = _bcm_th3_bst_profile_mem_range(unit, BST_OP_SET, bid, inst,
   3355                                                 &bid_inst_buffer[inst]);
   3356                         if (BCM_FAILURE(rv)) {
   3357                             goto cleanup;
   3358                         }
   3359                     }
   3360                 }
   3361             }
   3362         }
   3363 cleanup:
   3364         if (bid_inst_buffer) {
   3365             for (i = 0; i < resInfo->num_instance; ++i) {
   3366                 if (bid_inst_buffer[i]) {
   3367                     soc_cm_sfree(unit, bid_inst_buffer[i]);
   3368                 }
   3369             }
   3370 
   3371             sal_free (bid_inst_buffer);
   3372             bid_inst_buffer = NULL;
   3373         }
   3374         if (BCM_FAILURE(rv)) {
   3375             return rv;
   3376         }
   3377     }
   3378 
   3379     return rv;
   3380 }
   3381 
   3382 int
   3383 bcm_bst_th3_init(int unit)
   3384 {
   3385     _bcm_bst_cmn_unit_info_t *bst_info;
   3386     int bid;
   3387     uint32 mode;
   3388 
   3389     bst_info = _BCM_UNIT_BST_INFO(unit);
   3390     if (!bst_info) {
   3391         return BCM_E_MEMORY;
   3392     }
   3393 
   3394     bst_info->to_cell = _bcm_bst_th3_byte_to_cell;
   3395     bst_info->to_byte = _bcm_bst_th3_cell_to_byte;
   3396     bst_info->control_set = _bcm_th3_bst_control_set;
   3397     bst_info->control_get = _bcm_th3_bst_control_get;
   3398     bst_info->intr_to_resources = _bcm_bst_th3_intr_to_resources;
   3399     bst_info->hw_stat_snapshot = _bcm_bst_th3_sync_hw_snapshot;
   3400     bst_info->hw_stat_clear = NULL; /* new function has one more parameter */
   3401     bst_info->intr_enable_set = _bcm_bst_th3_intr_enable_set;
   3402     bst_info->pre_sync = NULL;
   3403     bst_info->post_sync = NULL;
   3404     bst_info->hw_intr_cb = _bcm_th3_set_hw_intr_cb;
   3405     bst_info->port_to_mmu_inst_map = _bst_th3_port_to_mmu_inst_map_get;
   3406     bst_info->thd_get = NULL; /* new function has one more parameter */
   3407     bst_info->thd_set = NULL; /* new function has one more parameter */
   3408     bst_info->profile_init = _bst_th3_profile_init;
   3409     bst_info->hw_sbusdma_desc_init = _bcm_bst_th3_sbusdma_desc_init;
   3410     bst_info->hw_sbusdma_desc_deinit = _bcm_bst_th3_sbusdma_desc_deinit;
   3411     bst_info->hw_sbusdma_desc_sync = _bcm_bst_th3_sbusdma_desc_sync;
   3412     bst_info->max_bytes = bst_info->to_byte(unit, _TH3_BST_THRESHOLD_CELL_MAX);
   3413 
   3414     mode = soc_property_get(unit, spn_BUFFER_STATS_COLLECT_TYPE, 1);
   3415     if (mode == 1) {
   3416         /* bst */
   3417         for (bid = bcmBstStatIdDevice; bid < bcmBstStatIdMaxCount; bid++) {
   3418             if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast ||
   3419                 ((bid >= bcmBstStatIdRQEQueue) &&
   3420                  ((bid <= bcmBstStatIdUCQueueGroup)))) {
   3421                 continue;
   3422             }
   3423             BCM_IF_ERROR_RETURN
   3424                 (_bcm_th3_bst_resource_init(unit, bid));
   3425         }
   3426 
   3427     } else if (mode == 2) {
   3428         BCM_IF_ERROR_RETURN
   3429                 (_bcm_th3_bst_resource_init(unit, bcmBstStatIdEgrPool));
   3430         BCM_IF_ERROR_RETURN
   3431                 (_bcm_th3_bst_resource_init(unit, bcmBstStatIdIngPool));
   3432     }
   3433     return BCM_E_NONE;
   3434 }
   3435 
   3436 
   3437 STATIC int
   3438 _bst_th3_sbusdma_desc_setup(int unit)
   3439 {
   3440     _bcm_bst_cmn_unit_info_t *bst_info;
   3441     _bcm_bst_resource_info_t *resInfo;
   3442     _bcm_bst_tbl_ctrl_t *tbl_ctrl;
   3443     int blk, bid, mi;
   3444     uint8 acc_type;
   3445     soc_mem_t mem, base_mem;
   3446     soc_reg_t reg;
   3447     uint32 size;
   3448     uint8 *buff = NULL;
   3449     _bcm_bst_tbl_desc_t *desc = NULL;
   3450     int stats_per_inst = 0;
   3451     int idx_count = 0;
   3452     int xpe = 0;
   3453     int stat_idx = 0;
   3454     int inst = 0;
   3455 
   3456     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   3457         return BCM_E_INIT;
   3458     }
   3459     buff = bst_info->bst_tbl_buf;
   3460     bst_tbl_ctrl[unit] = sal_alloc(bcmBstStatIdMaxCount *
   3461                                       sizeof(_bcm_bst_tbl_ctrl_t *),
   3462                                       "bst_tbl_ctrl_p");
   3463     if (bst_tbl_ctrl[unit] == NULL) {
   3464         return BCM_E_MEMORY;
   3465     }
   3466 
   3467     bst_info->bst_tbl_desc = sal_alloc(bst_info->bst_tbl_num * sizeof(_bcm_bst_tbl_desc_t),
   3468         "bst_tbl_desc_p");
   3469     if (bst_info->bst_tbl_desc == NULL) {
   3470         return BCM_E_MEMORY;
   3471     }
   3472     sal_memset(bst_info->bst_tbl_desc, 0,  bst_info->bst_tbl_num * sizeof(_bcm_bst_tbl_desc_t));
   3473     desc = bst_info->bst_tbl_desc;
   3474 
   3475     mi = 0;
   3476     for (bid = _BCM_BST_RESOURCE_MIN; bid < _BCM_BST_RESOURCE_MAX; bid++) {
   3477         resInfo = _BCM_BST_RESOURCE(unit, bid);
   3478         if (resInfo == NULL) {
   3479             return BCM_E_PARAM;
   3480         }
   3481 
   3482         if (!_BCM_BST_RESOURCE_VALID(resInfo)) {
   3483             continue;
   3484         }
   3485         if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   3486             continue;
   3487         }
   3488 
   3489         tbl_ctrl = sal_alloc(sizeof(_bcm_bst_tbl_ctrl_t), "bst_tbl_ctrl");
   3490         if (tbl_ctrl == NULL) {
   3491             return BCM_E_MEMORY;
   3492         }
   3493         size = 0;
   3494         tbl_ctrl->tindex = bid;
   3495         /*BST tables are either per-pipe or per-ITM in TH3*/
   3496         tbl_ctrl->entries = resInfo->num_instance;
   3497         tbl_ctrl->buff = buff;
   3498         tbl_ctrl->size = 0;
   3499         bst_tbl_ctrl[unit][bid] = tbl_ctrl;
   3500 
   3501         base_mem = resInfo->stat_mem[0];
   3502         reg = resInfo->stat_reg[0];
   3503         if (reg != INVALIDr) {
   3504             stats_per_inst = resInfo->num_stat_pp / resInfo->num_instance;
   3505             for (xpe = 0; xpe < resInfo->num_instance; xpe++) {
   3506                 if (stats_per_inst) {
   3507                     inst = xpe ;
   3508                     stat_idx = 0;
   3509                 } else {
   3510                     inst = REG_PORT_ANY;
   3511                     stat_idx = xpe;
   3512                     stats_per_inst = 1;
   3513                 }
   3514                 desc[mi].reg = reg;
   3515                 desc[mi].addr = soc_reg_addr_get(unit, reg, inst, stat_idx,
   3516                     SOC_REG_ADDR_OPTION_NONE, &blk,
   3517                     &acc_type);
   3518                 desc[mi].flags = 0;
   3519                 desc[mi].acc_type = acc_type;
   3520                 desc[mi].blk = blk;
   3521                 desc[mi].width = BYTES2WORDS(soc_reg_bytes(unit, reg));
   3522                 desc[mi].entries= stats_per_inst;
   3523                 desc[mi].shift = 8;
   3524                 size += desc[mi].entries * desc[mi].width * 4;
   3525                 tbl_ctrl->blk = desc[mi].blk;
   3526                 mi++;
   3527             }
   3528         } else if (base_mem != INVALIDm) {
   3529             idx_count = 0;
   3530             for (inst = 0; inst < resInfo->num_instance; inst++) {
   3531                 if (resInfo->num_instance == NUM_ITM(unit)) {
   3532                     mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, inst);
   3533                 } else {
   3534                     mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, inst);
   3535                 }
   3536                 if (mem == INVALIDm) {
   3537                     continue;
   3538                 }
   3539                 idx_count = soc_mem_index_max(unit, mem) + 1;
   3540                 desc[mi].mem = mem;
   3541                 desc[mi].flags = SOC_SBUSDMA_CFG_COUNTER_IS_MEM | SOC_SBUSDMA_CFG_USE_FLAGS;
   3542                 desc[mi].blk = SOC_MEM_BLOCK_ANY(unit, mem);
   3543                 desc[mi].addr = soc_mem_addr_get(unit, mem,
   3544                                                0, desc[mi].blk, 0, &acc_type);
   3545                 desc[mi].acc_type = acc_type;
   3546                 desc[mi].blk = SOC_BLOCK2SCH(unit, desc[mi].blk);
   3547                 desc[mi].width = soc_mem_entry_words(unit, mem);
   3548                 desc[mi].entries = idx_count;
   3549                 desc[mi].shift = 0;
   3550                 size += desc[mi].entries * desc[mi].width * 4;
   3551                 tbl_ctrl->blk = desc[mi].blk;
   3552                 mi++;
   3553             }
   3554         }
   3555         buff += size;
   3556         tbl_ctrl->size += size;
   3557     }
   3558 
   3559     return BCM_E_NONE;
   3560 }
   3561 
   3562 STATIC int
   3563 _bcm_bst_th3_sbusdma_desc_init(int unit)
   3564 {
   3565     _bcm_bst_cmn_unit_info_t *bst_info;
   3566     _bcm_bst_resource_info_t *resInfo;
   3567     int bid, mi;
   3568     soc_mem_t mem, base_mem;
   3569     soc_reg_t reg;
   3570     uint32 entries, width, size = 0;
   3571     int inst = 0;
   3572     int rv = BCM_E_INIT;
   3573     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   3574         return BCM_E_INIT;
   3575     }
   3576     mi = 0;
   3577     for (bid = _BCM_BST_RESOURCE_MIN; bid < _BCM_BST_RESOURCE_MAX; bid++) {
   3578         resInfo = _BCM_BST_RESOURCE(unit, bid);
   3579         if (resInfo == NULL) {
   3580             return BCM_E_PARAM;
   3581         }
   3582 
   3583         if (!_BCM_BST_RESOURCE_VALID(resInfo)) {
   3584             continue;
   3585         }
   3586 
   3587         if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   3588             continue;
   3589         }
   3590         base_mem = resInfo->stat_mem[0];
   3591         reg = resInfo->stat_reg[0];
   3592         if (reg != INVALIDr) {
   3593             for (inst = 0; inst < resInfo->num_instance; inst++) {
   3594                 entries = resInfo->num_stat_pp / resInfo->num_instance;
   3595                 width = BYTES2WORDS(soc_reg_bytes(unit, reg));
   3596                 size += entries * width * 4;
   3597                 mi++;
   3598             }
   3599         } else if (base_mem != INVALIDm) {
   3600             int idx_count = 0;
   3601             if (resInfo->num_instance == NUM_ITM(unit)) {
   3602                 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, 0);
   3603             } else {
   3604                 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, 0);
   3605             }
   3606             if (mem == INVALIDm) {
   3607                 return BCM_E_PARAM;
   3608             }
   3609             for (inst = 0; inst < resInfo->num_instance ; inst++) {
   3610                 if (resInfo->num_instance == NUM_ITM(unit)) {
   3611                     mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, 0);
   3612                 } else {
   3613                     mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, 0);
   3614                 }
   3615                 if (mem == INVALIDm) {
   3616                     continue;
   3617                 }
   3618                 idx_count = soc_mem_index_max(unit, mem) + 1;
   3619                 entries = idx_count;
   3620                 width = soc_mem_entry_words(unit, mem);
   3621                 size += entries * width * 4;
   3622                 mi++;
   3623             }
   3624         }
   3625     }
   3626     bst_info->bst_tbl_size = size;
   3627     bst_info->bst_tbl_num = mi;
   3628     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3629                 (BSL_META_U(unit,
   3630                             "Total bst tbls: %d, Total size: %d\n"),
   3631                  mi, size));
   3632     bst_tbl_handles[unit] = 0;
   3633     if (bst_info->bst_tbl_buf == NULL) {
   3634         bst_info->bst_tbl_buf = soc_cm_salloc(unit, size, "bst_tbl_buf");
   3635         if (bst_info->bst_tbl_buf == NULL) {
   3636             goto error;
   3637         }
   3638     }
   3639     sal_memset(bst_info->bst_tbl_buf, 0, size);
   3640     rv =_bst_th3_sbusdma_desc_setup(unit);
   3641     if (rv != SOC_E_NONE) {
   3642         goto error;
   3643     }
   3644 
   3645     rv = soc_bst_sbusdma_desc_setup(unit);
   3646     if (rv != SOC_E_NONE) {
   3647         goto error;
   3648     }
   3649     return BCM_E_NONE;
   3650 error:
   3651     if (bst_info->bst_tbl_buf) {
   3652         soc_cm_sfree(unit, bst_info->bst_tbl_buf);
   3653         bst_info->bst_tbl_buf = NULL;
   3654     }
   3655     if (bst_info->bst_tbl_desc) {
   3656         sal_free(bst_info->bst_tbl_desc);
   3657         bst_info->bst_tbl_desc = NULL;
   3658     }
   3659     rv = soc_bst_sbusdma_desc_free(unit);
   3660     return rv;
   3661 }
   3662 
   3663 STATIC int
   3664 _bst_th3_sw_sbusdma_desc_sync(int unit, int bid)
   3665 {
   3666     _bcm_bst_cmn_unit_info_t *bst_info;
   3667     _bcm_bst_resource_info_t *resInfo;
   3668     _bcm_bst_tbl_ctrl_t *tbl_ctrl;
   3669     int idx, idx_offset = 0, inst_offset = 0;
   3670     void *pentry;
   3671     uint32 rval, temp_val = 0;
   3672     uint8 *buff = NULL;
   3673     soc_mem_t mem, base_mem;
   3674     soc_reg_t reg;
   3675     uint32 width = 0;
   3676     bcm_gport_t gport = -1;
   3677     bcm_cos_t cosq = -1;
   3678     int port = -1;
   3679     int j, inst;
   3680     int max_idx = 0;
   3681     int stats_per_inst = 0;
   3682 
   3683     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   3684         sal_mutex_give(bst_info->bst_reslock);
   3685         return BCM_E_INIT;
   3686     }
   3687     if (!bst_tbl_ctrl[unit][bid]) {
   3688         sal_mutex_give(bst_info->bst_reslock);
   3689         return BCM_E_INIT;
   3690     }
   3691     tbl_ctrl = bst_tbl_ctrl[unit][bid];
   3692     buff = tbl_ctrl->buff;
   3693     resInfo = _BCM_BST_RESOURCE(unit, bid);
   3694     if (resInfo == NULL) {
   3695         sal_mutex_give(bst_info->bst_reslock);
   3696         return BCM_E_PARAM;
   3697     }
   3698 
   3699     base_mem = resInfo->stat_mem[0];
   3700     reg = resInfo->stat_reg[0];
   3701     if (reg != INVALIDr) {
   3702         inst_offset = 0;
   3703         for (idx = 0; idx < resInfo->num_stat_pp; idx++) {
   3704             rval = 0;
   3705             width = BYTES2WORDS(soc_reg_bytes(unit, reg));
   3706             idx_offset = idx + inst_offset;
   3707             sal_memcpy(&rval, buff, width * 4);
   3708             temp_val = soc_reg_field_get(unit, reg, rval, resInfo->stat_field);
   3709             if (bst_info->track_mode) {
   3710                 /* BST tracking is in Peak mode.
   3711                  * Hence store the watermark value only.
   3712                  */
   3713                 if (resInfo->p_stat[idx_offset] < temp_val) {
   3714                     resInfo->p_stat[idx_offset] = temp_val;
   3715                 }
   3716             } else {
   3717                 resInfo->p_stat[idx_offset] = temp_val;
   3718             }
   3719             buff = buff + width * 4;
   3720 
   3721             /* Check if there exists threshold for a resource
   3722              * continue if we don't have one */
   3723             if (resInfo->p_threshold == NULL) {
   3724                 continue;
   3725             }
   3726 
   3727             /* coverity[copy_paste_error : FALSE] */
   3728             if (resInfo->p_threshold[idx_offset] &&
   3729                 (resInfo->p_stat[idx_offset] >=
   3730                  (resInfo->p_threshold[idx_offset] * resInfo->threshold_gran)
   3731                 )) {
   3732                 /* Generate SOC EVENT */
   3733                 if (bst_info->handlers.reverse_resolve_index) {
   3734                     /* reverse map the inedx to port/cos pair */
   3735                     bst_info->handlers.reverse_resolve_index(unit, bid,
   3736                                                              port, idx_offset,
   3737                                                              &gport, &cosq);
   3738                     soc_event_generate(unit, SOC_SWITCH_EVENT_MMU_BST_TRIGGER,
   3739                                        bid, gport, cosq);
   3740                 }
   3741             }
   3742 
   3743         }
   3744     } else if (base_mem != INVALIDm) {
   3745         if (resInfo->num_instance == NUM_ITM(unit)) {
   3746             mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, 0);
   3747         } else {
   3748             mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, 0);
   3749         }
   3750 
   3751         if (mem == INVALIDm) {
   3752             sal_mutex_give(bst_info->bst_reslock);
   3753             return BCM_E_PARAM;
   3754         }
   3755         stats_per_inst = (resInfo->index_max + 1) / resInfo->num_instance;
   3756         max_idx = soc_mem_index_max(unit, mem);
   3757         for (inst = 0; inst < resInfo->num_instance; inst++) {
   3758             inst_offset = stats_per_inst * inst;
   3759             gport = BCM_GPORT_INVALID;
   3760             cosq = -1;
   3761             if (resInfo->num_instance == NUM_ITM(unit)) {
   3762                 mem = SOC_MEM_UNIQUE_ACC_ITM(unit, base_mem, inst);
   3763             } else {
   3764                 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, inst);
   3765             }
   3766             if (mem == INVALIDm) {
   3767                 continue;
   3768             }
   3769 
   3770             for (idx = 0; idx < max_idx; idx++) {
   3771                 if(resInfo->stat_field != INVALIDf) {
   3772                     pentry = soc_mem_table_idx_to_pointer(unit, mem, void*,
   3773                                                       buff, idx);
   3774                     temp_val = soc_mem_field32_get(unit, mem, pentry,
   3775                                                         resInfo->stat_field);
   3776                     idx_offset = idx + inst_offset;
   3777 
   3778                 } else {
   3779                     pentry = soc_mem_table_idx_to_pointer(unit, mem, void*,
   3780                                                       buff, idx);
   3781                     for(j = 0; j < resInfo->num_field; j++) {
   3782                         temp_val = soc_mem_field32_get(unit, mem,
   3783                                             pentry, resInfo->stat_fields[j]);
   3784                         idx_offset = (idx * (resInfo->num_field))
   3785                                                     + inst_offset + j;
   3786                     }
   3787 
   3788                 }
   3789                 if (bst_info->track_mode) {
   3790                     /* BST tracking is in Peak mode.
   3791                      * Hence store the watermark value only.
   3792                      */
   3793                     if (resInfo->p_stat[idx_offset] < temp_val) {
   3794                         resInfo->p_stat[idx_offset] = temp_val;
   3795                     }
   3796                 } else {
   3797                     resInfo->p_stat[idx_offset] = temp_val;
   3798                 }
   3799 
   3800                 if (resInfo->p_threshold[idx] &&
   3801                     (resInfo->p_stat[idx_offset] >=
   3802                      (resInfo->p_threshold[idx]) * resInfo->threshold_gran)) {
   3803                     /* Generate SOC EVENT */
   3804                     if (bst_info->handlers.reverse_resolve_index) {
   3805                         /* reverse map the inedx to port/cos pair */
   3806                         bst_info->handlers.reverse_resolve_index(unit, bid,
   3807                                                                  port, idx,
   3808                                                                  &gport, &cosq);
   3809                         soc_event_generate(unit, SOC_SWITCH_EVENT_MMU_BST_TRIGGER,
   3810                                            bid, gport, cosq);
   3811 
   3812                     }
   3813                 }
   3814             }
   3815             buff += tbl_ctrl->size / tbl_ctrl->entries;
   3816          }
   3817     }
   3818     return BCM_E_NONE;
   3819 }
   3820 
   3821 
   3822 
   3823 STATIC int
   3824 _bcm_bst_th3_sbusdma_desc_sync(int unit)
   3825 {
   3826     _bcm_bst_cmn_unit_info_t *bst_info;
   3827     _bcm_bst_resource_info_t *resInfo;
   3828     bcm_bst_stat_id_t bid;
   3829     int enable = 0;
   3830 
   3831     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   3832         return BCM_E_INIT;
   3833     }
   3834 
   3835     if (!_BCM_BST_SYNC_THREAD_VALID(bst_info)) {
   3836         return BCM_E_NONE;
   3837     }
   3838 
   3839     sal_mutex_take(bst_info->bst_reslock, sal_mutex_FOREVER);
   3840 
   3841     if (bst_info->control_get) {
   3842         bst_info->control_get(unit, bcmSwitchBstEnable, &enable);
   3843     }
   3844 
   3845     if (enable && bst_info->control_set) {
   3846         bst_info->control_set(unit, bcmSwitchBstEnable, 0,
   3847                               _bcmBstThreadOperInternal);
   3848     }
   3849 
   3850     BCM_IF_ERROR_RETURN(soc_bst_hw_sbusdma_desc_sync(unit));
   3851 
   3852     for (bid = _BCM_BST_RESOURCE_MIN; bid < _BCM_BST_RESOURCE_MAX; bid++) {
   3853         resInfo = _BCM_BST_RESOURCE(unit, bid);
   3854         if (resInfo == NULL) {
   3855             return BCM_E_PARAM;
   3856         }
   3857 
   3858         if (!_BCM_BST_RESOURCE_VALID(resInfo)) {
   3859             continue;
   3860         }
   3861         if (bid == bcmBstStatIdUcast || bid == bcmBstStatIdMcast) {
   3862             continue;
   3863         }
   3864 
   3865         BCM_IF_ERROR_RETURN(_bst_th3_sw_sbusdma_desc_sync(unit, bid));
   3866     }
   3867 
   3868     if (enable && bst_info->control_set) {
   3869         bst_info->control_set(unit, bcmSwitchBstEnable, enable,
   3870                               _bcmBstThreadOperInternal);
   3871     }
   3872 
   3873     sal_mutex_give(bst_info->bst_reslock);
   3874     return BCM_E_NONE;
   3875 }
   3876 
   3877 STATIC int
   3878 _bcm_bst_th3_sbusdma_desc_deinit(int unit)
   3879 {
   3880     _bcm_bst_cmn_unit_info_t *bst_info;
   3881     int rv = BCM_E_INIT;
   3882 
   3883     if ((bst_info = _BCM_UNIT_BST_INFO(unit)) == NULL) {
   3884         return BCM_E_INIT;
   3885     }
   3886 
   3887     if (bst_info->bst_tbl_buf) {
   3888         soc_cm_sfree(unit, bst_info->bst_tbl_buf);
   3889         bst_info->bst_tbl_buf = NULL;
   3890     }
   3891     if (bst_info->bst_tbl_desc) {
   3892         sal_free(bst_info->bst_tbl_desc);
   3893         bst_info->bst_tbl_desc = NULL;
   3894     }
   3895 
   3896     rv = soc_bst_sbusdma_desc_free(unit);
   3897     if (rv != BCM_E_NONE) {
   3898         return rv;
   3899     }
   3900 
   3901     return BCM_E_NONE;
   3902 }
   3903 
   3904 /* Function:
   3905  *  _bcm_bst_th3_retrive_port_cosq_from_voq
   3906  * Purpose:
   3907  *  Retrieve gport/cosq from chip_queue_number.
   3908  *  Used for decoding BST trigger information for notifying users.
   3909  *     unit       - (IN) unit number.
   3910  *     voq        - (IN) Chip global VOQ number.
   3911  *     gport      - (OUT) gport corresponding to input VOQ.
   3912  *     cosq       - (OUT) cosq corresponding to input VOQ.
   3913  */
   3914 STATIC int
   3915 _bcm_bst_th3_retrive_port_cosq_from_voq (int unit, int voq,  bcm_gport_t *gport,
   3916         bcm_cos_t *cosq)
   3917 {
   3918     soc_info_t *si = &SOC_INFO(unit);
   3919     int max_voq, port;
   3920     int port_q_base, port_num_q;
   3921 
   3922     if (gport == NULL || cosq == NULL) {
   3923         return BCM_E_PARAM;
   3924     }
   3925     max_voq = si->port_uc_cosq_base[SOC_TH3_MAX_NUM_PORTS - 1] +
   3926         SOC_TH3_NUM_GP_QUEUES;
   3927     if (voq >= max_voq) {
   3928         return BCM_E_INTERNAL;
   3929     }
   3930     /* Iterate through all ports to retrieve cosq_base and determine port,
   3931          * cosq*/
   3932     PBMP_ALL_ITER(unit, port) {
   3933         if (IS_CPU_PORT(unit, port)) {
   3934             port_q_base = si->port_cosq_base[port];
   3935         } else {
   3936             port_q_base = si->port_uc_cosq_base[port];
   3937         }
   3938         port_num_q = si->port_num_uc_cosq[port] + si->port_num_cosq[port];
   3939         if ((voq >= port_q_base) && (voq < port_q_base + port_num_q)) {
   3940             *gport = port;
   3941             *cosq = voq - port_q_base;
   3942             break;
   3943         }
   3944     }
   3945     return BCM_E_NONE;
   3946 }
   3947 
   3948 /* Function:
   3949  *  _bcm_th3_cosq_bst_map_resource_to_gport_cos
   3950  * Purpose:
   3951  *  Retrieve gport/cosq from BST SW index for a resource.
   3952  *  Used for decoding BST trigger information for notifying users.
   3953  *     unit       - (IN) unit number.
   3954  *     bid        - (IN) BST stat id.
   3955  *     port       - (IN) Unused (retained to maintain consistency).
   3956  *     index      - (IN) SW index for which stat > 0.
   3957  *     gport      - (OUT) gport corresponding to input VOQ.
   3958  *     cosq       - (OUT) cosq corresponding to input VOQ.
   3959  */
   3960 
   3961 int
   3962 _bcm_th3_cosq_bst_map_resource_to_gport_cos(int unit,
   3963     bcm_bst_stat_id_t bid, int port, int index, bcm_gport_t *gport,
   3964     bcm_cos_t *cosq)
   3965 {
   3966     soc_info_t *si = &SOC_INFO(unit);
   3967     _bcm_bst_resource_info_t *pres = NULL;
   3968     int phy_port = 0;
   3969     int mmu_port = 0;
   3970     int inst = 0;
   3971     int mmu_port_base = 0;
   3972     int stats_per_inst = 1;
   3973     int pipe, mmu_chip_port, mmu_global_port;
   3974 
   3975     if (bid >= bcmBstStatIdMaxCount) {
   3976         LOG_INFO(BSL_LS_BCM_COSQ,
   3977             (BSL_META_U(unit,
   3978             "_bcm_th_cosq_bst_map_resource_to_gport_cos: unit=%d bid=0x%x\n"),
   3979             unit, bid));
   3980         return BCM_E_NONE;
   3981     }
   3982 
   3983     pres = _BCM_BST_RESOURCE(unit, bid);
   3984     stats_per_inst = (pres->num_stat_pp) / (pres->num_instance);
   3985     inst = index / stats_per_inst;
   3986     mmu_port_base = inst * SOC_TH3_MMU_PORT_STRIDE;
   3987     index %= stats_per_inst;
   3988 
   3989     switch (bid) {
   3990     case bcmBstStatIdDevice:
   3991         *gport = -1;
   3992         *cosq = BCM_COS_INVALID;
   3993         break;
   3994 
   3995     case bcmBstStatIdIngPool:
   3996     case bcmBstStatIdEgrPool:
   3997     case bcmBstStatIdEgrMCastPool:
   3998         *gport = -1;
   3999         *cosq = index % _TH_MMU_NUM_POOL;
   4000         break;
   4001 
   4002     case bcmBstStatIdPortPool:
   4003         /* Per pipe memory indexed by Local MMU port number*/
   4004         mmu_port= index/_TH_MMU_NUM_POOL;
   4005         phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base];
   4006         *gport = si->port_p2l_mapping[phy_port];
   4007         *cosq = index % _TH_MMU_NUM_POOL;
   4008         break;
   4009 
   4010     case bcmBstStatIdPriGroupHeadroom:
   4011     case bcmBstStatIdPriGroupShared:
   4012         /* Per pipe memory indexed by Local MMU port number*/
   4013         mmu_port = index/_TH_MMU_NUM_PG;
   4014         phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base];
   4015         *gport = si->port_p2l_mapping[phy_port];
   4016         *cosq = index % _TH_MMU_NUM_PG;
   4017         break;
   4018 
   4019     case bcmBstStatIdUcast:
   4020     case bcmBstStatIdMcast:
   4021     case bcmBstStatIdQueueTotal:
   4022         /* Indexed based on chip_queue_number */
   4023         /* Iterate through all ports to retrieve cosq_base and determine port,
   4024          * cosq*/
   4025         _bcm_bst_th3_retrive_port_cosq_from_voq(unit, index, gport, cosq);
   4026         break;
   4027     case bcmBstStatIdEgrPortPoolSharedUcast:
   4028     case bcmBstStatIdEgrPortPoolSharedMcast:
   4029         /* Per pipe memory indexed by MMU chip port number*/
   4030         mmu_chip_port = index/_TH_MMU_NUM_POOL;
   4031         mmu_port = mmu_chip_port % 20; /*pipe offset for chip port number*/
   4032         pipe = index / (20 * _TH_MMU_NUM_POOL);
   4033         mmu_global_port = mmu_port + (pipe * SOC_TH3_MMU_PORT_STRIDE);
   4034         phy_port = si->port_m2p_mapping[mmu_global_port];
   4035         *gport = si->port_p2l_mapping[phy_port];
   4036         *cosq = index % _TH_MMU_NUM_POOL;
   4037         break;
   4038     default:
   4039         break;
   4040     }
   4041 
   4042     return BCM_E_NONE;
   4043 }
   4044 
   4045 #endif
   4046