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

cosq.c (548510B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * COS Queue Management
      8  * Purpose: API to set different cosq, priorities, and scheduler registers.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <soc/defs.h>
     14 #include <sal/core/libc.h>
     15 
     16 #if defined(BCM_TOMAHAWK_SUPPORT)
     17 #include <soc/drv.h>
     18 #include <soc/scache.h>
     19 #include <soc/scache_dictionary.h>
     20 #include <soc/profile_mem.h>
     21 #include <soc/debug.h>
     22 #include <soc/tomahawk.h>
     23 #include <soc/dma.h>
     24 #include <soc/mmu_config.h>
     25 #include <soc/uc.h>
     26 #include <soc/shared/qcm.h>
     27 
     28 
     29 #include <bcm/debug.h>
     30 #include <bcm/error.h>
     31 #include <bcm/cosq.h>
     32 #include <bcm_int/esw/mbcm.h>
     33 #include <bcm_int/esw/stack.h>
     34 #include <bcm_int/esw/cosq.h>
     35 #include <bcm_int/esw/virtual.h>
     36 #include <bcm_int/esw/tomahawk.h>
     37 #include <bcm_int/esw/ecn.h>
     38 #include <bcm_int/esw/oob.h>
     39 #if defined(INCLUDE_PSTATS)
     40 #include <bcm_int/esw/pstats.h>
     41 #endif /* INCLUDE_PSTATS */
     42 #if defined(BCM_TOMAHAWK2_SUPPORT)
     43 #include <bcm_int/esw/tomahawk2.h>
     44 #include <soc/tomahawk2.h>
     45 #endif
     46 #include <bcm_int/esw/pfc_deadlock.h>
     47 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT)
     48 #include <bcm_int/esw/tcb.h>
     49 #endif
     50 #include <bcm_int/esw_dispatch.h>
     51 
     52 #include <bcm_int/bst.h>
     53 
     54 #ifdef BCM_WARM_BOOT_SUPPORT
     55 #include <bcm_int/esw/switch.h>
     56 #endif /* BCM_WARM_BOOT_SUPPORT */
     57 #ifdef BCM_CMICM_SUPPORT
     58 #include <soc/cmicm.h>
     59 #endif
     60 
     61 #define _BCM_TH_NUM_UCAST_QUEUE_PER_PORT 10
     62 #define _BCM_TH_NUM_MCAST_QUEUE_PER_PORT 10
     63 #define _BCM_TH_NUM_SCHEDULER_PER_PORT   10
     64 #define _BCM_TH_NUM_CPU_MCAST_QUEUE      48
     65 #define _BCM_TH_NUM_BUFFER_PER_PIPE      2
     66 
     67 #define TH_WRED_CELL_FIELD_MAX       0xffff
     68 
     69 #define _TH_NUM_PIPES 4
     70 
     71 /* COS default value for TH is assumed to be 8 */
     72 #define BCM_TH_COS_DEFAULT  8
     73 /* COS max value for TH is assumed to be 10 */
     74 #define BCM_TH_COS_MAX  10
     75 
     76 /* TH supports 16 SAFC priority */
     77 #define _BCM_TH_NUM_SAFC_CLASS  16
     78 
     79 /* TH supports 8 PFC priority */
     80 #define _BCM_TH_NUM_PFC_CLASS   8
     81 
     82 #define _BCM_TH_NUM_TIME_DOMAIN    4
     83 
     84 typedef struct _bcm_th_cosq_time_info_s {
     85     uint32 ref_count;   
     86 } _bcm_th_cosq_time_info_t;
     87 
     88 /* WRED can be enabled at per UC queue / port / service pool basis
     89 MMU_WRED_AVG_QSIZE used entry: (330 + 132 + 4) = 466
     90 329 ~   0: Unicast Queue
     91 461 ~ 330: Port Service Pool (port 0 to 32)           
     92                    Address = 330 + {PORTID[5:0], SPID[1:0]} per PIPE           
     93                    Each Port's service pool is addressed by Address[1:0] of this memory address.
     94 465 ~ 462: Global Service Pool      
     95                    462: Global Service Pool 0      
     96                    463: Global Service Pool 1      
     97                    464: Global Service Pool 2      
     98                    465: Global Service Pool 3
     99 */
    100 STATIC _bcm_th_cosq_time_info_t time_domain_info[BCM_MAX_NUM_UNITS][_BCM_TH_NUM_TIME_DOMAIN] = {
    101     {
    102         {466}, /* Default all entries are pointing to TIME_0 */
    103         {0},
    104         {0},
    105         {0}
    106     }
    107 };
    108 
    109 /* WRED resolution table */
    110 #define _BCM_TH_NUM_WRED_RESOLUTION_TABLE   4
    111 STATIC uint32 _bcm_th_wred_resolution_tbl[_BCM_TH_NUM_WRED_RESOLUTION_TABLE] = {
    112     1,
    113     0,
    114     0,
    115     0,
    116 };
    117 
    118 typedef struct _bcm_th_cosq_cpu_cosq_config_s {
    119     /* All MC queues have DB[idx 0] and MCQE[idx 1] space */
    120     int q_min_limit[2];
    121     int q_shared_limit[2];
    122     uint8 q_limit_dynamic[2];
    123     uint8 q_limit_enable[2];
    124     uint8 q_color_limit_enable[2];
    125     uint8 enable;
    126 } _bcm_th_cosq_cpu_cosq_config_t;
    127 
    128 typedef struct _bcm_th_cosq_node_s {
    129     bcm_gport_t gport;
    130     int numq;
    131     int level;
    132     int hw_index;
    133     int in_use;
    134     bcm_gport_t parent_gport;
    135 } _bcm_th_cosq_node_t;
    136 
    137 typedef struct _bcm_th_cosq_port_info_s {
    138     _bcm_th_cosq_node_t ucast[_BCM_TH_NUM_UCAST_QUEUE_PER_PORT];
    139     _bcm_th_cosq_node_t mcast[_BCM_TH_NUM_MCAST_QUEUE_PER_PORT];
    140     _bcm_th_cosq_node_t sched[_BCM_TH_NUM_SCHEDULER_PER_PORT];
    141 } _bcm_th_cosq_port_info_t;
    142 
    143 typedef struct _bcm_th_cosq_cpu_port_info_s {
    144     _bcm_th_cosq_node_t sched[_BCM_TH_NUM_SCHEDULER_PER_PORT];
    145     _bcm_th_cosq_node_t mcast[_BCM_TH_NUM_CPU_MCAST_QUEUE];
    146 } _bcm_th_cosq_cpu_port_info_t;
    147 
    148 typedef struct _bcm_th_mmu_info_s {
    149     int gport_tree_created; /* FALSE: No GPORT tree exists */
    150     _bcm_th_cosq_port_info_t *_bcm_th_port_info;
    151     _bcm_th_cosq_cpu_port_info_t *_bcm_th_cpu_port_info;
    152     int ing_shared_limit[_TH_XPES_PER_DEV];
    153     int egr_db_shared_limit[_TH_XPES_PER_DEV];
    154     int egr_qe_shared_limit[_TH_XPES_PER_DEV];
    155 } _bcm_th_mmu_info_t;
    156 
    157 STATIC _bcm_th_mmu_info_t *_bcm_th_mmu_info[BCM_MAX_NUM_UNITS]; /* MMU info */
    158 STATIC _bcm_th_cosq_port_info_t *_bcm_th_cosq_port_info[BCM_MAX_NUM_UNITS];
    159 STATIC _bcm_th_cosq_cpu_port_info_t *_bcm_th_cosq_cpu_port_info[BCM_MAX_NUM_UNITS];
    160 STATIC soc_profile_mem_t *_bcm_th_cos_map_profile[BCM_MAX_NUM_UNITS];
    161 STATIC soc_profile_mem_t *_bcm_th_wred_profile[BCM_MAX_NUM_UNITS];
    162 STATIC soc_profile_reg_t *_bcm_th_prio2cos_profile[BCM_MAX_NUM_UNITS];
    163 STATIC soc_profile_mem_t *_bcm_th_ifp_cos_map_profile[BCM_MAX_NUM_UNITS];
    164 STATIC _bcm_th_cosq_cpu_cosq_config_t
    165             *_bcm_th_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][SOC_TH_NUM_CPU_QUEUES];
    166 
    167 typedef enum {
    168     _BCM_TH_COSQ_TYPE_UCAST,
    169     _BCM_TH_COSQ_TYPE_MCAST
    170 } _bcm_th_cosq_type_t;
    171 
    172 /* Number of COSQs configured for this unit */
    173 #define _TH_NUM_COS(unit) NUM_COS(unit)
    174 
    175 #define _TH_PORT_NUM_COS(unit, port) \
    176     ((IS_CPU_PORT(unit, port)) ? NUM_CPU_COSQ(unit) : \
    177         (IS_LB_PORT(unit, port)) ? 10 : _TH_NUM_COS(unit))
    178 
    179 
    180 #define _BCM_TH_MMU_INFO(unit) _bcm_th_mmu_info[(unit)]
    181 
    182 #ifdef BCM_WARM_BOOT_SUPPORT
    183 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    184 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
    185 #define BCM_WB_VERSION_1_2                SOC_SCACHE_VERSION(1,2)
    186 #define BCM_WB_VERSION_1_3                SOC_SCACHE_VERSION(1,3)
    187 #define BCM_WB_VERSION_1_4                SOC_SCACHE_VERSION(1,4)
    188 #define BCM_WB_VERSION_1_5                SOC_SCACHE_VERSION(1,5)
    189 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_5
    190 
    191 
    192 STATIC int
    193 _bcm_th_cosq_wb_alloc(int unit)
    194 {
    195     _bcm_th_mmu_info_t *mmu_info = NULL;
    196     soc_scache_handle_t scache_handle;
    197     uint8 *scache_ptr = NULL;
    198     int rv, alloc_size = 0, max_size = 4096 * 3;
    199     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
    200 
    201     mmu_info = _bcm_th_mmu_info[unit];
    202     if (mmu_info == NULL) {
    203         return BCM_E_INIT;
    204     }
    205 
    206     cpu_port_info = _bcm_th_cosq_cpu_port_info[unit];
    207     if (cpu_port_info == NULL) {
    208         return BCM_E_INIT;
    209     }
    210 
    211     /*
    212      * Sync _bcm_th_mmu_info[unit]->ing_shared_limit/
    213      * egr_db_shared_limit/egr_db_shared_limit
    214      */
    215     alloc_size += 3 * sizeof(int);
    216 
    217     /*
    218      * Sync _bcm_th_cosq_cpu_port_info structure
    219      */
    220 
    221     alloc_size += sizeof(_bcm_th_cosq_cpu_port_info_t);
    222 
    223     /*
    224      * Sync the ref_count of IFP_COS_MAPm/COS_MAPm
    225      */
    226     alloc_size += (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TH_MMU_NUM_INT_PRI) *
    227                    sizeof(uint16);
    228 
    229     /*
    230      * Added in BCM_WB_VERSION_1_1
    231      * Sync _bcm_th_cosq_cpu_cosq_config_t structure for all CPU queues
    232      */
    233     alloc_size += (SOC_TH_NUM_CPU_QUEUES *
    234                    sizeof(_bcm_th_cosq_cpu_cosq_config_t));
    235 
    236     /*
    237      * Added in BCM_WB_VERSION_1_1
    238      * Sync num_cos value
    239      */
    240     alloc_size += sizeof(int);
    241 
    242     /*
    243      * Added in BCM_WB_VERSION_1_1
    244      * Sync _bcm_pfc_deadlock_control_t structure
    245      * Only for TH/TH+
    246      */
    247     if (SOC_IS_TOMAHAWK(unit) &&
    248         soc_feature(unit, soc_feature_pfc_deadlock)) {
    249         alloc_size += sizeof(_bcm_pfc_deadlock_control_t);
    250     }  
    251 
    252    /*
    253      * Added TIME_DOMAIN ref count
    254      */
    255     alloc_size += sizeof(_bcm_th_cosq_time_info_t);
    256 
    257 #ifdef BCM_TOMAHAWK_SUPPORT 
    258     if (soc_feature(unit, soc_feature_ecn_wred)) {
    259         uint32 scache_size = 0;
    260         BCM_IF_ERROR_RETURN(
    261             bcmi_xgs5_ecn_scache_size_get(unit, &scache_size));
    262         alloc_size += scache_size;
    263     }
    264 #endif
    265 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB)
    266     if (soc_feature(unit, soc_feature_tcb)){
    267 #ifdef BCM_TOMAHAWK2_SUPPORT
    268         alloc_size += sizeof(uint16);
    269 #endif
    270     }
    271 #else
    272     alloc_size += sizeof(uint16);
    273 #endif
    274 
    275     /*
    276      * Added in BCM_WB_VERSION_1_4
    277      * Second around sync _bcm_pfc_deadlock_control_t structure
    278      */
    279     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
    280         alloc_size += _bcm_pfc_deadlock_alloc_size(unit);
    281     }
    282 
    283     /*
    284      * Added in BCM_WB_VERSION_1_5
    285      * Sync _bcm_th_cosq_cpu_cosq_config_t structure for all CPU queues
    286      */
    287     alloc_size += (_BCM_TH_NUM_WRED_RESOLUTION_TABLE *
    288                    sizeof(uint32));
    289 
    290     /* Reserving some space scache for future usecase (max_size) */
    291     if (alloc_size < max_size) {
    292         alloc_size = max_size;
    293     } else {
    294         /* Required size more than max size allocated for Cosq */
    295         return BCM_E_INIT;
    296     }
    297 
    298     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    299 
    300     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
    301                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
    302 
    303     if (rv == BCM_E_NOT_FOUND) {
    304         rv = BCM_E_NONE;
    305     }
    306 
    307     return rv;
    308 }
    309 #endif /* BCM_WARM_BOOT_SUPPORT */
    310 
    311 /*
    312  * index: degree, value: contangent(degree) * 100
    313  * max value is 0xffff (16-bit) at 0 degree
    314  * Same as TD2.
    315  */
    316 STATIC int
    317 _bcm_th_cotangent_lookup_table[] =
    318 {
    319     /*  0.. 5 */  65535, 5728, 2863, 1908, 1430, 1143,
    320     /*  6..11 */    951,  814,  711,  631,  567,  514,
    321     /* 12..17 */    470,  433,  401,  373,  348,  327,
    322     /* 18..23 */    307,  290,  274,  260,  247,  235,
    323     /* 24..29 */    224,  214,  205,  196,  188,  180,
    324     /* 30..35 */    173,  166,  160,  153,  148,  142,
    325     /* 36..41 */    137,  132,  127,  123,  119,  115,
    326     /* 42..47 */    111,  107,  103,  100,   96,   93,
    327     /* 48..53 */     90,   86,   83,   80,   78,   75,
    328     /* 54..59 */     72,   70,   67,   64,   62,   60,
    329     /* 60..65 */     57,   55,   53,   50,   48,   46,
    330     /* 66..71 */     44,   42,   40,   38,   36,   34,
    331     /* 72..77 */     32,   30,   28,   26,   24,   23,
    332     /* 78..83 */     21,   19,   17,   15,   14,   12,
    333     /* 84..89 */     10,    8,    6,    5,    3,    1,
    334     /* 90     */      0
    335 };
    336 
    337 /*
    338  * Given a slope (angle in degrees) from 0 to 90, return the number of cells
    339  * in the range from 0% drop probability to 100% drop probability.
    340  * Same as TD2.
    341  */
    342 STATIC int
    343 _bcm_th_angle_to_cells(int angle)
    344 {
    345     return (_bcm_th_cotangent_lookup_table[angle]);
    346 }
    347 
    348 /*
    349  * Given a number of packets in the range from 0% drop probability
    350  * to 100% drop probability, return the slope (angle in degrees).
    351  * Same as TD2.
    352  */
    353 STATIC int
    354 _bcm_th_cells_to_angle(int packets)
    355 {
    356     int angle;
    357 
    358     for (angle = 90; angle >= 0 ; angle--) {
    359         if (packets <= _bcm_th_cotangent_lookup_table[angle]) {
    360             break;
    361         }
    362     }
    363     return angle;
    364 }
    365 
    366 
    367 /*
    368  *  Convert HW drop probability to percent value
    369  *  Same as TD2.
    370  */
    371 STATIC int
    372 _bcm_th_hw_drop_prob_to_percent[] = {
    373     0,     /* 0  */
    374     1,     /* 1  */
    375     2,     /* 2  */
    376     3,     /* 3  */
    377     4,     /* 4  */
    378     5,     /* 5  */
    379     6,     /* 6  */
    380     7,     /* 7  */
    381     8,     /* 8  */
    382     9,     /* 9  */
    383     10,    /* 10 */
    384     25,    /* 11 */
    385     50,    /* 12 */
    386     75,    /* 13 */
    387     100,   /* 14 */
    388     -1     /* 15 */
    389 };
    390 
    391 STATIC int
    392 _bcm_th_percent_to_drop_prob(int percent)
    393 {
    394    int i;
    395 
    396    for (i = 14; i > 0 ; i--) {
    397       if (percent >= _bcm_th_hw_drop_prob_to_percent[i]) {
    398           break;
    399       }
    400    }
    401    return i;
    402 }
    403 
    404 STATIC int
    405 _bcm_th_drop_prob_to_percent(int drop_prob) {
    406    return (_bcm_th_hw_drop_prob_to_percent[drop_prob]);
    407 }
    408 
    409 /*
    410  * Function:
    411  *     _bcm_th_cosq_node_get
    412  * Purpose:
    413  *     Get internal information of queue group or scheduler type GPORT
    414  * Parameters:
    415  *     unit       - (IN) unit number
    416  *     gport      - (IN) queue group/scheduler GPORT identifier
    417  *     modid      - (OUT) module identifier
    418  *     port       - (OUT) port number
    419  *     id         - (OUT) queue group or scheduler identifier
    420  *     node       - (OUT) node structure for the specified GPORT
    421  * Returns:
    422  *     BCM_E_XXX
    423  */
    424 STATIC int
    425 _bcm_th_cosq_node_get(int unit, bcm_gport_t gport, bcm_module_t *modid,
    426                       bcm_port_t *port, int *id, _bcm_th_cosq_node_t **node)
    427 {
    428     _bcm_th_cosq_port_info_t *port_info = NULL;
    429     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
    430     _bcm_th_cosq_node_t *node_base = NULL;
    431     bcm_module_t modid_out;
    432     bcm_port_t port_out;
    433     uint32 encap_id;
    434     int index;
    435 
    436     if (_bcm_th_cosq_port_info[unit] == NULL) {
    437         return BCM_E_INIT;
    438     }
    439     if (_bcm_th_cosq_cpu_port_info[unit] == NULL) {
    440         return BCM_E_INIT;
    441     }
    442 
    443     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    444         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    445         port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
    446     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    447         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    448         port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
    449     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
    450         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    451         port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff;
    452     } else {
    453         return BCM_E_PORT;
    454     }
    455 
    456     if (!SOC_PORT_VALID(unit, port_out)) {
    457         return BCM_E_PORT;
    458     }
    459     if (IS_CPU_PORT(unit, port_out)) {
    460         cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][port_out];
    461     } else {
    462         port_info = &_bcm_th_cosq_port_info[unit][port_out];
    463     }
    464 
    465     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    466         encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
    467         index = encap_id;
    468         if (index >= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) {
    469             return BCM_E_PORT;
    470         }
    471         node_base = port_info->ucast;
    472     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    473         encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport);
    474         index = encap_id;
    475         if (!IS_CPU_PORT(unit, port_out) && (index >= _BCM_TH_NUM_MCAST_QUEUE_PER_PORT)) {
    476             return BCM_E_PORT;
    477         }
    478         if (IS_CPU_PORT(unit, port_out) && (index >= _BCM_TH_NUM_CPU_MCAST_QUEUE)) {
    479             return BCM_E_PORT;
    480         }
    481         if (IS_CPU_PORT(unit, port_out)) {
    482             node_base = cpu_port_info->mcast;
    483         } else {
    484             node_base = port_info->mcast;
    485         }
    486     } else { /* scheduler */
    487         encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 16) & 0x3ff;
    488         index = encap_id;
    489         if (index >= _BCM_TH_NUM_SCHEDULER_PER_PORT) {
    490             return BCM_E_PORT;
    491         }
    492         if (IS_CPU_PORT(unit, port_out)) {
    493             node_base = cpu_port_info->sched;
    494         } else {
    495             node_base = port_info->sched;
    496         }
    497     }
    498 
    499     if ((node_base == NULL) ||
    500         (node_base[index].numq == 0) ||
    501         (node_base[index].in_use == 0)) {
    502         return BCM_E_NOT_FOUND;
    503     }
    504 
    505     if (modid != NULL) {
    506         *modid = modid_out;
    507     }
    508     if (port != NULL) {
    509         *port = port_out;
    510     }
    511     if (id != NULL) {
    512         *id = encap_id;
    513     }
    514     if (node != NULL) {
    515         *node = &node_base[index];
    516     }
    517 
    518     return BCM_E_NONE;
    519 }
    520 
    521 /*
    522  * Function:
    523  *     _bcm_th_cosq_localport_resolve
    524  * Purpose:
    525  *     Resolve GPORT if it is a local port
    526  * Parameters:
    527  *     unit       - (IN) unit number
    528  *     gport      - (IN) GPORT identifier
    529  *     local_port - (OUT) local port number
    530  * Returns:
    531  *     BCM_E_XXX
    532  */
    533 STATIC int
    534 _bcm_th_cosq_localport_resolve(int unit, bcm_gport_t gport,
    535                                bcm_port_t *local_port)
    536 {
    537     bcm_module_t module;
    538     bcm_port_t port;
    539     bcm_trunk_t trunk;
    540     int id, result, rv;
    541 
    542     if (!BCM_GPORT_IS_SET(gport)) {
    543         if (!SOC_PORT_VALID(unit, gport)) {
    544             return BCM_E_PORT;
    545         }
    546         *local_port = gport;
    547         return BCM_E_NONE;
    548     }
    549 
    550     rv = _bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id);
    551     if (rv == BCM_E_PORT) {
    552         /* returning E_PARAM when invalid gport is given as param */
    553         return BCM_E_PARAM;
    554     } else if (BCM_FAILURE(rv)) {
    555         return rv;
    556     }
    557 
    558     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result));
    559     if (result == FALSE) {
    560         return BCM_E_PARAM;
    561     }
    562 
    563     *local_port = port;
    564 
    565     return BCM_E_NONE;
    566 }
    567 
    568 STATIC int
    569 _bcm_th_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
    570                            int *p_pool_start, int *p_pool_end)
    571 {
    572     int local_port;
    573     int pool;
    574 
    575     if (cosq == BCM_COS_INVALID) {
    576         if (p_pool_start && p_pool_end) {
    577             *p_pool_start = 0;
    578             *p_pool_end = 3;
    579             return BCM_E_NONE;
    580         } else {
    581             return BCM_E_PARAM;
    582         }
    583     }
    584 
    585     BCM_IF_ERROR_RETURN
    586         (_bcm_th_cosq_index_resolve(unit, gport, cosq,
    587                                     _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL,
    588                                     &local_port, &pool, NULL));
    589 
    590     if (p_pool_start) {
    591         *p_pool_start = pool;
    592     }
    593     if (p_pool_end) {
    594         *p_pool_end = pool;
    595     }
    596     return BCM_E_NONE;
    597 }
    598 
    599 STATIC int
    600 _bcm_th_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri,
    601                             int *p_pg_start, int *p_pg_end)
    602 {
    603     bcm_port_t local_port;
    604     uint32  rval,pool;
    605     soc_reg_t reg = INVALIDr;
    606     static const soc_reg_t prigroup_reg[] = {
    607         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
    608     };
    609     static const soc_field_t prigroup_field[] = {
    610         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
    611         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
    612         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
    613         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
    614     };
    615 
    616     if (pri == BCM_COS_INVALID) {
    617         *p_pg_start = 0;
    618         *p_pg_end = 7;
    619         return BCM_E_NONE;
    620     }
    621 
    622     BCM_IF_ERROR_RETURN
    623             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
    624 
    625     if (!SOC_PORT_VALID(unit, local_port)) {
    626         return BCM_E_PORT;
    627     }
    628 
    629     if (pri >= _TH_MMU_NUM_INT_PRI) {
    630         return BCM_E_PARAM;
    631     }
    632        /* get PG for port using Port+Cos */
    633     if (pri < (_TH_MMU_NUM_INT_PRI / 2)) {
    634         reg = prigroup_reg[0];
    635     } else {
    636         reg = prigroup_reg[1];
    637     }
    638 
    639     SOC_IF_ERROR_RETURN
    640         (soc_reg32_get(unit, reg, local_port, 0, &rval));
    641         pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]);
    642 
    643     if (p_pg_start) {
    644         *p_pg_start = pool;
    645     }
    646 
    647     if (p_pg_end) {
    648         *p_pg_end = pool;
    649     }
    650 
    651     return BCM_E_NONE;
    652 }
    653 
    654 
    655 /*
    656  * This function is used to get shared pool
    657  * for given Ingress [Port, Priority]
    658  */
    659 STATIC int
    660 _bcm_th_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_t pri,
    661                             int *p_pool_start, int *p_pool_end)
    662 {
    663     int local_port;
    664     uint32 rval, pool;
    665     int pri_grp;
    666     static const soc_field_t prigroup_spid_field[] = {
    667         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
    668         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
    669     };
    670 
    671     if (pri == BCM_COS_INVALID) {
    672         if (p_pool_start && p_pool_end) {
    673             *p_pool_start = 0;
    674             *p_pool_end = 3;
    675             return BCM_E_NONE;
    676         } else {
    677             return BCM_E_PARAM;
    678         }
    679     }
    680 
    681     if ((pri < 0) || (pri >= _TH_MMU_NUM_INT_PRI)) {
    682         /* Error. Input pri > Max Pri_Grp */
    683         return BCM_E_PARAM;
    684     }
    685 
    686     BCM_IF_ERROR_RETURN
    687         (_bcm_th_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp));
    688 
    689     BCM_IF_ERROR_RETURN
    690             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
    691 
    692     if (!SOC_PORT_VALID(unit, local_port)) {
    693         return BCM_E_PORT;
    694     }
    695 
    696     if (pri_grp >= _TH_MMU_NUM_PG) {
    697         return BCM_E_PARAM;
    698     }
    699 
    700     SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval));
    701     pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval,
    702                              prigroup_spid_field[pri_grp]);
    703 
    704     if (p_pool_start) {
    705         *p_pool_start = pool;
    706     }
    707     if (p_pool_end) {
    708         *p_pool_end = pool;
    709     }
    710     return BCM_E_NONE;
    711 }
    712 
    713 /*
    714  * This function is used to get shared pool
    715  * for given Ingress [Port, Priority_group]
    716  */
    717 STATIC int
    718 _bcm_th_cosq_ingress_sp_get_by_pg(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp,
    719                             int *p_pool_start, int *p_pool_end)
    720 {
    721     int local_port;
    722     uint32 rval, pool;
    723     static const soc_field_t prigroup_spid_field[] = {
    724         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
    725         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
    726     };
    727 
    728     if (pri_grp == BCM_COS_INVALID) {
    729         if (p_pool_start && p_pool_end) {
    730             *p_pool_start = 0;
    731             *p_pool_end = 3;
    732             return BCM_E_NONE;
    733         } else {
    734             return BCM_E_PARAM;
    735         }
    736     }
    737 
    738     BCM_IF_ERROR_RETURN
    739             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
    740 
    741     if (!SOC_PORT_VALID(unit, local_port)) {
    742         return BCM_E_PORT;
    743     }
    744 
    745     if (pri_grp >= _TH_MMU_NUM_PG) {
    746         return BCM_E_PARAM;
    747     }
    748 
    749     SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval));
    750     pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval,
    751                              prigroup_spid_field[pri_grp]);
    752 
    753     if (p_pool_start) {
    754         *p_pool_start = pool;
    755     }
    756     if (p_pool_end) {
    757         *p_pool_end = pool;
    758     }
    759     return BCM_E_NONE;
    760 }
    761 
    762 
    763 /*
    764  * This function is used to get headroom pool
    765  * for given Ingress [Port, Priority]
    766  */
    767 STATIC int
    768 _bcm_th_cosq_ingress_hdrm_pool_get(int unit, bcm_gport_t gport,
    769                                    bcm_cos_t pri,
    770                                    int *p_hdrm_pool_start,
    771                                    int *p_hdrm_pool_end)
    772 {
    773     int local_port;
    774     uint32 rval, hdrm_pool;
    775     int pri_grp;
    776     static const soc_field_t prigroup_hpid_field[] = {
    777         PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf,
    778         PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf
    779     };
    780 
    781     if (pri == BCM_COS_INVALID) {
    782         if (p_hdrm_pool_start && p_hdrm_pool_end) {
    783             *p_hdrm_pool_start = 0;
    784             *p_hdrm_pool_end = 3;
    785             return BCM_E_NONE;
    786         } else {
    787             return BCM_E_PARAM;
    788         }
    789     }
    790 
    791     if ((pri < 0) || (pri >= _TH_MMU_NUM_INT_PRI)) {
    792         /* Error. Input pri > Max Pri_Grp */
    793         return BCM_E_PARAM;
    794     }
    795 
    796     BCM_IF_ERROR_RETURN
    797         (_bcm_th_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp));
    798 
    799     BCM_IF_ERROR_RETURN
    800             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
    801 
    802     if (!SOC_PORT_VALID(unit, local_port)) {
    803         return BCM_E_PORT;
    804     }
    805 
    806     if (pri_grp >= _TH_MMU_NUM_PG) {
    807         return BCM_E_PARAM;
    808     }
    809 
    810     SOC_IF_ERROR_RETURN(READ_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, &rval));
    811     hdrm_pool = soc_reg_field_get(unit, THDI_HDRM_PORT_PG_HPIDr, rval,
    812                                   prigroup_hpid_field[pri_grp]);
    813 
    814     if (p_hdrm_pool_start) {
    815         *p_hdrm_pool_start = hdrm_pool;
    816     }
    817     if (p_hdrm_pool_end) {
    818         *p_hdrm_pool_end = hdrm_pool;
    819     }
    820 
    821     return BCM_E_NONE;
    822 }
    823 
    824 /*
    825  * Function:
    826  *     _bcm_th_cosq_port_cos_resolve
    827  * Purpose:
    828  *     Find UC/MC queue gport for a given logical port
    829  *     and cos value.
    830  * Parameters:
    831  *     unit      - (IN) unit number
    832  *     port      - (IN) logical port
    833  *     cos       - (IN) cos value
    834  *     style     - (IN) index style
    835  *                 (_BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE or
    836  *                 _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE)
    837  *     gport     - (OUT) Queue gport
    838  * Returns:
    839  *     BCM_E_XXX
    840  */
    841 int
    842 _bcm_th_cosq_port_cos_resolve(int unit, bcm_port_t port, bcm_cos_t cos,
    843                               _bcm_th_cosq_index_style_t style,
    844                               bcm_gport_t *gport)
    845 {
    846     _bcm_th_cosq_port_info_t *port_info = NULL;
    847     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
    848 
    849     if (gport == NULL) {
    850         return BCM_E_PARAM;
    851     }
    852 
    853     if (_bcm_th_cosq_port_info[unit] == NULL) {
    854         return BCM_E_INIT;
    855     }
    856     if (_bcm_th_cosq_cpu_port_info[unit] == NULL) {
    857         return BCM_E_INIT;
    858     }
    859 
    860     if ((IS_CPU_PORT(unit, port)) &&
    861         (style == _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE)) {
    862         return BCM_E_PARAM;
    863     }
    864 
    865     if (cos < 0) {
    866         return BCM_E_PARAM;
    867     }
    868 
    869     if (!SOC_PORT_VALID(unit, port)) {
    870         return BCM_E_PORT;
    871     }
    872 
    873     if (_BCM_TH_MMU_INFO(unit)->gport_tree_created != TRUE) {
    874         return BCM_E_INTERNAL;
    875     }
    876 
    877     if (IS_CPU_PORT(unit, port)) {
    878         cpu_port_info = _bcm_th_cosq_cpu_port_info[unit];
    879     } else {
    880         port_info = &_bcm_th_cosq_port_info[unit][port];
    881     }
    882 
    883     if (style == _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE) {
    884         if (cos >= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) {
    885             return BCM_E_PARAM;
    886         }
    887         *gport = port_info->ucast[cos].gport;
    888     } else if (style == _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE) {
    889         if (IS_CPU_PORT(unit, port)) {
    890             if (cos >= _BCM_TH_NUM_CPU_MCAST_QUEUE) {
    891                 return BCM_E_PARAM;
    892             }
    893             *gport = cpu_port_info->mcast[cos].gport;
    894         } else {
    895             if (cos >= _BCM_TH_NUM_MCAST_QUEUE_PER_PORT) {
    896                 return BCM_E_PARAM;
    897             }
    898             *gport = port_info->mcast[cos].gport;
    899         }
    900     } else {
    901         return BCM_E_INTERNAL;
    902     }
    903 
    904     return BCM_E_NONE;
    905 }
    906 
    907 int
    908 _bcm_th_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid,
    909                           bcm_port_t *port, bcm_trunk_t *trunk_id, int *id,
    910                           int *qnum)
    911 {
    912     _bcm_th_cosq_node_t *node;
    913 
    914     BCM_IF_ERROR_RETURN
    915         (_bcm_th_cosq_node_get(unit, gport, modid, port, id, &node));
    916     *trunk_id = -1;
    917 
    918     if (qnum) {
    919         if (node->hw_index == -1) {
    920             return BCM_E_PARAM;
    921         }
    922         *qnum = node->hw_index;
    923     }
    924 
    925     return BCM_E_NONE;
    926 }
    927 
    928 /*
    929  * Function:
    930  *     _bcm_th_cosq_index_resolve
    931  * Purpose:
    932  *     Find hardware index for the given port/cosq
    933  * Parameters:
    934  *     unit       - (IN) unit number
    935  *     port       - (IN) port number or GPORT identifier
    936  *     cosq       - (IN) COS queue number
    937  *     style      - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX)
    938  *     local_port - (OUT) local port number
    939  *     index      - (OUT) result index
    940  *     count      - (OUT) number of index
    941  * Returns:
    942  *     BCM_E_XXX
    943  */
    944 int
    945 _bcm_th_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
    946                            _bcm_th_cosq_index_style_t style,
    947                            bcm_port_t *local_port, int *index, int *count)
    948 {
    949     bcm_port_t resolved_port;
    950     soc_info_t *si;
    951     int resolved_index = -1;
    952     int id, startq, numq = 0;
    953     int phy_port, pipe;
    954     int uc_base = 0, mc_base = 0, cpu_mc_base = 0; /* Q base number */
    955     int mmu_port; /* global mmu port number */
    956     int local_mmu_port; /* local mmu port number - local to per pipe */
    957     _bcm_th_cosq_node_t *node;
    958     uint32 entry0[SOC_MAX_MEM_WORDS];
    959     soc_mem_t mem;
    960 
    961     si = &SOC_INFO(unit);
    962 
    963     if (cosq < -1) {
    964         return BCM_E_PARAM;
    965     } else if (cosq == -1) {
    966         startq = 0;
    967         numq = NUM_COS(unit);
    968     } else {
    969         startq = cosq;
    970         numq = 1;
    971     }
    972 
    973     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
    974         BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
    975         BCM_GPORT_IS_SCHEDULER(port)) {
    976         BCM_IF_ERROR_RETURN
    977             (_bcm_th_cosq_node_get(unit, port, NULL, &resolved_port, &id,
    978                                    &node));
    979         if (resolved_port < 0) {
    980             return BCM_E_PORT;
    981         }
    982     } else {
    983         BCM_IF_ERROR_RETURN
    984             (_bcm_th_cosq_localport_resolve(unit, port, &resolved_port));
    985         if (resolved_port < 0) {
    986             return BCM_E_PORT;
    987         }
    988         node = NULL;
    989         numq = (IS_CPU_PORT(unit, resolved_port)) ? NUM_CPU_COSQ(unit) : NUM_COS(unit);
    990     }
    991     phy_port = si->port_l2p_mapping[resolved_port];
    992     mmu_port = si->port_p2m_mapping[phy_port];
    993     local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1);
    994     mc_base = si->port_cosq_base[resolved_port];
    995     uc_base = si->port_uc_cosq_base[resolved_port];
    996 
    997     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, resolved_port, &pipe));
    998 
    999     switch (style) {
   1000         case _BCM_TH_COSQ_INDEX_STYLE_WRED_DEVICE:
   1001             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1002                 return BCM_E_PARAM;
   1003             }
   1004             if ((port == -1) || (cosq == -1)) {
   1005                 numq = _TH_MMU_NUM_POOL; /* 4 Global Service Pools */
   1006                 resolved_index = 462;
   1007             } else {
   1008                 BCM_IF_ERROR_RETURN
   1009                     (_bcm_th_cosq_egress_sp_get(unit, port, cosq,
   1010                                                 &resolved_index,
   1011                                                 NULL));
   1012                 numq = 1;
   1013                 resolved_index += 462;
   1014             }
   1015             break;
   1016         case _BCM_TH_COSQ_INDEX_STYLE_WRED_PORT:
   1017             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1018                 return BCM_E_PARAM;
   1019             }
   1020             resolved_index = 0;
   1021             if (cosq != -1) {
   1022                 BCM_IF_ERROR_RETURN
   1023                     (_bcm_th_cosq_egress_sp_get(unit, port, cosq,
   1024                                                 &resolved_index,
   1025                                                 NULL));
   1026             }
   1027             resolved_index += SOC_TH_NUM_UC_QUEUES_PER_PIPE +
   1028                               (local_mmu_port * 4);
   1029             numq = (cosq == -1) ? 4: 1;
   1030             break;
   1031         case _BCM_TH_COSQ_INDEX_STYLE_WRED_QUEUE:
   1032             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1033                 return BCM_E_PARAM;
   1034             }
   1035             resolved_index = local_mmu_port * _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
   1036             if (cosq != -1) {
   1037                 if (cosq >= NUM_COS(unit)) {
   1038                     return BCM_E_PARAM;
   1039                 }
   1040                 resolved_index += cosq;
   1041             }
   1042             numq = (cosq == -1) ? NUM_COS(unit): 1;
   1043             break;
   1044         case _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL:
   1045             if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) {
   1046                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1047                     /* regular unicast queue */
   1048                     resolved_index = (uc_base + (node->hw_index %
   1049                                        _BCM_TH_NUM_UCAST_QUEUE_PER_PORT));
   1050                     mem = MMU_THDU_Q_TO_QGRP_MAPm;
   1051                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1052                     if (IS_CPU_PORT(unit, resolved_port)) {
   1053                         cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   1054                         resolved_index = cpu_mc_base +
   1055                                          ((node->hw_index - cpu_mc_base) %
   1056                                            _BCM_TH_NUM_CPU_MCAST_QUEUE);
   1057                     } else {
   1058                         resolved_index = (mc_base + (node->hw_index %
   1059                                            _BCM_TH_NUM_MCAST_QUEUE_PER_PORT));
   1060                     }
   1061                     mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   1062                 } else { /* scheduler */
   1063                     return BCM_E_PARAM;
   1064                 }
   1065             } else { /* node == NULL */
   1066                 numq = si->port_num_cosq[resolved_port];
   1067                 if (startq >= numq) {
   1068                     return BCM_E_PARAM;
   1069                 }
   1070                 resolved_index = (local_mmu_port *
   1071                                   _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) + startq;
   1072                 mem = MMU_THDU_Q_TO_QGRP_MAPm;
   1073             }
   1074             mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe];
   1075 
   1076             SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index,
   1077                                 entry0));
   1078             resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf);
   1079             break;
   1080         case _BCM_TH_COSQ_INDEX_STYLE_COS:
   1081             if (node) {
   1082                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1083                      resolved_index = node->hw_index %
   1084                                       _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
   1085                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1086                      if (IS_CPU_PORT(unit, resolved_port)) {
   1087                          cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   1088                          resolved_index = (node->hw_index - cpu_mc_base) %
   1089                                           NUM_CPU_COSQ(unit);
   1090                      } else {
   1091                          resolved_index = node->hw_index %
   1092                                           _BCM_TH_NUM_MCAST_QUEUE_PER_PORT;
   1093                      }
   1094                 } else {
   1095                      resolved_index = node->hw_index %
   1096                                       _BCM_TH_NUM_SCHEDULER_PER_PORT;
   1097                 }
   1098             } else {
   1099                 resolved_index = startq;
   1100             }
   1101             break;
   1102         case _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE:
   1103             /* Return hw_index for given unicast queue gport */
   1104             if (node) {
   1105                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   1106                      resolved_index = (uc_base + (node->hw_index %
   1107                                         _BCM_TH_NUM_UCAST_QUEUE_PER_PORT));
   1108                 } else {
   1109                     return BCM_E_PARAM;
   1110                 }
   1111             } else {
   1112                 if (startq >= numq) {
   1113                     return BCM_E_PARAM;
   1114                 }
   1115                 resolved_index = uc_base + startq;
   1116             }
   1117             break;
   1118         case _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE:
   1119             /* Return hw_index for given multicast queue gport */
   1120             if (node) {
   1121                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   1122                      if (IS_CPU_PORT(unit, resolved_port)) {
   1123                          cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   1124                          resolved_index = cpu_mc_base +
   1125                                           ((node->hw_index - cpu_mc_base) %
   1126                                               _BCM_TH_NUM_CPU_MCAST_QUEUE);
   1127                      } else {
   1128                          resolved_index = (mc_base + (node->hw_index %
   1129                                             _BCM_TH_NUM_MCAST_QUEUE_PER_PORT));
   1130                      }
   1131                 } else {
   1132                     return BCM_E_PARAM;
   1133                 }
   1134             } else {
   1135                 if (startq >= numq) {
   1136                     return BCM_E_PARAM;
   1137                 }
   1138                 resolved_index = mc_base + startq;
   1139             }
   1140             break;
   1141         default:
   1142             return BCM_E_PARAM;
   1143     }
   1144 
   1145     if (index) {
   1146         *index = resolved_index;
   1147     }
   1148     if (local_port) {
   1149         *local_port = resolved_port;
   1150     }
   1151     if (count) {
   1152         *count = (cosq == -1) ? numq : 1;
   1153     }
   1154 
   1155     return BCM_E_NONE;
   1156 }
   1157 
   1158 STATIC int
   1159 _bcm_th_cosq_cpu_port_info_dump(int unit)
   1160 {
   1161     _bcm_th_cosq_cpu_port_info_t *port_info;
   1162     bcm_port_t port = 0; /* CPU Port */
   1163     _bcm_th_cosq_node_t *node;
   1164     int index;
   1165     soc_th_sched_mode_e sched_mode = 0;
   1166     int weight = 0;
   1167     char *sched_modes[] = {"X", "SP", "WRR", "WERR"};
   1168 
   1169     if (!SOC_PORT_VALID(unit, port)) {
   1170         return BCM_E_PORT;
   1171     }
   1172     port_info = _bcm_th_cosq_cpu_port_info[unit];
   1173 
   1174     LOG_CLI((BSL_META_U(unit,
   1175                         "=== CPU PORT ===\n")));
   1176 
   1177     LOG_CLI((BSL_META_U(unit,
   1178                         "L0 Nodes\n")));
   1179     for (index = 0; index < _BCM_TH_NUM_SCHEDULER_PER_PORT; index++) {
   1180         /* Node */
   1181         node = &port_info->sched[index];
   1182 
   1183         BCM_IF_ERROR_RETURN(
   1184                 soc_th_cosq_sched_mode_get(unit, port, node->level, index,
   1185                                            &sched_mode, &weight, 0));
   1186         LOG_CLI((BSL_META_U(unit,
   1187                             "    LO.%d: GPORT=0x%x MODE=%s WT=%d\n"),
   1188                              index, node->gport,
   1189                              sched_modes[sched_mode], weight));
   1190     }
   1191 
   1192     LOG_CLI((BSL_META_U(unit,
   1193                         "\nMC Queues\n")));
   1194     for (index = 0; index < _BCM_TH_NUM_CPU_MCAST_QUEUE; index++) {
   1195         int parent_id = 0;
   1196         /* MC Queue */
   1197         node = &port_info->mcast[index];
   1198         BCM_IF_ERROR_RETURN(
   1199                 soc_th_cosq_sched_mode_get(unit, port, node->level, index,
   1200                                            &sched_mode, &weight, 1));
   1201         BCM_IF_ERROR_RETURN(
   1202             _bcm_th_cosq_node_get(unit, node->parent_gport, NULL, NULL,
   1203                                   &parent_id, NULL));
   1204         LOG_CLI((BSL_META_U(unit,
   1205                             "    MC.%d: GPORT=0x%x MODE=%s WT=%d"
   1206                             " PARENT=L0.%d\n"),
   1207                              index, node->gport,
   1208                              sched_modes[sched_mode], weight,
   1209                              parent_id));
   1210     }
   1211     LOG_CLI((BSL_META_U(unit,
   1212                         "=========== \n")));
   1213 
   1214     return BCM_E_NONE;
   1215 }
   1216 
   1217 STATIC int
   1218 _bcm_th_cosq_port_info_dump(int unit, bcm_port_t port)
   1219 {
   1220     _bcm_th_cosq_port_info_t *port_info;
   1221     _bcm_th_cosq_node_t *node;
   1222     int index, empty;
   1223     soc_th_sched_mode_e sched_mode = 0;
   1224     int weight = 0;
   1225     char *sched_modes[] = {"X", "SP", "WRR", "WERR"};
   1226 
   1227     if (!SOC_PORT_VALID(unit, port)) {
   1228         return BCM_E_PORT;
   1229     }
   1230     port_info = &_bcm_th_cosq_port_info[unit][port];
   1231 
   1232     empty = TRUE;
   1233     for (index = 0; index < _BCM_TH_NUM_SCHEDULER_PER_PORT; index++) {
   1234         if (port_info->sched[index].numq > 0) {
   1235             empty = FALSE;
   1236             break;
   1237         }
   1238     }
   1239     if (empty) {
   1240         for (index = 0; index < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; index++) {
   1241             if (port_info->ucast[index].numq > 0) {
   1242                 empty = FALSE;
   1243                 break;
   1244             }
   1245         }
   1246     }
   1247     if (empty) {
   1248         for (index = 0; index < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; index++) {
   1249             if (port_info->mcast[index].numq > 0) {
   1250                 empty = FALSE;
   1251                 break;
   1252             }
   1253         }
   1254     }
   1255 
   1256     if (empty == TRUE) {
   1257         return BCM_E_NOT_FOUND;
   1258     }
   1259 
   1260     LOG_CLI((BSL_META_U(unit,
   1261                         "=== PORT %d\n"), port));
   1262 
   1263     for (index = 0; index < _BCM_TH_NUM_SCHEDULER_PER_PORT; index++) {
   1264         /* Node */
   1265         node = &port_info->sched[index];
   1266 
   1267         BCM_IF_ERROR_RETURN(
   1268                 soc_th_cosq_sched_mode_get(unit, port, node->level, index,
   1269                                            &sched_mode, &weight, 0));
   1270         LOG_CLI((BSL_META_U(unit,
   1271                             "LO.%d: GPORT=0x%x MODE=%s WT=%d\n"),
   1272                              index, node->gport,
   1273                              sched_modes[sched_mode], weight));
   1274 
   1275         /* UC Queue */
   1276         node = &port_info->ucast[index % _BCM_TH_NUM_UCAST_QUEUE_PER_PORT];
   1277         BCM_IF_ERROR_RETURN(
   1278                 soc_th_cosq_sched_mode_get(unit, port, node->level, index,
   1279                                            &sched_mode, &weight, 0));
   1280         LOG_CLI((BSL_META_U(unit,
   1281                             "    UC.%d: GPORT=0x%x MODE=%s WT=%d\n"),
   1282                              index, node->gport,
   1283                              sched_modes[sched_mode], weight));
   1284 
   1285         /* MC Queue */
   1286         node = &port_info->mcast[index % _BCM_TH_NUM_MCAST_QUEUE_PER_PORT];
   1287         BCM_IF_ERROR_RETURN(
   1288                 soc_th_cosq_sched_mode_get(unit, port, node->level, index,
   1289                                            &sched_mode, &weight, 1));
   1290         LOG_CLI((BSL_META_U(unit,
   1291                             "    MC.%d: GPORT=0x%x MODE=%s WT=%d\n"),
   1292                              index, node->gport,
   1293                              sched_modes[sched_mode], weight));
   1294     }
   1295     LOG_CLI((BSL_META_U(unit,
   1296                         "=========== \n")));
   1297 
   1298     return BCM_E_NONE;
   1299 }
   1300 
   1301 /*
   1302  * Function:
   1303  *     bcm_th_cosq_gport_get
   1304  * Purpose:
   1305  *     Get a cosq gport structure
   1306  * Parameters:
   1307  *     unit  - (IN) unit number
   1308  *     gport - (IN) GPORT identifier
   1309  *     port  - (OUT) port number
   1310  *     numq  - (OUT) number of COS queues
   1311  *     flags - (OUT) flags (BCM_COSQ_GPORT_XXX)
   1312  * Returns:
   1313  *     BCM_E_XXX
   1314  */
   1315 int
   1316 bcm_th_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port,
   1317                       int *numq, uint32 *flags)
   1318 {
   1319     _bcm_th_cosq_node_t *node;
   1320     bcm_port_t local_port;
   1321     bcm_module_t modid;
   1322     _bcm_gport_dest_t dest;
   1323 
   1324     if (port == NULL || numq == NULL || flags == NULL) {
   1325         return BCM_E_PARAM;
   1326     }
   1327 
   1328     LOG_INFO(BSL_LS_BCM_COSQ,
   1329              (BSL_META_U(unit,
   1330                          "bcm_th_cosq_gport_get: unit=%d gport=0x%x\n"),
   1331               unit, gport));
   1332 
   1333     if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   1334          BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   1335          BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   1336          BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   1337         BCM_IF_ERROR_RETURN
   1338             (_bcm_th_cosq_node_get(unit, gport, NULL, &local_port,
   1339                                    NULL, &node));
   1340 
   1341         *numq = node->numq;
   1342 
   1343         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   1344             *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
   1345         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1346             *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP;
   1347         } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1348             *flags = BCM_COSQ_GPORT_SCHEDULER;
   1349         } else {
   1350             *flags = 0;
   1351         }
   1352     } else {
   1353         BCM_IF_ERROR_RETURN
   1354             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   1355         *flags = 0;
   1356         *numq = _BCM_TH_NUM_SCHEDULER_PER_PORT;
   1357     }
   1358 
   1359     if (SOC_USE_GPORT(unit)) {
   1360         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   1361         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   1362         dest.modid = modid;
   1363         dest.port = local_port;
   1364         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port));
   1365     } else {
   1366         *port = local_port;
   1367     }
   1368 
   1369     LOG_INFO(BSL_LS_BCM_COSQ,
   1370              (BSL_META_U(unit,
   1371                          "                       port=0x%x numq=%d flags=0x%x\n"),
   1372               *port, *numq, *flags));
   1373 
   1374     return BCM_E_NONE;
   1375 }
   1376 
   1377 int
   1378 bcm_th_cosq_config_set(int unit, int numq)
   1379 {
   1380     port_cos_map_entry_t cos_map_entries[16];
   1381     void *entries[1];
   1382     uint32 index;
   1383     int count;
   1384     bcm_port_t port;
   1385     int cos, prio, ref_count = -1;
   1386     uint32 i;
   1387     soc_mem_t mem = INVALIDm;
   1388 
   1389     if (numq < 1 || numq > BCM_TH_COS_MAX) {
   1390         return BCM_E_PARAM;
   1391     }
   1392 
   1393     index = 0;
   1394     while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) {
   1395         BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit,
   1396                                       _bcm_th_cos_map_profile[unit],
   1397                                       index, &ref_count));
   1398         if (ref_count > 0) {
   1399             while (ref_count) {
   1400                 if (!soc_profile_mem_delete(unit,
   1401                             _bcm_th_cos_map_profile[unit], index)) {
   1402                     ref_count -= 1;
   1403                 }
   1404             }
   1405         }
   1406         index += 16;
   1407     }
   1408 
   1409     /* Distribute first 8 internal priority levels into the specified number
   1410      * of cosq, map remaining internal priority levels to highest priority
   1411      * cosq */
   1412     sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
   1413     entries[0] = &cos_map_entries;
   1414     prio = 0;
   1415     mem = PORT_COS_MAPm;
   1416 
   1417     for (cos = 0; cos < numq; cos++) {
   1418         for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) {
   1419             soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
   1420                                 UC_COS1f, cos);
   1421             soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
   1422                                 MC_COS1f, cos);
   1423             prio++;
   1424         }
   1425     }
   1426     for (prio = 8; prio < 16; prio++) {
   1427         /*TH may have up to 10 cosq.*/
   1428         if (prio < numq) {
   1429             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f,
   1430                             prio);
   1431             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f,
   1432                             prio);
   1433         } else {
   1434             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f,
   1435                             numq - 1);
   1436             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f,
   1437                             numq - 1);
   1438         }
   1439     }
   1440 
   1441     /* Map internal priority levels to CPU CoS queues */
   1442     BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq));
   1443 
   1444     BCM_IF_ERROR_RETURN
   1445         (soc_profile_mem_add(unit, _bcm_th_cos_map_profile[unit], entries, 16,
   1446                              &index));
   1447     count = 0;
   1448     PBMP_ALL_ITER(unit, port) {
   1449         BCM_IF_ERROR_RETURN
   1450             (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   1451                                     index / 16));
   1452         count++;
   1453     }
   1454     if (SOC_INFO(unit).cpu_hg_index != -1) {
   1455         BCM_IF_ERROR_RETURN
   1456             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   1457                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   1458                                     index / 16));
   1459         count++;
   1460     }
   1461     for (i = 1; i < count; i++) {
   1462         soc_profile_mem_reference(unit, _bcm_th_cos_map_profile[unit], index,
   1463                                   0);
   1464     }
   1465 
   1466     _TH_NUM_COS(unit) = numq;
   1467 
   1468     return BCM_E_NONE;
   1469 }
   1470 
   1471 /*
   1472  * Function:
   1473  *     bcm_th_cosq_config_get
   1474  * Purpose:
   1475  *     Get the number of cos queues
   1476  * Parameters:
   1477  *     unit - unit number
   1478  *     numq - (Output) number of cosq
   1479  * Returns:
   1480  *     BCM_E_XXX
   1481  */
   1482 int
   1483 bcm_th_cosq_config_get(int unit, int *numq)
   1484 {
   1485     if (numq != NULL) {
   1486         *numq = _TH_NUM_COS(unit);
   1487     }
   1488 
   1489     return BCM_E_NONE;
   1490 }
   1491 
   1492 /*
   1493  * Function:
   1494  *     _bcm_th_cosq_sched_set
   1495  * Purpose:
   1496  *     Set scheduling mode
   1497  * Parameters:
   1498  *     unit                - (IN) unit number
   1499  *     port                - (IN) port number or GPORT identifier
   1500  *     cosq                - (IN) COS queue number
   1501  *     mode                - (IN) scheduling mode (BCM_COSQ_XXX)
   1502  *     weight              - (IN) weight
   1503  * Returns:
   1504  *     BCM_E_XXX
   1505  */
   1506 STATIC int
   1507 _bcm_th_cosq_sched_set(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
   1508                         int mode, int weight)
   1509 {
   1510     soc_th_sched_mode_e sched_mode;
   1511     bcm_port_t local_port;
   1512     int lwts = 1, child_index=0, lvl = SOC_TH_NODE_LVL_L0, mc = 0;
   1513 
   1514     if (cosq < 0) {
   1515         if (cosq == -1) {
   1516             /* caller needs to resolve the wild card value (-1) */
   1517             return BCM_E_INTERNAL;
   1518         } else { /* reject all other negative value */
   1519             return BCM_E_PARAM;
   1520         }
   1521     }
   1522     if ((weight < 0) || (weight > 127)) {
   1523         return BCM_E_PARAM;
   1524     }
   1525 
   1526     switch(mode) {
   1527         case BCM_COSQ_STRICT:
   1528             sched_mode = SOC_TH_SCHED_MODE_STRICT;
   1529             lwts = 0;
   1530             break;
   1531         case BCM_COSQ_ROUND_ROBIN:
   1532             sched_mode = SOC_TH_SCHED_MODE_WRR;
   1533             lwts = 1;
   1534             break;
   1535         case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   1536             sched_mode = SOC_TH_SCHED_MODE_WRR;
   1537             lwts = weight;
   1538             break;
   1539         case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   1540             sched_mode = SOC_TH_SCHED_MODE_WERR;
   1541             lwts = weight;
   1542             break;
   1543         default:
   1544             return BCM_E_PARAM;
   1545     }
   1546 
   1547     /* Weight = 0 corresponds to Strict Mode */
   1548     if (lwts == 0) {
   1549         sched_mode = SOC_TH_SCHED_MODE_STRICT;
   1550     }
   1551 
   1552     child_index = cosq;
   1553     BCM_IF_ERROR_RETURN
   1554         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   1555 
   1556     if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1557         /* We need to set lvl = L0(schedular node) so that sched mode is set at it's parent */
   1558         lvl = SOC_TH_NODE_LVL_L0;
   1559     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   1560                BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1561         /* We need to set lvl = L1(UC/MC nodes) so that sched mode is set at it's parent */
   1562         lvl = SOC_TH_NODE_LVL_L1;
   1563         mc = BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1 : 0;
   1564     } else if (IS_CPU_PORT(unit, local_port)) {
   1565         lvl = SOC_TH_NODE_LVL_L1;
   1566         mc = 1;
   1567     }
   1568     BCM_IF_ERROR_RETURN(soc_th_cosq_sched_mode_set(unit, local_port,
   1569                                                    lvl,
   1570                                                    child_index,
   1571                                                    sched_mode, lwts, mc));
   1572 
   1573     return BCM_E_NONE;
   1574 }
   1575 
   1576 /*
   1577  * Function:
   1578  *     _bcm_th_cosq_sched_get
   1579  * Purpose:
   1580  *     Get scheduling mode setting
   1581  * Parameters:
   1582  *     unit                - (IN) unit number
   1583  *     port                - (IN) port number or GPORT identifier
   1584  *     cosq                - (IN) COS queue number
   1585  *     mode                - (OUT) scheduling mode (BCM_COSQ_XXX)
   1586  *     weight              - (OUT) weight
   1587  * Returns:
   1588  *     BCM_E_XXX
   1589  */
   1590 STATIC int
   1591 _bcm_th_cosq_sched_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
   1592                        int *mode, int *weight)
   1593 {
   1594     soc_th_sched_mode_e sched_mode;
   1595     bcm_port_t local_port;
   1596     int lvl = SOC_TH_NODE_LVL_L0, mc = 0;
   1597 
   1598     BCM_IF_ERROR_RETURN
   1599         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   1600     if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1601         lvl = SOC_TH_NODE_LVL_L0;
   1602     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   1603                BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1604         lvl = SOC_TH_NODE_LVL_L1;
   1605         mc = BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1 : 0;
   1606     } else if (IS_CPU_PORT(unit, local_port)) {
   1607         lvl = SOC_TH_NODE_LVL_L1;
   1608         mc = 1;
   1609     }
   1610     BCM_IF_ERROR_RETURN(
   1611             soc_th_cosq_sched_mode_get(unit, local_port, lvl, cosq,
   1612                             &sched_mode, weight, mc));
   1613     switch(sched_mode) {
   1614         case SOC_TH_SCHED_MODE_STRICT:
   1615             *mode = BCM_COSQ_STRICT;
   1616         break;
   1617         case SOC_TH_SCHED_MODE_WRR:
   1618             *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   1619         break;
   1620         case SOC_TH_SCHED_MODE_WERR:
   1621             *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   1622         break;
   1623         default:
   1624             return BCM_E_INTERNAL;
   1625         break;
   1626     }
   1627     return BCM_E_NONE;
   1628 }
   1629 
   1630 /*
   1631  * Function:
   1632  *     _bcm_th_cosq_bucket_set
   1633  * Purpose:
   1634  *     Configure COS queue bandwidth control bucket
   1635  * Parameters:
   1636  *     unit          - (IN) unit number
   1637  *     gport         - (IN) port number or GPORT identifier
   1638  *     cosq          - (IN) COS queue number
   1639  *     min_quantum   - (IN) kbps or packet/second
   1640  *     max_quantum   - (IN) kbps or packet/second
   1641  *     burst_quantum - (IN) kbps or packet/second
   1642  *     flags         - (IN)
   1643  * Returns:
   1644  *     BCM_E_XXX
   1645  * Notes:
   1646  *     If port is any form of local port, cosq is the hardware queue index.
   1647  */
   1648 STATIC int
   1649 _bcm_th_cosq_bucket_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   1650                         uint32 min_quantum, uint32 max_quantum,
   1651                         uint32 kbits_burst_min, uint32 kbits_burst_max,
   1652                         uint32 flags)
   1653 {
   1654     _bcm_th_cosq_node_t *node = NULL;
   1655     bcm_port_t local_port;
   1656     uint32 rval, meter_flags;
   1657     uint32 bucketsize_max, bucketsize_min;
   1658     uint32 granularity_max, granularity_min;
   1659     uint32 refresh_rate_max, refresh_rate_min;
   1660     int refresh_bitsize = 0, bucket_bitsize = 0;
   1661     int pipe, phy_port, mmu_port, index;
   1662     soc_mem_t config_mem = INVALIDm;
   1663     uint32 entry[SOC_MAX_MEM_WORDS];
   1664     soc_info_t *si;
   1665     int cpu_mc_base = 0;
   1666 
   1667     /* caller should resolve the cosq. */
   1668     if (cosq < 0) {
   1669         if (cosq == -1) {
   1670             /* caller needs to resolve the wild card value (-1) */
   1671             return BCM_E_INTERNAL;
   1672         } else { /* reject all other negative value */
   1673             return BCM_E_PARAM;
   1674         }
   1675     }
   1676 
   1677     BCM_IF_ERROR_RETURN
   1678         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   1679 
   1680     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   1681 
   1682     si = &SOC_INFO(unit);
   1683     phy_port = si->port_l2p_mapping[local_port];
   1684     mmu_port = si->port_p2m_mapping[phy_port];
   1685 
   1686     if (BCM_GPORT_IS_SET(gport) &&
   1687         ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   1688           BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   1689           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   1690           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport))) {
   1691 
   1692         BCM_IF_ERROR_RETURN
   1693             (_bcm_th_cosq_node_get(unit, gport, NULL,
   1694                                    NULL, NULL, &node));
   1695     }
   1696 
   1697     if (node) {
   1698         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1699             if (node->level == SOC_TH_NODE_LVL_L0) {
   1700                 config_mem = MMU_MTRO_L0_MEMm;
   1701                 cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT;
   1702                 index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   1703                          _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq;
   1704             } else {
   1705                 return BCM_E_PARAM;
   1706             }
   1707         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   1708                    BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1709             config_mem = MMU_MTRO_L1_MEMm;
   1710             cosq = node->hw_index % si->port_num_cosq[local_port];
   1711 
   1712             if (IS_CPU_PORT(unit, local_port)) {
   1713                 /*Adjust mc cosq for cpu port*/
   1714                 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   1715                 cosq = (node->hw_index - cpu_mc_base) %
   1716                        _BCM_TH_NUM_CPU_MCAST_QUEUE;
   1717                 /* For CPU port's MC queue starting index: 660(L1 Memory) */
   1718                 config_mem = MMU_MTRO_L1_MEMm;
   1719                 index = SOC_TH_MMU_CPU_MCQ_OFFSET + cosq;
   1720             } else if (SOC_PBMP_MEMBER(si->management_pbm, local_port)) {
   1721                 config_mem = MMU_MTRO_L1_MEMm;
   1722                 index = (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ?
   1723                     SOC_TH_MMU_MGMT_MCQ_OFFSET : SOC_TH_MMU_MGMT_UCQ_OFFSET) + cosq;
   1724             } else {
   1725                 index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   1726                          _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq;
   1727                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1728                      index += SOC_TH_NUM_UC_QUEUES_PER_PIPE;
   1729                 }
   1730             }
   1731        } else {
   1732             return BCM_E_PARAM;
   1733        }
   1734     } else {
   1735         if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) {
   1736             return BCM_E_PARAM;
   1737         }
   1738         if (!IS_CPU_PORT(unit, local_port)) {
   1739             index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   1740                      _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq;
   1741             config_mem = MMU_MTRO_L0_MEMm;
   1742         } else {
   1743             /* For CPU port, refer L1 memory (logical queue, starting index 660)
   1744              * directly */
   1745             config_mem = MMU_MTRO_L1_MEMm;
   1746             index = (2 * SOC_TH_NUM_UC_QUEUES_PER_PIPE) + cosq;
   1747         }
   1748     }
   1749 
   1750     /*
   1751      * COVERITY
   1752      *
   1753      * This checker will not be True.
   1754      * It is kept intentionally as a defensive check for future development.
   1755      */
   1756     /* coverity[dead_error_line] */
   1757     if (config_mem == INVALIDm) {
   1758         return BCM_E_PARAM;
   1759     }
   1760     config_mem = SOC_MEM_UNIQUE_ACC(unit, config_mem)[pipe];
   1761 
   1762     if (config_mem == INVALIDm) {
   1763         return BCM_E_PARAM;
   1764     }
   1765 
   1766     meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ?
   1767                             _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   1768 #ifdef BCM_TOMAHAWK2_SUPPORT
   1769     if (soc_feature(unit, soc_feature_mmu_sed)) {
   1770         BCM_IF_ERROR_RETURN(READ_MMU_SEDCFG_MISCCONFIGr(unit, &rval));
   1771         if (soc_reg_field_get(unit, MMU_SEDCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) {
   1772             meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   1773         }
   1774     } else
   1775 #endif
   1776     {
   1777         BCM_IF_ERROR_RETURN(READ_MMU_SCFG_MISCCONFIGr(unit, &rval));
   1778         if (soc_reg_field_get(unit, MMU_SCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) {
   1779             meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   1780         }
   1781     }
   1782 
   1783     refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf);
   1784     bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf);
   1785 
   1786     BCM_IF_ERROR_RETURN
   1787         (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max,
   1788                                            meter_flags, refresh_bitsize,
   1789                                            bucket_bitsize, &refresh_rate_max,
   1790                                            &bucketsize_max, &granularity_max));
   1791 
   1792     BCM_IF_ERROR_RETURN
   1793         (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min,
   1794                                            meter_flags, refresh_bitsize,
   1795                                            bucket_bitsize, &refresh_rate_min,
   1796                                            &bucketsize_min, &granularity_min));
   1797 
   1798     sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   1799 
   1800     soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max);
   1801     soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max);
   1802     soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max);
   1803 
   1804     soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min);
   1805     soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min);
   1806     soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min);
   1807 
   1808     soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf,
   1809                         (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0);
   1810 
   1811     BCM_IF_ERROR_RETURN
   1812         (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry));
   1813 
   1814     return BCM_E_NONE;
   1815 }
   1816 
   1817 /*
   1818  * Function:
   1819  *     _bcm_th_cosq_bucket_get
   1820  * Purpose:
   1821  *     Get COS queue bandwidth control bucket setting
   1822  * Parameters:
   1823  *     unit          - (IN) unit number
   1824  *     gport         - (IN) port number or GPORT identifier
   1825  *     cosq          - (IN) COS queue number
   1826  *     min_quantum   - (OUT) kbps or packet/second
   1827  *     max_quantum   - (OUT) kbps or packet/second
   1828  *     burst_quantum - (OUT) kbps or packet/second
   1829  *     flags         - (IN)
   1830  * Returns:
   1831  *     BCM_E_XXX
   1832  * Notes:
   1833  *     If port is any form of local port, cosq is the hardware queue index.
   1834  */
   1835 STATIC int
   1836 _bcm_th_cosq_bucket_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
   1837                         uint32 *min_quantum, uint32 *max_quantum,
   1838                         uint32 *kbits_burst_min, uint32 *kbits_burst_max,
   1839                         uint32 *flags)
   1840 {
   1841     _bcm_th_cosq_node_t *node = NULL;
   1842     bcm_port_t local_port;
   1843     uint32 rval;
   1844     uint32 refresh_rate, bucketsize, granularity, meter_flags;
   1845     int pipe, phy_port, mmu_port, index;
   1846     soc_mem_t config_mem = INVALIDm;
   1847     uint32 entry[SOC_MAX_MEM_WORDS];
   1848     soc_info_t *si;
   1849     int cpu_mc_base = 0;
   1850 
   1851     if (cosq < 0) {
   1852         if (cosq == -1) {
   1853             /* caller needs to resolve the wild card value (-1) */
   1854             return BCM_E_INTERNAL;
   1855         } else { /* reject all other negative value */
   1856             return BCM_E_PARAM;
   1857         }
   1858     }
   1859 
   1860     BCM_IF_ERROR_RETURN
   1861         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   1862 
   1863     si = &SOC_INFO(unit);
   1864     phy_port = si->port_l2p_mapping[local_port];
   1865     mmu_port = si->port_p2m_mapping[phy_port];
   1866     pipe = si->port_pipe[local_port];
   1867 
   1868     if (BCM_GPORT_IS_SET(gport) &&
   1869         ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   1870           BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   1871           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   1872           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport))) {
   1873 
   1874         BCM_IF_ERROR_RETURN
   1875             (_bcm_th_cosq_node_get(unit, gport, NULL,
   1876                                    NULL, NULL, &node));
   1877     }
   1878 
   1879     if (node) {
   1880         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1881             if (node->level == SOC_TH_NODE_LVL_L0) {
   1882                 config_mem = MMU_MTRO_L0_MEMm;
   1883                 cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT;
   1884                 index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   1885                          _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq;
   1886             } else {
   1887                 return BCM_E_PARAM;
   1888             }
   1889         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   1890                    BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1891             config_mem = MMU_MTRO_L1_MEMm;
   1892             cosq = node->hw_index % si->port_num_cosq[local_port];
   1893 
   1894             if (IS_CPU_PORT(unit, local_port)) {
   1895                 /*Adjust mc cosq for cpu port*/
   1896                 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   1897                 cosq = (node->hw_index - cpu_mc_base) %
   1898                        _BCM_TH_NUM_CPU_MCAST_QUEUE;
   1899                 /* For CPU port's MC queue starting index: 660(L1 Memory) */
   1900                 config_mem = MMU_MTRO_L1_MEMm;
   1901                 index = SOC_TH_MMU_CPU_MCQ_OFFSET + cosq;
   1902             } else if (SOC_PBMP_MEMBER(si->management_pbm, local_port)) {
   1903                 config_mem = MMU_MTRO_L1_MEMm;
   1904                 index = (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ?
   1905                     SOC_TH_MMU_MGMT_MCQ_OFFSET : SOC_TH_MMU_MGMT_UCQ_OFFSET) + cosq;
   1906             } else {
   1907                 index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   1908                          _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq;
   1909                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1910                      index += SOC_TH_NUM_UC_QUEUES_PER_PIPE;
   1911                 }
   1912             }
   1913         } else {
   1914             return BCM_E_PARAM;
   1915         }
   1916     } else {
   1917         if ((cosq < 0) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) {
   1918             return BCM_E_PARAM;
   1919         }
   1920         if (!IS_CPU_PORT(unit, local_port)) {
   1921             index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   1922                      _BCM_TH_NUM_SCHEDULER_PER_PORT) + cosq;
   1923             config_mem = MMU_MTRO_L0_MEMm;
   1924         } else {
   1925             /* For CPU port, refer L1 memory (logical queue, starting index 660)
   1926              * directly */
   1927             config_mem = MMU_MTRO_L1_MEMm;
   1928             index = (2 * SOC_TH_NUM_UC_QUEUES_PER_PIPE) + cosq;
   1929         }
   1930     }
   1931 
   1932     /*
   1933      * COVERITY
   1934      *
   1935      * This checker will not be True.
   1936      * It is kept intentionally as a defensive case for future development.
   1937      */
   1938     /* coverity[dead_error_line] */
   1939     if (config_mem == INVALIDm) {
   1940         return BCM_E_PARAM;
   1941     }
   1942     config_mem = SOC_MEM_UNIQUE_ACC(unit, config_mem)[pipe];
   1943 
   1944     if (config_mem == INVALIDm) {
   1945         return BCM_E_PARAM;
   1946     }
   1947 
   1948     index = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, config_mem, index);
   1949 
   1950     if (min_quantum == NULL || max_quantum == NULL ||
   1951         kbits_burst_max == NULL || kbits_burst_min == NULL) {
   1952         return BCM_E_PARAM;
   1953     }
   1954 
   1955     BCM_IF_ERROR_RETURN
   1956         (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry));
   1957 
   1958     meter_flags = 0;
   1959     *flags = 0;
   1960 #ifdef BCM_TOMAHAWK2_SUPPORT
   1961     if (soc_feature(unit, soc_feature_mmu_sed)) {
   1962         BCM_IF_ERROR_RETURN(READ_MMU_SEDCFG_MISCCONFIGr(unit, &rval));
   1963         if (soc_reg_field_get(unit, MMU_SEDCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) {
   1964             meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   1965         }
   1966     } else
   1967 #endif
   1968     {
   1969         BCM_IF_ERROR_RETURN(READ_MMU_SCFG_MISCCONFIGr(unit, &rval));
   1970         if (soc_reg_field_get(unit, MMU_SCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) {
   1971             meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   1972         }
   1973     }
   1974     if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) {
   1975         meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE;
   1976         *flags |= BCM_COSQ_BW_PACKET_MODE;
   1977     }
   1978 
   1979     granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf);
   1980     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf);
   1981     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf);
   1982     BCM_IF_ERROR_RETURN
   1983         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   1984                                            granularity, meter_flags,
   1985                                            max_quantum, kbits_burst_max));
   1986 
   1987     granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf);
   1988     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf);
   1989     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf);
   1990     BCM_IF_ERROR_RETURN
   1991         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   1992                                            granularity, meter_flags,
   1993                                            min_quantum, kbits_burst_min));
   1994     return BCM_E_NONE;
   1995 }
   1996 
   1997 STATIC int
   1998 _bcm_th_cosq_time_domain_get(int unit, int time_id, int *time_value)
   1999 {
   2000     uint32 time_domain_val;
   2001     soc_reg_t time_domain_reg = TIME_DOMAINr;
   2002     
   2003     if (time_id < 0 || time_id > _BCM_TH_NUM_TIME_DOMAIN - 1) {
   2004         return SOC_E_PARAM;
   2005     }
   2006 
   2007     if (time_value == NULL) {
   2008         return SOC_E_PARAM;
   2009     }
   2010     
   2011     BCM_IF_ERROR_RETURN(
   2012         soc_reg32_get(unit, time_domain_reg, REG_PORT_ANY, time_id, &time_domain_val));
   2013     *time_value = soc_reg_field_get(unit, time_domain_reg,
   2014                                    time_domain_val, TIME_DOMAIN_FIELDf);
   2015     return SOC_E_NONE;
   2016 }
   2017 
   2018 STATIC int
   2019 _bcm_th_cosq_time_domain_set(int unit, int time_value, int *time_id)
   2020 {
   2021     int id;
   2022     uint32 time_domain_val;
   2023     soc_reg_t time_domain_reg = TIME_DOMAINr;
   2024 
   2025     if (time_value < 0 || time_value > 63) {
   2026         return SOC_E_PARAM;
   2027     }
   2028    
   2029     for (id = 0; id < _BCM_TH_NUM_TIME_DOMAIN; id++) {
   2030         BCM_IF_ERROR_RETURN(
   2031             soc_reg32_get(unit, time_domain_reg, REG_PORT_ANY, id, &time_domain_val));
   2032         if (!time_domain_info[unit][id].ref_count) {
   2033             soc_reg_field_set(unit, time_domain_reg, &time_domain_val, 
   2034                               TIME_DOMAIN_FIELDf, time_value);
   2035             time_domain_info[unit][id].ref_count++;
   2036             break;
   2037         }
   2038     }
   2039     
   2040     if (id == _BCM_TH_NUM_TIME_DOMAIN) {/* No field in TIME_DOMAINr is free,return ERR*/
   2041         return BCM_E_RESOURCE;
   2042     }
   2043 
   2044     if (time_id) {
   2045         *time_id = id;
   2046     }     
   2047     SOC_IF_ERROR_RETURN(
   2048         soc_reg32_set(unit, time_domain_reg, REG_PORT_ANY, id, time_domain_val));
   2049     return SOC_E_NONE;
   2050 }
   2051 
   2052 /*
   2053  * Function:
   2054  *     bcm_th_cosq_wred_resolution_id_create
   2055  * Purpose:
   2056  *     Assign a unused entry. Default drop rules are WRED drop. 
   2057  * Parameters:
   2058  *     unit                - (IN) unit number
   2059  *     index               - (OUT) entry index
   2060  * Returns:
   2061  *     BCM_E_XXX
   2062  */
   2063 int
   2064 bcm_th_cosq_wred_resolution_entry_create(int unit, int *index)
   2065 {
   2066     uint32 i, rval = 0;
   2067     soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   2068 
   2069     for (i = 0; i < _BCM_TH_NUM_WRED_RESOLUTION_TABLE; i ++) {
   2070         if (_bcm_th_wred_resolution_tbl[i] == 0) {
   2071             /* hw reset value */
   2072             soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, 0xAAA);
   2073             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, i, rval));
   2074             _bcm_th_wred_resolution_tbl[i] ++;
   2075             *index = i;
   2076             return SOC_E_NONE;
   2077         }
   2078     }
   2079 
   2080     return SOC_E_RESOURCE;
   2081 }
   2082 
   2083 /*
   2084  * Function:
   2085  *     bcm_th_cosq_wred_resolution_id_destroy
   2086  * Purpose:
   2087  *     Callback an entry and set its drop rules to WRED drop. 
   2088  * Parameters:
   2089  *     unit                - (IN) unit number
   2090  *     index               - (IN) entry index
   2091  * Returns:
   2092  *     BCM_E_XXX
   2093  */
   2094 int
   2095 bcm_th_cosq_wred_resolution_entry_destroy(int unit, int index)
   2096 {
   2097     uint32 rval = 0;
   2098     soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   2099 
   2100     if ((index < 0) || (index >= _BCM_TH_NUM_WRED_RESOLUTION_TABLE)) {
   2101         return SOC_E_PARAM;
   2102     }
   2103 
   2104     if (_bcm_th_wred_resolution_tbl[index] == 0) {
   2105         return SOC_E_NOT_FOUND;
   2106     }
   2107 
   2108     /* hw reset value */
   2109     soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, 0xAAA);
   2110     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval));
   2111     _bcm_th_wred_resolution_tbl[index] = 0;
   2112 
   2113     return SOC_E_NONE;
   2114 }
   2115 
   2116 /*
   2117  * Function:
   2118  *     bcm_th_cosq_wred_resolution_set
   2119  * Purpose:
   2120  *     Set one rule of a resolution table entry
   2121  * Parameters:
   2122  *     unit                - (IN) unit number
   2123  *     index               - (IN) entry index
   2124  *     rule                - (IN) drop rule
   2125  * Returns:
   2126  *     BCM_E_XXX
   2127  * Notes:
   2128  *     One entry has 12 bits, equals to 6 rules
   2129  */
   2130 int
   2131 bcm_th_cosq_wred_resolution_set(int unit, int index, bcm_cosq_discard_rule_t *rule)
   2132 {
   2133     uint32 offset, sp, qmin;
   2134     uint32 rval, fval, drop;
   2135     soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   2136 
   2137     if ((index < 0) || (index >= _BCM_TH_NUM_WRED_RESOLUTION_TABLE)) {
   2138         return SOC_E_PARAM;
   2139     }
   2140 
   2141     if (_bcm_th_wred_resolution_tbl[index] == 0) {
   2142         return BCM_E_NOT_FOUND;
   2143     }
   2144 
   2145     switch (rule->egress_pool_congestion_state) {
   2146         case BCM_COSQ_DISCARD_CONGESTION_LOW:
   2147             sp = 0;
   2148             break;
   2149         case BCM_COSQ_DISCARD_CONGESTION_MEDIUM:
   2150             sp = 1;
   2151             break;
   2152         case BCM_COSQ_DISCARD_CONGESTION_HIGH:
   2153             sp = 2;
   2154             break;
   2155         default:
   2156             return SOC_E_PARAM;
   2157     }
   2158 
   2159     switch (rule->queue_min_congestion_state) {
   2160         case BCM_COSQ_DISCARD_CONGESTION_LOW:
   2161             qmin = 0;
   2162             break;
   2163         case BCM_COSQ_DISCARD_CONGESTION_HIGH:
   2164             qmin = 1;
   2165             break;
   2166         default:
   2167             return SOC_E_PARAM;
   2168     }
   2169 
   2170     switch (rule->action) {
   2171         case BCM_COSQ_DISCARD_ACTION_WRED_DROP:
   2172             drop = 0x2;
   2173             break;
   2174         case BCM_COSQ_DISCARD_ACTION_FORCE_DROP:
   2175             drop = 0x3;
   2176             break;
   2177         case BCM_COSQ_DISCARD_ACTION_FORCE_NO_DROP:
   2178             drop = 0x0;
   2179             break;
   2180         default:
   2181             return SOC_E_PARAM;
   2182     }
   2183 
   2184     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval));
   2185     fval = soc_reg_field_get(unit, reg, rval, MMU_CONGESTION_EXPERIENCEf);
   2186 
   2187     offset = (sp * 2 + qmin) * 2;       /* 2 bits per rule */
   2188     fval = (fval & (~(0x3 << offset))) | (drop << offset);
   2189 
   2190     soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, fval);
   2191     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval));
   2192 
   2193     return SOC_E_NONE;
   2194 }
   2195 
   2196 /*
   2197  * Function:
   2198  *     bcm_th_cosq_wred_resolution_get
   2199  * Purpose:
   2200  *     Get all rules of a resolution table entry
   2201  * Parameters:
   2202  *     unit                - (IN) unit number
   2203  *     index               - (IN) entry index
   2204  *     max                 - (IN) rule array size
   2205  *     rule                - (OUT) rule array
   2206  *     count               - (OUT) actual rules count
   2207  * Returns:
   2208  *     BCM_E_XXX
   2209  * Notes:
   2210  *     One entry has 12 bits, equals to 6 rules
   2211  */
   2212 int
   2213 bcm_th_cosq_wred_resolution_get(int unit, int index, int max,
   2214                                  bcm_cosq_discard_rule_t *rule, int *count)
   2215 {
   2216     uint32 offset, sp, qmin, i = 0;
   2217     uint32 rval, fval, action;
   2218     soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   2219     uint32 sp_map[3] = {
   2220         BCM_COSQ_DISCARD_CONGESTION_LOW,
   2221         BCM_COSQ_DISCARD_CONGESTION_MEDIUM,
   2222         BCM_COSQ_DISCARD_CONGESTION_HIGH,
   2223     };
   2224     uint32 qmin_map[2] = {
   2225         BCM_COSQ_DISCARD_CONGESTION_LOW,
   2226         BCM_COSQ_DISCARD_CONGESTION_HIGH,
   2227     };
   2228     uint32 action_map[4] = {
   2229         BCM_COSQ_DISCARD_ACTION_FORCE_NO_DROP,
   2230         -1,
   2231         BCM_COSQ_DISCARD_ACTION_WRED_DROP,
   2232         BCM_COSQ_DISCARD_ACTION_FORCE_DROP,
   2233     };
   2234 
   2235     if ((!count) ||
   2236         (index < 0) || (index >= _BCM_TH_NUM_WRED_RESOLUTION_TABLE)) {
   2237         return SOC_E_PARAM;
   2238     }
   2239 
   2240     *count = 3 * 2;
   2241 
   2242     if (!rule) {
   2243         return SOC_E_NONE;
   2244     }
   2245 
   2246     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval));
   2247     fval = soc_reg_field_get(unit, reg, rval, MMU_CONGESTION_EXPERIENCEf);
   2248 
   2249     for (sp = 0; sp < 3; sp ++) {
   2250         for (qmin = 0; qmin < 2; qmin ++) {
   2251             offset = (sp * 2 + qmin) * 2;       /* 2 bits per rule */
   2252             action = (fval >> offset) & 0x3;
   2253             if (i < max) {
   2254                 rule[i].egress_pool_congestion_state = sp_map[sp];
   2255                 rule[i].queue_min_congestion_state = qmin_map[qmin];
   2256                 rule[i].action = action_map[action];
   2257                 i ++;
   2258             }
   2259         }
   2260     }
   2261 
   2262     return SOC_E_NONE;
   2263 }
   2264 
   2265 /*
   2266  * Function:
   2267  *     _bcm_th_cosq_wred_set
   2268  * Purpose:
   2269  *     Configure unicast queue WRED setting
   2270  * Parameters:
   2271  *     unit                - (IN) unit number
   2272  *     port                - (IN) port number or GPORT identifier
   2273  *     cosq                - (IN) COS queue number
   2274  *     flags               - (IN) BCM_COSQ_DISCARD_XXX
   2275  *     min_thresh          - (IN) Min Threshold
   2276  *     max_thresh          - (IN) Max Threshold
   2277  *     drop_probablity     - (IN) Probabilistic drop rate
   2278  *     gain                - (IN)
   2279  *     ignore_enable_flags - (IN)
   2280  *     lflags              - (IN) Config Flags
   2281  *     refresh_time        - (IN) actual refresh time
   2282  * Returns:
   2283  *     BCM_E_XXX
   2284  * Notes:
   2285  *     If port is any form of local port, cosq is the hardware queue index.
   2286  */
   2287 STATIC int
   2288 _bcm_th_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   2289                       bcm_cosq_buffer_id_t buffer,
   2290                       uint32 flags, uint32 min_thresh, uint32 max_thresh,
   2291                       int drop_probability, int gain, int ignore_enable_flags,
   2292                       uint32 lflags, int refresh_time, uint32 resolution_id,
   2293                       uint32 use_queue_group)
   2294 {
   2295     /* Local Variables */
   2296     soc_mem_t wred_config_mem = INVALIDm;
   2297     bcm_port_t local_port = -1;
   2298     int index, i, start_index, end_index, count = 0;
   2299     int end_offset, need_profile = 0, pipe, xpe, xpe_map, accessed = 0;
   2300     uint32 profile_index, old_profile_index;
   2301     uint32 wred_flags = 0;
   2302     void *entries[9];
   2303     soc_mem_t mems[9];
   2304     static soc_mem_t wred_mems[9] = {
   2305         MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m,
   2306         MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m,
   2307         MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m,
   2308         MMU_WRED_DROP_CURVE_PROFILE_6m, MMU_WRED_DROP_CURVE_PROFILE_7m,
   2309         MMU_WRED_DROP_CURVE_PROFILE_8m
   2310     };
   2311     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   2312     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   2313     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   2314     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   2315     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   2316     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   2317     mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green;
   2318     mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow;
   2319     mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red;
   2320     mmu_wred_config_entry_t entry;
   2321     int rate = 0;
   2322     int from_pipe, to_pipe;
   2323     int time_id,time,old_time,current_time_sel;
   2324     int rv = SOC_E_NONE, exists = 0;
   2325 
   2326     if ((buffer != BCM_COSQ_BUFFER_ID_INVALID) && 
   2327         ((buffer < 0) || (buffer >= _TH_XPES_PER_DEV))) {
   2328         return BCM_E_PARAM;
   2329     }
   2330     
   2331     wred_flags = flags | lflags;
   2332     end_offset = 0;
   2333 
   2334     /* Check Flags for WRED res level - Device-SP/Port-SP/Queues */
   2335     if ((wred_flags & BCM_COSQ_DISCARD_DEVICE) && (port == BCM_GPORT_INVALID)) {
   2336         /* (Port == -1) For all Global SPs */
   2337         index = 462;
   2338         count = _TH_MMU_NUM_POOL;
   2339         /*For all pipe*/
   2340         from_pipe = 0;
   2341         to_pipe = NUM_PIPE(unit) - 1;
   2342 
   2343     } else {
   2344         BCM_IF_ERROR_RETURN
   2345             (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   2346         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   2347         from_pipe = to_pipe = pipe;
   2348 
   2349         if (wred_flags & BCM_COSQ_DISCARD_DEVICE) {
   2350             BCM_IF_ERROR_RETURN
   2351                 (_bcm_th_cosq_index_resolve(unit, port, cosq,
   2352                                             _BCM_TH_COSQ_INDEX_STYLE_WRED_DEVICE,
   2353                                             NULL, &index, &count));
   2354             /* (cosq == -1) For all Global SPs */
   2355         } else if (wred_flags & BCM_COSQ_DISCARD_PORT) {
   2356             /* Port SP - Given or all SPs of the port */
   2357             BCM_IF_ERROR_RETURN
   2358                 (_bcm_th_cosq_index_resolve(unit, port, cosq,
   2359                                             _BCM_TH_COSQ_INDEX_STYLE_WRED_PORT,
   2360                                             NULL, &index, &count));
   2361             /* (cosq == -1) For all SPs of the given port */
   2362         } else {
   2363             /* Per Queue WRED settings */
   2364             BCM_IF_ERROR_RETURN
   2365                 (_bcm_th_cosq_index_resolve(unit, port, cosq,
   2366                                             _BCM_TH_COSQ_INDEX_STYLE_WRED_QUEUE,
   2367                                             NULL, &index, &count));
   2368             /* (cosq == -1) For all Queues of the given port */
   2369         }
   2370     }
   2371 
   2372 
   2373     end_offset = (count > 0) ? (count - 1) : 0;
   2374 
   2375     if (index < 0) {
   2376         return BCM_E_PARAM;
   2377     }
   2378     if (refresh_time < 1) {
   2379         return BCM_E_PARAM;
   2380     }
   2381     start_index = index;
   2382     end_index = start_index + end_offset;
   2383 
   2384     rate = _bcm_th_percent_to_drop_prob(drop_probability);
   2385 
   2386     for (pipe = from_pipe; pipe <= to_pipe; pipe++ ) {
   2387         /* Config MMU_WRED_CONFIGm for the respective resource */
   2388         wred_config_mem = MMU_WRED_CONFIGm;
   2389 
   2390         for (i=0; i < 9; i++) {
   2391             mems[i] = INVALIDm;
   2392         }
   2393 
   2394         if (wred_flags & (BCM_COSQ_DISCARD_COLOR_ALL |
   2395                           BCM_COSQ_DISCARD_TCP |
   2396                           BCM_COSQ_DISCARD_NONTCP |
   2397                           BCM_COSQ_DISCARD_ECT_MARKED |
   2398                           BCM_COSQ_DISCARD_RESPONSIVE_DROP |
   2399                           BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) {
   2400             need_profile = 1;
   2401 
   2402             if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN |
   2403                            BCM_COSQ_DISCARD_COLOR_YELLOW |
   2404                            BCM_COSQ_DISCARD_COLOR_RED))) {
   2405                 flags |= BCM_COSQ_DISCARD_COLOR_ALL;
   2406             }
   2407 
   2408             if (!(wred_flags & (BCM_COSQ_DISCARD_NONTCP |
   2409                                 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP |
   2410                                 BCM_COSQ_DISCARD_ECT_MARKED)) ||
   2411                  ((wred_flags & BCM_COSQ_DISCARD_TCP) ||
   2412                  (wred_flags & BCM_COSQ_DISCARD_RESPONSIVE_DROP))) {
   2413                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   2414                     mems[0] = wred_mems[0];
   2415                 }
   2416                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2417                     mems[1] = wred_mems[1];
   2418                 }
   2419                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2420                     mems[2] = wred_mems[2];
   2421                 }
   2422             }
   2423             if ((wred_flags & BCM_COSQ_DISCARD_NONTCP) ||
   2424                 (wred_flags & BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)){
   2425                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   2426                     mems[3] = wred_mems[3];
   2427                 }
   2428                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2429                     mems[4] = wred_mems[4];
   2430                 }
   2431                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2432                     mems[5] = wred_mems[5];
   2433                 }
   2434             }
   2435             if (wred_flags & BCM_COSQ_DISCARD_ECT_MARKED) {
   2436                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   2437                     mems[6] = wred_mems[6];
   2438                 }
   2439                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2440                     mems[7] = wred_mems[7];
   2441                 }
   2442                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2443                     mems[8] = wred_mems[8];
   2444                 }
   2445             }
   2446         }
   2447 
   2448         entries[0] = &entry_tcp_green;
   2449         entries[1] = &entry_tcp_yellow;
   2450         entries[2] = &entry_tcp_red;
   2451         entries[3] = &entry_nontcp_green;
   2452         entries[4] = &entry_nontcp_yellow;
   2453         entries[5] = &entry_nontcp_red;
   2454         entries[6] = &entry_ecn_green;
   2455         entries[7] = &entry_ecn_yellow;
   2456         entries[8] = &entry_ecn_red;
   2457 
   2458         if (buffer == BCM_COSQ_BUFFER_ID_INVALID) {
   2459             xpe_map = SOC_INFO(unit).epipe_xpe_map[pipe];
   2460         } else if (port == BCM_GPORT_INVALID) {
   2461             xpe_map = (1 << buffer) & SOC_INFO(unit).epipe_xpe_map[pipe];
   2462         } else {
   2463             xpe_map = (1 << buffer);
   2464         }
   2465 
   2466         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
   2467             if (!(xpe_map & (1 << xpe))) {
   2468                 continue;
   2469             }
   2470 
   2471             accessed = 1;
   2472             for (index = start_index; index <= end_index; index++) {
   2473                 old_profile_index = 0xffffffff;
   2474                 BCM_IF_ERROR_RETURN
   2475                      (soc_tomahawk_xpe_mem_read(unit, wred_config_mem, xpe, pipe,
   2476                                                 MEM_BLOCK_ALL, index, &entry));
   2477             
   2478                 if (need_profile) {
   2479                     old_profile_index = soc_mem_field32_get(unit, wred_config_mem,
   2480                                                             &entry, PROFILE_INDEXf);
   2481             
   2482                     BCM_IF_ERROR_RETURN
   2483                         (soc_profile_mem_get(unit, _bcm_th_wred_profile[unit],
   2484                                              old_profile_index, 1, entries));
   2485             
   2486                     for (i = 0; i < 9; i++) {
   2487                         if (mems[i] == INVALIDm) {
   2488                             continue;
   2489                         }
   2490                         soc_mem_field32_set(unit, wred_mems[i], entries[i],
   2491                                             MIN_THDf, min_thresh);
   2492                         soc_mem_field32_set(unit, wred_mems[i], entries[i],
   2493                                             MAX_THDf, max_thresh);
   2494                         soc_mem_field32_set(unit, wred_mems[i], entries[i],
   2495                                             MAX_DROP_RATEf, rate);
   2496                     }
   2497                     BCM_IF_ERROR_RETURN
   2498                         (soc_profile_mem_add(unit, _bcm_th_wred_profile[unit],
   2499                                              entries, 1, &profile_index));
   2500                     soc_mem_field32_set(unit, wred_config_mem, &entry, PROFILE_INDEXf, profile_index);
   2501                 }
   2502             
   2503                 soc_mem_field32_set(unit, wred_config_mem, &entry, WEIGHTf, gain);
   2504                 /* Some APIs only modify profiles */
   2505                 if (!ignore_enable_flags) {
   2506                     soc_mem_field32_set(unit, wred_config_mem, &entry, CAP_AVERAGEf,
   2507                                         flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   2508                     soc_mem_field32_set(unit, wred_config_mem, &entry, WRED_ENf,
   2509                                         flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   2510                     soc_mem_field32_set(unit, wred_config_mem, &entry, LOGICAL_Q_TRACK_ENABLEf,
   2511                                         flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   2512                     soc_mem_field32_set(unit, wred_config_mem, &entry, ECN_MARKING_ENf,
   2513                                         flags & BCM_COSQ_DISCARD_MARK_CONGESTION ?  1 : 0);
   2514                 }
   2515             
   2516                 current_time_sel = soc_mem_field32_get(unit, wred_config_mem, 
   2517                                                        &entry, TIME_DOMAIN_SELf);
   2518                 time = refresh_time - 1;
   2519                 exists = 0;
   2520                 /* If the time value exist, update reference count only */
   2521                 for (time_id = 0; time_id < _BCM_TH_NUM_TIME_DOMAIN; time_id++) {
   2522                     BCM_IF_ERROR_RETURN
   2523                         (_bcm_th_cosq_time_domain_get(unit, time_id, &old_time));            
   2524                     if (time == old_time) {
   2525                         /* Only set exist flag if this entry reference count already update,
   2526                                       otherwise update reference count */
   2527                         if(time_id != current_time_sel){ 
   2528                             soc_mem_field32_set(unit, wred_config_mem, &entry, 
   2529                                                 TIME_DOMAIN_SELf, time_id);
   2530                             time_domain_info[unit][time_id].ref_count++;
   2531                             time_domain_info[unit][current_time_sel].ref_count--;
   2532                         }
   2533                         exists = 1;
   2534                         break;
   2535                     }
   2536                 }
   2537             
   2538                 if(!exists){
   2539                     rv = _bcm_th_cosq_time_domain_set(unit, time, &time_id);
   2540                     if(rv == SOC_E_NONE){
   2541                         soc_mem_field32_set(unit, wred_config_mem, &entry, 
   2542                                             TIME_DOMAIN_SELf, time_id);
   2543                         time_domain_info[unit][current_time_sel].ref_count--;
   2544                     } else {
   2545                         return rv;
   2546                     }
   2547                 }
   2548 
   2549                 soc_mem_field32_set(unit, wred_config_mem, &entry, QG_ENf,
   2550                                     use_queue_group ? 1 : 0);
   2551                 if (flags & BCM_COSQ_DISCARD_MARK_CONGESTION) {
   2552                     soc_mem_field32_set(unit, wred_config_mem, &entry,
   2553                         WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf,
   2554                         resolution_id);
   2555                 } else {
   2556                     soc_mem_field32_set(unit, wred_config_mem, &entry,
   2557                         WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf,
   2558                         resolution_id);
   2559                 }
   2560 
   2561                 BCM_IF_ERROR_RETURN
   2562                     (soc_tomahawk_xpe_mem_write(unit, wred_config_mem, xpe, pipe,
   2563                                                 MEM_BLOCK_ALL, index, &entry));
   2564             
   2565                 if (old_profile_index != 0xffffffff) {
   2566                     SOC_IF_ERROR_RETURN
   2567                         (soc_profile_mem_delete(unit, _bcm_th_wred_profile[unit],
   2568                                                 old_profile_index));
   2569                 }
   2570             
   2571             }
   2572         }
   2573 
   2574     }
   2575 
   2576     /* pipe (port) and xpe (buffer) are not related */
   2577     if (!accessed) {
   2578         return BCM_E_PARAM;
   2579     }
   2580     
   2581     return rv;
   2582 }
   2583 
   2584 /*
   2585  * Function:
   2586  *     _bcm_th_cosq_wred_get
   2587  * Purpose:
   2588  *     Configure unicast queue WRED setting
   2589  * Parameters:
   2590  *     unit                - (IN) unit number
   2591  *     port                - (IN) port number or GPORT identifier
   2592  *     cosq                - (IN) COS queue number
   2593  *     flags               - (IN/OUT) BCM_COSQ_DISCARD_XXX
   2594  *     min_thresh          - (OUT) Min Threshold
   2595  *     max_thresh          - (OUT) Max Threshold
   2596  *     drop_probablity     - (OUT) Probabilistic drop rate
   2597  *     gain                - (OUT)
   2598  *     lflags              - (IN) Config flags
   2599  *     refresh_time        - (OUT) Time Domain
   2600  * Returns:
   2601  *     BCM_E_XXX
   2602  * Notes:
   2603  *     If port is any form of local port, cosq is the hardware queue index.
   2604  */
   2605 STATIC int
   2606 _bcm_th_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   2607                       bcm_cosq_buffer_id_t buffer,
   2608                       uint32 *flags, uint32 *min_thresh, uint32 *max_thresh,
   2609                       int *drop_probability, int *gain, uint32 lflags,
   2610                       int *refresh_time, uint32 *resolution_id,
   2611                       uint32 *use_queue_group)
   2612 {
   2613     soc_mem_t wred_config_mem = INVALIDm, mem = INVALIDm;
   2614     bcm_port_t local_port = -1;
   2615     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   2616     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   2617     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   2618     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   2619     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   2620     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   2621     mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green;
   2622     mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow;
   2623     mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red;
   2624     void *entries[9];
   2625     void *entry_p;
   2626     int index, profile_index;
   2627     mmu_wred_config_entry_t entry;
   2628     uint32 wred_flags = 0;
   2629     int rate = 0, pipe = -1, xpe;
   2630     int time_id, time;
   2631 
   2632     if ((buffer != BCM_COSQ_BUFFER_ID_INVALID) && 
   2633         ((buffer < 0) || (buffer >= _TH_XPES_PER_DEV))) {
   2634         return BCM_E_PARAM;
   2635     }
   2636 
   2637     if (flags) {
   2638         wred_flags = *flags | lflags;
   2639     } else {
   2640         wred_flags = lflags;
   2641     }
   2642 
   2643     if ((wred_flags & BCM_COSQ_DISCARD_DEVICE) && (port == BCM_GPORT_INVALID)) {
   2644         /* (Port == -1) For all Global SPs */
   2645         index = 462;
   2646         pipe = 0;
   2647 
   2648     } else {
   2649         BCM_IF_ERROR_RETURN
   2650             (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   2651         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   2652 
   2653         /* Check Flags for WRED res level - Device-SP/Port-SP/Queues */
   2654         if(wred_flags & BCM_COSQ_DISCARD_DEVICE) {
   2655             BCM_IF_ERROR_RETURN
   2656                 (_bcm_th_cosq_index_resolve(unit, port, cosq,
   2657                                             _BCM_TH_COSQ_INDEX_STYLE_WRED_DEVICE,
   2658                                             NULL, &index, NULL));
   2659         } else if (wred_flags & BCM_COSQ_DISCARD_PORT) {
   2660             /* Port SP - Given or all SPs of the port */
   2661             BCM_IF_ERROR_RETURN
   2662                 (_bcm_th_cosq_index_resolve(unit, port, cosq,
   2663                                             _BCM_TH_COSQ_INDEX_STYLE_WRED_PORT,
   2664                                             NULL, &index, NULL));
   2665         } else {
   2666             /* Per Queue WRED settings */
   2667             BCM_IF_ERROR_RETURN
   2668                 (_bcm_th_cosq_index_resolve(unit, port, cosq,
   2669                                             _BCM_TH_COSQ_INDEX_STYLE_WRED_QUEUE,
   2670                                             NULL, &index, NULL));
   2671         }
   2672     }
   2673 
   2674     if ((index < 0) || (pipe == -1)) {
   2675         return BCM_E_PARAM;
   2676     }
   2677 
   2678     if (buffer == BCM_COSQ_BUFFER_ID_INVALID) {
   2679         xpe = -1;
   2680     } else if (port == BCM_GPORT_INVALID) {
   2681         xpe = buffer;
   2682         pipe = -1;
   2683     } else if (SOC_INFO(unit).epipe_xpe_map[pipe] & (1 << buffer)) {
   2684         xpe = buffer;
   2685     } else {
   2686         return BCM_E_PARAM;
   2687     }
   2688 
   2689     wred_config_mem = MMU_WRED_CONFIGm;
   2690     BCM_IF_ERROR_RETURN
   2691         (soc_tomahawk_xpe_mem_read(unit, wred_config_mem, xpe, pipe,
   2692                                    MEM_BLOCK_ALL, index, &entry));
   2693 
   2694     profile_index = soc_mem_field32_get(unit, wred_config_mem,
   2695                                         &entry, PROFILE_INDEXf);
   2696 
   2697     if (!(wred_flags & (BCM_COSQ_DISCARD_NONTCP |
   2698                         BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP |
   2699                         BCM_COSQ_DISCARD_ECT_MARKED))) {
   2700         /* By default we will assume
   2701            BCM_COSQ_DISCARD_TCP */
   2702         if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2703             mem = MMU_WRED_DROP_CURVE_PROFILE_1m;
   2704             entry_p = &entry_tcp_yellow;
   2705         } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2706             mem = MMU_WRED_DROP_CURVE_PROFILE_2m;
   2707             entry_p = &entry_tcp_red;
   2708         } else {
   2709             /* By default we will assume
   2710                BCM_COSQ_DISCARD_COLOR_GREEN */
   2711             mem = MMU_WRED_DROP_CURVE_PROFILE_0m;
   2712             entry_p = &entry_tcp_green;
   2713         }
   2714     } else if ((wred_flags & BCM_COSQ_DISCARD_NONTCP) ||
   2715                (wred_flags & BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) {
   2716         if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2717             mem = MMU_WRED_DROP_CURVE_PROFILE_4m;
   2718             entry_p = &entry_nontcp_yellow;
   2719         } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2720             mem = MMU_WRED_DROP_CURVE_PROFILE_5m;
   2721             entry_p = &entry_nontcp_red;
   2722         } else {
   2723             /* By default we will assume
   2724                BCM_COSQ_DISCARD_COLOR_GREEN */
   2725             mem = MMU_WRED_DROP_CURVE_PROFILE_3m;
   2726             entry_p = &entry_nontcp_green;
   2727         }
   2728     } else {
   2729         if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2730             mem = MMU_WRED_DROP_CURVE_PROFILE_7m;
   2731             entry_p = &entry_ecn_yellow;
   2732         } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2733             mem = MMU_WRED_DROP_CURVE_PROFILE_8m;
   2734             entry_p = &entry_ecn_red;
   2735         } else {
   2736             /* By default we will assume
   2737                BCM_COSQ_DISCARD_COLOR_GREEN */
   2738             mem = MMU_WRED_DROP_CURVE_PROFILE_6m;
   2739             entry_p = &entry_ecn_green;
   2740         }
   2741     }
   2742 
   2743     entries[0] = &entry_tcp_green;
   2744     entries[1] = &entry_tcp_yellow;
   2745     entries[2] = &entry_tcp_red;
   2746     entries[3] = &entry_nontcp_green;
   2747     entries[4] = &entry_nontcp_yellow;
   2748     entries[5] = &entry_nontcp_red;
   2749     entries[6] = &entry_ecn_green;
   2750     entries[7] = &entry_ecn_yellow;
   2751     entries[8] = &entry_ecn_red;
   2752 
   2753     BCM_IF_ERROR_RETURN
   2754         (soc_profile_mem_get(unit, _bcm_th_wred_profile[unit],
   2755                              profile_index, 1, entries));
   2756     if (min_thresh != NULL) {
   2757         *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf);
   2758     }
   2759     if (max_thresh != NULL) {
   2760         *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf);
   2761     }
   2762     if (drop_probability != NULL) {
   2763         rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf);
   2764         *drop_probability = _bcm_th_drop_prob_to_percent(rate);
   2765     }
   2766     if (gain) {
   2767         *gain = soc_mem_field32_get(unit, wred_config_mem, &entry, WEIGHTf);
   2768     }
   2769 
   2770     /* Get the Time Domain value */
   2771     if (refresh_time) {
   2772         time_id = soc_mem_field32_get(unit, wred_config_mem, &entry, 
   2773                                       TIME_DOMAIN_SELf);
   2774         BCM_IF_ERROR_RETURN
   2775             (_bcm_th_cosq_time_domain_get(unit,time_id,&time));
   2776         *refresh_time = time + 1;
   2777     }
   2778 
   2779     /* Get flags */
   2780     if (flags) {
   2781         *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE |
   2782                     BCM_COSQ_DISCARD_MARK_CONGESTION);
   2783         if (soc_mem_field32_get(unit, wred_config_mem, &entry, CAP_AVERAGEf)) {
   2784             *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   2785         }
   2786         if (soc_mem_field32_get(unit, wred_config_mem, &entry, WRED_ENf)) {
   2787             *flags |= BCM_COSQ_DISCARD_ENABLE;
   2788         }
   2789         if (soc_mem_field32_get(unit, wred_config_mem, &entry, ECN_MARKING_ENf)) {
   2790             *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION;
   2791         }
   2792     }
   2793 
   2794     /* Get resolution table index */
   2795     if (resolution_id) {
   2796         if (soc_mem_field32_get(unit, wred_config_mem, &entry, ECN_MARKING_ENf)) {
   2797             *resolution_id = soc_mem_field32_get(unit, wred_config_mem, &entry,
   2798                 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf);
   2799         } else {
   2800             *resolution_id = soc_mem_field32_get(unit, wred_config_mem, &entry,
   2801                 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf);
   2802         }
   2803     }
   2804 
   2805     /* Get use_queue_group */
   2806     if (use_queue_group) {
   2807         *use_queue_group =
   2808             soc_mem_field32_get(unit, wred_config_mem, &entry, QG_ENf);
   2809     }
   2810 
   2811     return BCM_E_NONE;
   2812 }
   2813 
   2814 STATIC _bcm_bst_cb_ret_t
   2815 _bcm_th_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   2816                           bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index,
   2817                           int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv)
   2818 {
   2819     int phy_port, mmu_port, local_port;
   2820     int mmu_port_base = 0;
   2821     _bcm_th_cosq_node_t *node = NULL;
   2822     soc_info_t *si;
   2823     uint32 rval = 0;
   2824     int pool_idx;
   2825 
   2826     *bcm_rv = _bcm_th_cosq_localport_resolve(unit, gport, &local_port);
   2827 
   2828     if (BCM_E_NONE != (*bcm_rv)) {
   2829         goto error;
   2830     }
   2831 
   2832     si = &SOC_INFO(unit);
   2833     phy_port = si->port_l2p_mapping[local_port];
   2834     mmu_port = si->port_p2m_mapping[phy_port];
   2835 
   2836     *pipe = mmu_port / SOC_TH_MMU_PORT_STRIDE;
   2837 
   2838     if (bid == bcmBstStatIdDevice) {
   2839         *start_hw_index = *end_hw_index = 0;
   2840         *bcm_rv = BCM_E_NONE;
   2841         return _BCM_BST_RV_OK;
   2842     }
   2843 
   2844     if ((bid == bcmBstStatIdEgrPool) || (bid == bcmBstStatIdEgrMCastPool)) {
   2845         if(_bcm_th_cosq_egress_sp_get(unit, gport, cosq, start_hw_index,
   2846                                       end_hw_index)) {
   2847             goto error;
   2848         }
   2849         return _BCM_BST_RV_OK;
   2850     } else if (bid == bcmBstStatIdHeadroomPool) {
   2851         /* ingress headroom pool */
   2852         if (_bcm_th_cosq_ingress_hdrm_pool_get(unit, gport, cosq,
   2853                                                start_hw_index, end_hw_index)) {
   2854             goto error;
   2855         }
   2856         return _BCM_BST_RV_OK;
   2857     } else if (bid == bcmBstStatIdIngPool) {
   2858         /* ingress pool */
   2859         if (_bcm_th_cosq_ingress_sp_get(unit, gport, cosq,
   2860                                         start_hw_index, end_hw_index)) {
   2861             goto error;
   2862         }
   2863         return _BCM_BST_RV_OK;
   2864     } else if (bid == bcmBstStatIdRQEPool) {
   2865         /* RQE pool */
   2866         if (cosq == BCM_COS_INVALID) {
   2867             *start_hw_index = 0;
   2868             *end_hw_index = _TH_MMU_NUM_POOL - 1;
   2869         }else if ((cosq < 0) || (cosq >= _TH_MMU_NUM_RQE_QUEUES)) {
   2870             return BCM_E_PARAM;
   2871         } else {
   2872             SOC_IF_ERROR_RETURN
   2873                 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, cosq, &rval));
   2874 
   2875             pool_idx = soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval,
   2876                                                SPIDf);
   2877             *start_hw_index = *end_hw_index = pool_idx;
   2878         }
   2879         return _BCM_BST_RV_OK;
   2880     } else if (bid == bcmBstStatIdRQEQueue) {
   2881         /* RQE queue */
   2882         if (cosq == BCM_COS_INVALID) {
   2883             *start_hw_index = 0;
   2884             *end_hw_index = _TH_MMU_NUM_RQE_QUEUES - 1;
   2885         }else if ((cosq < 0) || (cosq >= _TH_MMU_NUM_RQE_QUEUES)) {
   2886             return BCM_E_PARAM;
   2887         } else {
   2888             *start_hw_index = *end_hw_index = cosq;
   2889         }
   2890         return _BCM_BST_RV_OK;
   2891     } else if (bid == bcmBstStatIdUCQueueGroup) {
   2892         /* unicast queue group */
   2893         mmu_port_base = SOC_TH_MMU_PORT_STRIDE * (*pipe);
   2894         *start_hw_index = *end_hw_index = mmu_port - mmu_port_base;
   2895         return _BCM_BST_RV_OK;
   2896     }
   2897 
   2898     if (bid == bcmBstStatIdPortPool) {
   2899         /* ingress pool */
   2900         if (_bcm_th_cosq_ingress_sp_get(unit, gport, cosq,
   2901                                         start_hw_index, end_hw_index)) {
   2902             goto error;
   2903         }
   2904         *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 4) +
   2905                           *start_hw_index;
   2906         *end_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 4) +
   2907                         *end_hw_index;
   2908     } else if ((bid == bcmBstStatIdPriGroupShared) ||
   2909                (bid == bcmBstStatIdPriGroupHeadroom)) {
   2910         /* ingress PG */
   2911         if (_bcm_th_cosq_ingress_pg_get(unit, gport, cosq,
   2912                                         start_hw_index, end_hw_index)) {
   2913             goto error;
   2914         }
   2915         *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 8) +
   2916                           *start_hw_index;
   2917         *end_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 8) +
   2918                         *end_hw_index;
   2919     } else if (bid == bcmBstStatIdEgrPortPoolSharedUcast ||
   2920                bid == bcmBstStatIdEgrPortPoolSharedMcast) {
   2921         /* egress pool */
   2922         if (_bcm_th_cosq_egress_sp_get(unit, gport, cosq,
   2923                                        start_hw_index, end_hw_index)) {
   2924             goto error;
   2925         }
   2926         *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 4) +
   2927                           *start_hw_index;
   2928         *end_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) * 4) +
   2929                         *end_hw_index;
   2930     } else {
   2931         if ((bid == bcmBstStatIdMcast) && IS_CPU_PORT(unit, local_port)) {
   2932             *start_hw_index = cosq + _BCM_BST_TH_CPU_QUEUE_START;
   2933             *end_hw_index = * start_hw_index;
   2934         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   2935             if (bid != bcmBstStatIdUcast) {
   2936                 goto error;
   2937             }
   2938             BCM_IF_ERROR_RETURN
   2939                 (_bcm_th_cosq_node_get(unit, gport, NULL,
   2940                                        &local_port, NULL, &node));
   2941             if (!node) {
   2942                 goto error;
   2943             }
   2944             cosq = node->hw_index % _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
   2945             *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   2946                                _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) + cosq;
   2947             *end_hw_index = *start_hw_index;
   2948         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2949             if (bid != bcmBstStatIdMcast) {
   2950                 goto error;
   2951             }
   2952             BCM_IF_ERROR_RETURN
   2953                 (_bcm_th_cosq_node_get(unit, gport, NULL,
   2954                                        &local_port, NULL, &node));
   2955             if (!node) {
   2956                 goto error;
   2957             }
   2958             cosq = node->hw_index % _BCM_TH_NUM_MCAST_QUEUE_PER_PORT;
   2959             *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   2960                                _BCM_TH_NUM_MCAST_QUEUE_PER_PORT) + cosq;
   2961             *end_hw_index = *start_hw_index;
   2962         } else {
   2963             if (cosq < 0) {
   2964                 if (bid == bcmBstStatIdUcast) {
   2965                     if (IS_LB_PORT(unit, local_port)) {
   2966                         goto error;
   2967                     }
   2968                     *start_hw_index = (mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   2969                                       _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
   2970                     *end_hw_index = *start_hw_index +
   2971                                     _BCM_TH_NUM_UCAST_QUEUE_PER_PORT - 1;
   2972                 } else {
   2973                     *start_hw_index = (mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   2974                                       _BCM_TH_NUM_MCAST_QUEUE_PER_PORT;
   2975                     *end_hw_index = *start_hw_index +
   2976                                     _BCM_TH_NUM_MCAST_QUEUE_PER_PORT - 1;
   2977                 }
   2978             } else if (cosq < _TH_PORT_NUM_COS(unit, local_port)) {
   2979                 if (bid == bcmBstStatIdUcast) {
   2980                     if (IS_LB_PORT(unit, local_port)) {
   2981                         goto error;
   2982                     }
   2983                     *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   2984                                        _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) + cosq;
   2985                     *end_hw_index = *start_hw_index;
   2986                 } else {
   2987                     *start_hw_index = ((mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1)) *
   2988                                        _BCM_TH_NUM_MCAST_QUEUE_PER_PORT) + cosq;
   2989                     *end_hw_index = *start_hw_index;
   2990                 }
   2991             } else {
   2992                 goto error;
   2993             }
   2994         }
   2995     }
   2996 
   2997     *bcm_rv = BCM_E_NONE;
   2998     return _BCM_BST_RV_OK;
   2999 
   3000 error:
   3001     *bcm_rv = BCM_E_PARAM;
   3002     return _BCM_BST_RV_ERROR;
   3003 }
   3004 
   3005 STATIC int
   3006 _bcm_th_cosq_bst_map_resource_to_gport_cos(int unit,
   3007     bcm_bst_stat_id_t bid, int port, int index, bcm_gport_t *gport,
   3008     bcm_cos_t *cosq)
   3009 {
   3010     soc_info_t *si = &SOC_INFO(unit);
   3011     _bcm_bst_resource_info_t *pres = NULL;
   3012     int phy_port = 0;
   3013     int mmu_port = 0;
   3014     int pipe = 0;
   3015     int mmu_port_base = 0;
   3016     int stats_per_inst = 1;
   3017     int stats_per_pipe = 1;
   3018 
   3019     if (bid >= bcmBstStatIdMaxCount) {
   3020         LOG_INFO(BSL_LS_BCM_COSQ,
   3021             (BSL_META_U(unit,
   3022             "_bcm_th_cosq_bst_map_resource_to_gport_cos: unit=%d bid=0x%x\n"),
   3023             unit, bid));
   3024         return BCM_E_NONE;
   3025     }
   3026 
   3027     pres = _BCM_BST_RESOURCE(unit, bid);
   3028     stats_per_inst = (pres->num_stat_pp) / (pres->num_instance);
   3029     index %= stats_per_inst;
   3030     if (pres->flags & _BCM_BST_CMN_RES_F_PIPED) {
   3031         stats_per_pipe = stats_per_inst / NUM_PIPE(unit);
   3032         pipe = index / stats_per_pipe;
   3033         index %= stats_per_pipe;
   3034         mmu_port_base = SOC_TH_MMU_PORT_STRIDE * pipe;
   3035     }
   3036 
   3037     switch (bid) {
   3038     case bcmBstStatIdDevice:
   3039         *gport = -1;
   3040         *cosq = BCM_COS_INVALID;
   3041         break;
   3042 
   3043     case bcmBstStatIdIngPool:
   3044     case bcmBstStatIdEgrPool:
   3045     case bcmBstStatIdEgrMCastPool:
   3046     case bcmBstStatIdRQEPool:
   3047         *gport = -1;
   3048         *cosq = index % _TH_MMU_NUM_POOL;
   3049         break;
   3050 
   3051     case bcmBstStatIdRQEQueue:
   3052         *gport = -1;
   3053         *cosq = index % _TH_MMU_NUM_RQE_QUEUES;
   3054         break;
   3055 
   3056     case bcmBstStatIdUCQueueGroup:
   3057         mmu_port= index;
   3058         phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base];
   3059         *gport = si->port_p2l_mapping[phy_port];
   3060         *cosq =  -1;
   3061         break;
   3062 
   3063     case bcmBstStatIdPortPool:
   3064         mmu_port= index/_TH_MMU_NUM_POOL;
   3065         phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base];
   3066         *gport = si->port_p2l_mapping[phy_port];
   3067         *cosq = index % _TH_MMU_NUM_POOL;
   3068         break;
   3069 
   3070     case bcmBstStatIdPriGroupHeadroom:
   3071     case bcmBstStatIdPriGroupShared:
   3072         mmu_port = index/_TH_MMU_NUM_PG;
   3073         phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base];
   3074         *gport = si->port_p2l_mapping[phy_port];
   3075         *cosq = index % _TH_MMU_NUM_PG;
   3076         break;
   3077 
   3078     case bcmBstStatIdUcast:
   3079     case bcmBstStatIdMcast:
   3080         if ((bid == bcmBstStatIdMcast) && _BCM_BST_TH_IS_CPU_QUEUE(index)) {
   3081             *gport = 0;
   3082             *cosq = index - _BCM_BST_TH_CPU_QUEUE_START;
   3083         } else {
   3084             mmu_port = index/10;
   3085             phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base];
   3086             *gport = si->port_p2l_mapping[phy_port];
   3087             *cosq = index % 10;
   3088         }
   3089         break;
   3090     case bcmBstStatIdEgrPortPoolSharedUcast:
   3091     case bcmBstStatIdEgrPortPoolSharedMcast:
   3092         mmu_port = index/_TH_MMU_NUM_POOL;
   3093         phy_port = si->port_m2p_mapping[mmu_port + mmu_port_base];
   3094         *gport = si->port_p2l_mapping[phy_port];
   3095         *cosq = index % _TH_MMU_NUM_POOL;
   3096         break;
   3097     default:
   3098         break;
   3099     }
   3100 
   3101     return BCM_E_NONE;
   3102 }
   3103 
   3104 
   3105 int
   3106 _bcm_th_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type,
   3107                                int *class)
   3108 {
   3109     switch (sctype) {
   3110         case bcmSwitchPFCClass7Queue:
   3111         case bcmSwitchPFCClass6Queue:
   3112         case bcmSwitchPFCClass5Queue:
   3113         case bcmSwitchPFCClass4Queue:
   3114         case bcmSwitchPFCClass3Queue:
   3115         case bcmSwitchPFCClass2Queue:
   3116         case bcmSwitchPFCClass1Queue:
   3117         case bcmSwitchPFCClass0Queue:
   3118             *type = _BCM_TH_COSQ_TYPE_UCAST;
   3119             break;
   3120         case bcmSwitchPFCClass7McastQueue:
   3121         case bcmSwitchPFCClass6McastQueue:
   3122         case bcmSwitchPFCClass5McastQueue:
   3123         case bcmSwitchPFCClass4McastQueue:
   3124         case bcmSwitchPFCClass3McastQueue:
   3125         case bcmSwitchPFCClass2McastQueue:
   3126         case bcmSwitchPFCClass1McastQueue:
   3127         case bcmSwitchPFCClass0McastQueue:
   3128             *type = _BCM_TH_COSQ_TYPE_MCAST;
   3129             break;
   3130         default:
   3131             /* Unsupported Switch Control types should return E_UNAVAIL */
   3132             return BCM_E_UNAVAIL;
   3133     }
   3134 
   3135     switch (sctype) {
   3136         case bcmSwitchPFCClass7Queue:
   3137         case bcmSwitchPFCClass7McastQueue:
   3138             *class = 7;
   3139             break;
   3140         case bcmSwitchPFCClass6Queue:
   3141         case bcmSwitchPFCClass6McastQueue:
   3142             *class = 6;
   3143             break;
   3144         case bcmSwitchPFCClass5Queue:
   3145         case bcmSwitchPFCClass5McastQueue:
   3146             *class = 5;
   3147             break;
   3148         case bcmSwitchPFCClass4Queue:
   3149         case bcmSwitchPFCClass4McastQueue:
   3150             *class = 4;
   3151             break;
   3152         case bcmSwitchPFCClass3Queue:
   3153         case bcmSwitchPFCClass3McastQueue:
   3154             *class = 3;
   3155             break;
   3156         case bcmSwitchPFCClass2Queue:
   3157         case bcmSwitchPFCClass2McastQueue:
   3158             *class = 2;
   3159             break;
   3160         case bcmSwitchPFCClass1Queue:
   3161         case bcmSwitchPFCClass1McastQueue:
   3162             *class = 1;
   3163             break;
   3164         case bcmSwitchPFCClass0Queue:
   3165         case bcmSwitchPFCClass0McastQueue:
   3166             *class = 0;
   3167             break;
   3168         /*
   3169          * COVERITY
   3170          *
   3171          * This default is unreachable but needed for some compiler.
   3172          */
   3173         /* coverity[dead_error_begin] */
   3174         default:
   3175             return BCM_E_INTERNAL;
   3176     }
   3177     return BCM_E_NONE;
   3178 }
   3179 
   3180 /* Function to Set Default Scheduler Configuration for all the ports */
   3181 STATIC int
   3182 _bcm_th_cosq_sched_default_config(int unit)
   3183 {
   3184     _bcm_th_cosq_port_info_t *port_info = NULL;
   3185     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
   3186     bcm_port_t port;
   3187     int default_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN, default_weight = 1;
   3188     int i;
   3189 
   3190     port = 0;
   3191     cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][port];
   3192     for (i = 0; i < _BCM_TH_NUM_SCHEDULER_PER_PORT; i++) {
   3193         BCM_IF_ERROR_RETURN
   3194             (bcm_th_cosq_gport_sched_set(unit, cpu_port_info->sched[i].gport,
   3195                 -1, default_mode, default_weight));
   3196     }
   3197     for (i = 0; i < _BCM_TH_NUM_CPU_MCAST_QUEUE; i++) {
   3198         BCM_IF_ERROR_RETURN
   3199             (bcm_th_cosq_gport_sched_set(unit, cpu_port_info->mcast[i].gport,
   3200                 -1, default_mode, default_weight));
   3201     }
   3202 
   3203     PBMP_ALL_ITER(unit, port) {
   3204         if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   3205             continue;
   3206         } else {
   3207             port_info = &_bcm_th_cosq_port_info[unit][port];
   3208         }
   3209         for (i = 0; i < _BCM_TH_NUM_SCHEDULER_PER_PORT; i++) {
   3210             BCM_IF_ERROR_RETURN
   3211                 (bcm_th_cosq_gport_sched_set(unit, port_info->sched[i].gport,
   3212                     -1, default_mode, default_weight));
   3213         }
   3214         for (i = 0; i < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; i++) {
   3215             BCM_IF_ERROR_RETURN
   3216                 (bcm_th_cosq_gport_sched_set(unit, port_info->ucast[i].gport,
   3217                     -1, default_mode, default_weight));
   3218         }
   3219         for (i = 0; i < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; i++) {
   3220             BCM_IF_ERROR_RETURN
   3221                 (bcm_th_cosq_gport_sched_set(unit, port_info->mcast[i].gport,
   3222                     -1, default_mode, default_weight));
   3223         }
   3224     }
   3225     return BCM_E_NONE;
   3226 }
   3227 
   3228 STATIC int
   3229 _bcm_th_cosq_gport_default_config(int unit)
   3230 {
   3231     BCM_IF_ERROR_RETURN
   3232         (_bcm_th_cosq_sched_default_config(unit));
   3233 
   3234     return BCM_E_NONE;
   3235 }
   3236 
   3237 STATIC int
   3238 _bcm_th_cosq_cpu_tree_create(int unit, bcm_gport_t *sched_gport)
   3239 {
   3240     bcm_gport_t cpu_mc_gport[_BCM_TH_NUM_CPU_MCAST_QUEUE];
   3241     int id, cmc, pci_cmc = SOC_PCI_CMC(unit);
   3242     int ch_l0_map[SOC_CMCS_NUM_MAX];
   3243 
   3244     if (SOC_CMCS_NUM(unit) > SOC_CMCS_NUM_MAX) {
   3245         return BCM_E_INIT;
   3246     }
   3247 
   3248     for (cmc = 0; cmc < SOC_CMCS_NUM(unit); cmc++) {
   3249         if (cmc == pci_cmc) {
   3250             ch_l0_map[cmc] = 0;
   3251         } else if (cmc == SOC_ARM_CMC(unit, 0)) {
   3252             ch_l0_map[cmc] = 7;
   3253         } else if (cmc == SOC_ARM_CMC(unit, 1)) {
   3254             ch_l0_map[cmc] = 8;
   3255         } else {
   3256             return BCM_E_PARAM;
   3257         }
   3258     }
   3259 
   3260     /* Adding MC queues and attaching them to Schedular nodes */
   3261     for (id = 0; id < _BCM_TH_NUM_CPU_MCAST_QUEUE; id++) {
   3262         cmc = (id < NUM_CPU_ARM_COSQ(unit, pci_cmc)) ? pci_cmc :
   3263               (id < (NUM_CPU_ARM_COSQ(unit, pci_cmc) +
   3264                      NUM_CPU_ARM_COSQ(unit, 1))) ? SOC_ARM_CMC(unit, 0) :
   3265                      SOC_ARM_CMC(unit, 1);
   3266         BCM_IF_ERROR_RETURN
   3267             (bcm_th_cosq_gport_add(unit, 0, 1,
   3268                                    BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   3269                                    &cpu_mc_gport[id]));
   3270         BCM_IF_ERROR_RETURN
   3271             (bcm_th_cosq_gport_attach(unit, cpu_mc_gport[id],
   3272                                       sched_gport[ch_l0_map[cmc]], id));
   3273     }
   3274     return BCM_E_NONE;
   3275 }
   3276 
   3277 /*
   3278  * Function:
   3279  *      _bcm_th_cosq_gport_tree_create
   3280  * Purpose:
   3281  *      During cosq init create the default cosq gport tree.
   3282  *      Schedualar (L0) nodes are created and attach to physical ports.
   3283  *      UC and MC queues are added and attached to each L0 nodes.
   3284  * Parameters:
   3285  *      unit - (IN) unit number.
   3286  *      port - (IN) port number
   3287  * Returns:
   3288  *     BCM_E_XXX
   3289  */
   3290 STATIC int
   3291 _bcm_th_cosq_gport_tree_create(int unit, bcm_port_t port)
   3292 {
   3293     int id;
   3294     bcm_gport_t sched_gport[_BCM_TH_NUM_SCHEDULER_PER_PORT];
   3295     bcm_gport_t uc_gport[_BCM_TH_NUM_UCAST_QUEUE_PER_PORT];
   3296     bcm_gport_t mc_gport[_BCM_TH_NUM_MCAST_QUEUE_PER_PORT];
   3297     int numq = 0;
   3298 
   3299     if (IS_CPU_PORT(unit, port)) {
   3300         numq = 48;
   3301     } else {
   3302         numq = 2;
   3303     }
   3304     /* Adding L0 (schedular) nodes and attaching them to front panel and cpu port */
   3305     for (id = 0; id < _BCM_TH_NUM_SCHEDULER_PER_PORT; id++) {
   3306         BCM_IF_ERROR_RETURN
   3307             (bcm_th_cosq_gport_add(unit, port, numq, BCM_COSQ_GPORT_SCHEDULER,
   3308                                    &sched_gport[id]));
   3309         BCM_IF_ERROR_RETURN
   3310             (bcm_th_cosq_gport_attach(unit, sched_gport[id], port, id));
   3311     }
   3312 
   3313     numq = 1;
   3314     if (IS_CPU_PORT(unit, port)) {
   3315         BCM_IF_ERROR_RETURN
   3316             (_bcm_th_cosq_cpu_tree_create(unit, sched_gport));
   3317     } else {
   3318         /* Adding UC queues and attaching them to Schedular nodes */
   3319         for (id = 0; id < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; id++) {
   3320             BCM_IF_ERROR_RETURN
   3321                 (bcm_th_cosq_gport_add(unit, port, numq,
   3322                                        BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
   3323                                        &uc_gport[id]));
   3324             BCM_IF_ERROR_RETURN
   3325                 (bcm_th_cosq_gport_attach(unit, uc_gport[id],
   3326                                           sched_gport[id], id));
   3327         }
   3328 
   3329         /* Adding MC queues and attaching them to Schedular nodes */
   3330         for (id = 0; id < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; id++) {
   3331             BCM_IF_ERROR_RETURN
   3332                 (bcm_th_cosq_gport_add(unit, port, numq,
   3333                                        BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   3334                                        &mc_gport[id]));
   3335             BCM_IF_ERROR_RETURN
   3336                 (bcm_th_cosq_gport_attach(unit, mc_gport[id],
   3337                                           sched_gport[id], id));
   3338         }
   3339     }
   3340 
   3341     return SOC_E_NONE;
   3342 }
   3343 
   3344 /*
   3345  * Function:
   3346  *     bcm_th_ecn_init
   3347  * Purpose:
   3348  *     Initialize (clear) all ECN memories/registers
   3349  * Parameters:
   3350  *     unit - unit number
   3351  * Returns:
   3352  *     BCM_E_XXX
   3353  */
   3354 STATIC int
   3355 _bcm_th_ecn_init(int unit)
   3356 {
   3357     egr_ip_to_int_cn_mapping_entry_t entry_egr_ip_int_cn;
   3358     int count, i;
   3359     uint32  fld_val;
   3360 
   3361     BCM_IF_ERROR_RETURN(_bcm_esw_ecn_init(unit));
   3362 
   3363     /* Perform additional Tomahawk specific ECN initialization */
   3364     /* EGR_IP_TO_INT_CN_MAPPING is identical to IP_TO_INT_CN_MAPPING table
   3365      */
   3366     if (!SOC_WARM_BOOT(unit)) {
   3367         count = soc_mem_index_count(unit, EGR_IP_TO_INT_CN_MAPPINGm);
   3368         for (i = 0; i < count; i++) {
   3369             sal_memset(&entry_egr_ip_int_cn, 0, sizeof(entry_egr_ip_int_cn));
   3370             switch (i) {
   3371                 case 0:
   3372                     fld_val = _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP;
   3373                     break;
   3374                 case 1:
   3375                     fld_val = _BCM_ECN_INT_CN_RESPONSIVE_DROP;
   3376                     break;
   3377                 case 6:
   3378                 case 7:
   3379                     fld_val = _BCM_ECN_INT_CN_CONGESTION_MARK_ECN;
   3380                     break;
   3381                 default:
   3382                     fld_val = _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN;
   3383                     break;
   3384             }
   3385             soc_mem_field32_set(unit, EGR_IP_TO_INT_CN_MAPPINGm,
   3386                 &entry_egr_ip_int_cn, INT_CNf, fld_val);
   3387             SOC_IF_ERROR_RETURN
   3388                 (soc_mem_write(unit, EGR_IP_TO_INT_CN_MAPPINGm, MEM_BLOCK_ALL,
   3389                                i, (void *)&entry_egr_ip_int_cn));
   3390         }
   3391     }
   3392     return BCM_E_NONE;
   3393 }
   3394 
   3395 /*
   3396  * Function:
   3397  *     _bcm_th_rqe_q_init
   3398  * Purpose:
   3399  *     Initialize RQE registers
   3400  * Parameters:
   3401  *     unit - unit number
   3402  * Returns:
   3403  *     BCM_E_XXX
   3404  */
   3405 STATIC int
   3406 _bcm_th_rqe_q_init(int unit)
   3407 {
   3408     uint32 rval;
   3409 
   3410     rval = 0;
   3411     SOC_IF_ERROR_RETURN(READ_CPU_LO_RQE_Q_NUMr(unit, &rval));
   3412     soc_reg_field_set(unit, CPU_LO_RQE_Q_NUMr, &rval, RQE_Q_NUMf, 8);
   3413     SOC_IF_ERROR_RETURN(WRITE_CPU_LO_RQE_Q_NUMr(unit, rval));
   3414 
   3415     rval = 0;
   3416     SOC_IF_ERROR_RETURN(READ_CPU_HI_RQE_Q_NUMr(unit, &rval));
   3417     soc_reg_field_set(unit, CPU_HI_RQE_Q_NUMr, &rval, RQE_Q_NUMf, 9);
   3418     SOC_IF_ERROR_RETURN(WRITE_CPU_HI_RQE_Q_NUMr(unit, rval));
   3419 
   3420     return BCM_E_NONE;
   3421 }
   3422 
   3423 /*
   3424  * Function:
   3425  *     _bcm_th_cosq_cleanup
   3426  * Purpose:
   3427  *     Clean resource in case of error during Cosq Init
   3428  * Parameters:
   3429  *     unit - unit number
   3430  * Returns:
   3431  *     No return value
   3432  */
   3433 STATIC void
   3434 _bcm_th_cosq_cleanup(int unit)
   3435 {
   3436     if (_bcm_th_cosq_port_info[unit] != NULL) {
   3437         sal_free(_bcm_th_cosq_port_info[unit]);
   3438         _bcm_th_cosq_port_info[unit] = NULL;
   3439     }
   3440 
   3441     if (_bcm_th_cosq_cpu_port_info[unit] != NULL) {
   3442         sal_free(_bcm_th_cosq_cpu_port_info[unit]);
   3443         _bcm_th_cosq_cpu_port_info[unit] = NULL;
   3444     }
   3445 
   3446     if (_bcm_th_mmu_info[unit] != NULL) {
   3447         sal_free(_bcm_th_mmu_info[unit]);
   3448         _bcm_th_mmu_info[unit] = NULL;
   3449     }
   3450 
   3451     if (_bcm_th_cos_map_profile[unit] != NULL) {
   3452         soc_profile_mem_destroy(unit, _bcm_th_cos_map_profile[unit]);
   3453         sal_free(_bcm_th_cos_map_profile[unit]);
   3454         _bcm_th_cos_map_profile[unit] = NULL;
   3455     }
   3456 
   3457     if (_bcm_th_ifp_cos_map_profile[unit] != NULL) {
   3458         soc_profile_mem_destroy(unit, _bcm_th_ifp_cos_map_profile[unit]);
   3459         sal_free(_bcm_th_ifp_cos_map_profile[unit]);
   3460         _bcm_th_ifp_cos_map_profile[unit] = NULL;
   3461     }
   3462 
   3463     if (_bcm_th_wred_profile[unit] != NULL) {
   3464         soc_profile_mem_destroy(unit, _bcm_th_wred_profile[unit]);
   3465         sal_free(_bcm_th_wred_profile[unit]);
   3466         _bcm_th_wred_profile[unit] = NULL;
   3467     }
   3468 
   3469     if (_bcm_th_prio2cos_profile[unit] != NULL) {
   3470         soc_profile_reg_destroy(unit, _bcm_th_prio2cos_profile[unit]);
   3471         sal_free(_bcm_th_prio2cos_profile[unit]);
   3472         _bcm_th_prio2cos_profile[unit] = NULL;
   3473     }
   3474 
   3475 #if defined(INCLUDE_PSTATS)
   3476     if (_BCM_PSTATS_UNIT_DRIVER(unit) != NULL) {
   3477         _bcm_pstats_deinit(unit);
   3478     }
   3479 #endif /* INCLUDE_PSTATS */
   3480 
   3481 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT)
   3482 #ifdef BCM_TOMAHAWK2_SUPPORT
   3483     _bcm_th2_cosq_tcb_deinit(unit);
   3484 #endif
   3485 #endif
   3486 
   3487     (void)_bcm_bst_detach(unit);
   3488 
   3489 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(INCLUDE_L3)
   3490     bcmi_ecn_map_clean_up(unit);
   3491 #endif
   3492 
   3493     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
   3494         (void)_bcm_pfc_deadlock_deinit(unit);
   3495     }
   3496     return;
   3497 }
   3498 
   3499 /*
   3500  * Function:
   3501  *     bcm_th_cosq_detach
   3502  * Purpose:
   3503  *     Discard all COS schedule/mapping state.
   3504  * Parameters:
   3505  *     unit - unit number
   3506  * Returns:
   3507  *     BCM_E_XXX
   3508  */
   3509 int
   3510 bcm_th_cosq_detach(int unit, int software_state_only)
   3511 {
   3512     _bcm_th_cosq_cleanup(unit);
   3513     return BCM_E_NONE;
   3514 }
   3515 
   3516 /*
   3517  * Function:
   3518  *     bcm_th_cosq_init
   3519  * Purpose:
   3520  *     Initialize (clear) all COS schedule/mapping state.
   3521  * Parameters:
   3522  *     unit - unit number
   3523  * Returns:
   3524  *     BCM_E_XXX
   3525  */
   3526 int
   3527 bcm_th_cosq_init(int unit)
   3528 {
   3529     int i, numq, alloc_size, pipe = -1, xpe = -1;
   3530     soc_mem_t mem = INVALIDm;
   3531     bcm_port_t port;
   3532     soc_reg_t reg;
   3533     static soc_mem_t wred_mems[9] = {
   3534         MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m,
   3535         MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m,
   3536         MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m,
   3537         MMU_WRED_DROP_CURVE_PROFILE_6m, MMU_WRED_DROP_CURVE_PROFILE_7m,
   3538         MMU_WRED_DROP_CURVE_PROFILE_8m
   3539     };
   3540     int entry_words[9];
   3541     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   3542     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   3543     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   3544     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   3545     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   3546     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   3547     mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green;
   3548     mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow;
   3549     mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red;
   3550     void *entries[9];
   3551     int ii, wred_prof_count;
   3552     soc_mem_t wred_config_mem = INVALIDm;
   3553     uint64 rval64s[16], *prval64s[1];
   3554     uint32 rval, profile_index;
   3555     _bcm_bst_device_handlers_t bst_callbks;
   3556     _bcm_th_cosq_cpu_cosq_config_t *cpu_cosq_config_p = NULL;
   3557     int rv = BCM_E_NONE;
   3558     soc_info_t *si = &SOC_INFO(unit);
   3559 
   3560     if (!SOC_WARM_BOOT(unit)) {
   3561         _bcm_th_cosq_cleanup(unit);
   3562     }
   3563 
   3564     numq = soc_property_get(unit, spn_BCM_NUM_COS, BCM_TH_COS_DEFAULT);
   3565 
   3566     if (numq < 1) {
   3567         numq = 1;
   3568     } else if (numq > BCM_TH_COS_MAX) {
   3569         numq = BCM_TH_COS_MAX;
   3570     }
   3571 
   3572     /* Create Port Information structure */
   3573     alloc_size = sizeof(_bcm_th_cosq_port_info_t) * 136;
   3574     if (_bcm_th_cosq_port_info[unit] == NULL) {
   3575         _bcm_th_cosq_port_info[unit] =
   3576             sal_alloc(alloc_size, "_bcm_th_cosq_port_info");
   3577             if (_bcm_th_cosq_port_info[unit] == NULL) {
   3578                 return BCM_E_MEMORY;
   3579             }
   3580     }
   3581     sal_memset(_bcm_th_cosq_port_info[unit], 0, alloc_size);
   3582 
   3583     /* Create CPU Port Information structure */
   3584     alloc_size = sizeof(_bcm_th_cosq_cpu_port_info_t);
   3585     if (_bcm_th_cosq_cpu_port_info[unit] == NULL) {
   3586         _bcm_th_cosq_cpu_port_info[unit] =
   3587             sal_alloc(alloc_size, "_bcm_th_cosq_cpu_port_info");
   3588         if (_bcm_th_cosq_cpu_port_info[unit] == NULL) {
   3589             _bcm_th_cosq_cleanup(unit);
   3590             return BCM_E_MEMORY;
   3591         }
   3592     }
   3593     sal_memset(_bcm_th_cosq_cpu_port_info[unit], 0, alloc_size);
   3594 
   3595     /* Create MMU Port Information structure */
   3596     alloc_size = sizeof(_bcm_th_mmu_info_t);
   3597     if (_bcm_th_mmu_info[unit] == NULL) {
   3598         _bcm_th_mmu_info[unit] =
   3599             sal_alloc(alloc_size, "_bcm_th_mmu_info");
   3600         if (_bcm_th_mmu_info[unit] == NULL) {
   3601             _bcm_th_cosq_cleanup(unit);
   3602             return BCM_E_MEMORY;
   3603         }
   3604     }
   3605     sal_memset(_bcm_th_mmu_info[unit], 0, alloc_size);
   3606     _BCM_TH_MMU_INFO(unit)->_bcm_th_port_info =
   3607             _bcm_th_cosq_port_info[unit];
   3608     _BCM_TH_MMU_INFO(unit)->_bcm_th_cpu_port_info =
   3609             _bcm_th_cosq_cpu_port_info[unit];
   3610 
   3611     /* Create profile for PORT_COS_MAP table */
   3612     if (_bcm_th_cos_map_profile[unit] == NULL) {
   3613         _bcm_th_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   3614                                                   "COS_MAP Profile Mem");
   3615         if (_bcm_th_cos_map_profile[unit] == NULL) {
   3616             _bcm_th_cosq_cleanup(unit);
   3617             return BCM_E_MEMORY;
   3618         }
   3619         soc_profile_mem_t_init(_bcm_th_cos_map_profile[unit]);
   3620     }
   3621     mem = PORT_COS_MAPm;
   3622     entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32);
   3623 
   3624     rv = soc_profile_mem_create(unit, &mem, entry_words, 1,
   3625                                 _bcm_th_cos_map_profile[unit]);
   3626     if (rv != SOC_E_NONE) {
   3627         _bcm_th_cosq_cleanup(unit);
   3628         return rv;
   3629     }
   3630 
   3631     /* Create profile for IFP_COS_MAP table */
   3632     if (_bcm_th_ifp_cos_map_profile[unit] == NULL) {
   3633         _bcm_th_ifp_cos_map_profile[unit]
   3634             = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem");
   3635         if (_bcm_th_ifp_cos_map_profile[unit] == NULL) {
   3636             _bcm_th_cosq_cleanup(unit);
   3637             return BCM_E_MEMORY;
   3638         }
   3639         soc_profile_mem_t_init(_bcm_th_ifp_cos_map_profile[unit]);
   3640     }
   3641     mem = IFP_COS_MAPm;
   3642     entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32);
   3643 
   3644     rv = soc_profile_mem_create(unit, &mem, entry_words, 1,
   3645                                 _bcm_th_ifp_cos_map_profile[unit]);
   3646     if (rv != SOC_E_NONE) {
   3647         _bcm_th_cosq_cleanup(unit);
   3648         return rv;
   3649     }
   3650 
   3651     /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */
   3652     if (_bcm_th_wred_profile[unit] == NULL) {
   3653         _bcm_th_wred_profile[unit] =
   3654                 sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem");
   3655         if (_bcm_th_wred_profile[unit] == NULL) {
   3656             _bcm_th_cosq_cleanup(unit);
   3657             return BCM_E_MEMORY;
   3658         }
   3659         soc_profile_mem_t_init(_bcm_th_wred_profile[unit]);
   3660     }
   3661 
   3662 
   3663     entry_words[0] =
   3664         sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32);
   3665     entry_words[1] =
   3666         sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32);
   3667     entry_words[2] =
   3668         sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32);
   3669     entry_words[3] =
   3670         sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32);
   3671     entry_words[4] =
   3672         sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32);
   3673     entry_words[5] =
   3674         sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32);
   3675     entry_words[6] =
   3676         sizeof(mmu_wred_drop_curve_profile_6_entry_t) / sizeof(uint32);
   3677     entry_words[7] =
   3678         sizeof(mmu_wred_drop_curve_profile_7_entry_t) / sizeof(uint32);
   3679     entry_words[8] =
   3680         sizeof(mmu_wred_drop_curve_profile_8_entry_t) / sizeof(uint32);
   3681 
   3682     rv = soc_profile_mem_create(unit, wred_mems, entry_words, 9,
   3683                                 _bcm_th_wred_profile[unit]);
   3684     if (rv != SOC_E_NONE) {
   3685         _bcm_th_cosq_cleanup(unit);
   3686         return rv;
   3687     }
   3688 
   3689     /* Create profile for PRIO2COS_PROFILE register */
   3690     if (_bcm_th_prio2cos_profile[unit] == NULL) {
   3691         _bcm_th_prio2cos_profile[unit] =
   3692             sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_PROFILE Profile Reg");
   3693         if (_bcm_th_prio2cos_profile[unit] == NULL) {
   3694             _bcm_th_cosq_cleanup(unit);
   3695             return BCM_E_MEMORY;
   3696         }
   3697         soc_profile_reg_t_init(_bcm_th_prio2cos_profile[unit]);
   3698     }
   3699     reg = PRIO2COS_PROFILEr;
   3700     rv = soc_profile_reg_create(unit, &reg, 1, _bcm_th_prio2cos_profile[unit]);
   3701     if (rv != SOC_E_NONE) {
   3702         _bcm_th_cosq_cleanup(unit);
   3703         return rv;
   3704     }
   3705 
   3706     if (_bcm_th_cosq_cpu_cosq_config[unit][0] == NULL) {
   3707         cpu_cosq_config_p = sal_alloc(
   3708                 SOC_TH_NUM_CPU_QUEUES * sizeof(_bcm_th_cosq_cpu_cosq_config_t),
   3709                 "CPU Cosq Config");
   3710         if (cpu_cosq_config_p == NULL) {
   3711             _bcm_th_cosq_cleanup(unit);
   3712             return BCM_E_MEMORY;
   3713         }
   3714         if (NUM_CPU_COSQ(unit) > SOC_TH_NUM_CPU_QUEUES) {
   3715             /* Invalid CPU Queues */
   3716             if (cpu_cosq_config_p != NULL) {
   3717                 sal_free(cpu_cosq_config_p);
   3718                 cpu_cosq_config_p = NULL;
   3719             }
   3720             _bcm_th_cosq_cleanup(unit);
   3721             return BCM_E_INIT;
   3722         }
   3723         for (i = 0; i < NUM_CPU_COSQ(unit); i++) {
   3724             _bcm_th_cosq_cpu_cosq_config[unit][i] = cpu_cosq_config_p + i;
   3725         }
   3726     }
   3727 
   3728     /* Assign default init values for RQE queue number */
   3729     rv = _bcm_th_rqe_q_init(unit);
   3730     if (rv != BCM_E_NONE) {
   3731         if (cpu_cosq_config_p != NULL) {
   3732             sal_free(cpu_cosq_config_p);
   3733             cpu_cosq_config_p = NULL;
   3734         }
   3735         _bcm_th_cosq_cleanup(unit);
   3736         return rv;
   3737     }
   3738 
   3739     /* Requires ECN init to program the default Responsive/Non-responsive
   3740      * settings in Hardware
   3741      */
   3742     if(soc_feature(unit, soc_feature_ecn_wred)) {
   3743         rv = _bcm_th_ecn_init(unit);
   3744         if (rv != BCM_E_NONE) {
   3745             if (cpu_cosq_config_p != NULL) {
   3746                 sal_free(cpu_cosq_config_p);
   3747                 cpu_cosq_config_p = NULL;
   3748             }
   3749             _bcm_th_cosq_cleanup(unit);
   3750             return rv;
   3751         }
   3752     }
   3753 
   3754 #if defined(INCLUDE_PSTATS)
   3755     if (soc_feature(unit, soc_feature_pstats)) {
   3756         rv = _bcm_pstats_init(unit);
   3757         if (rv != BCM_E_NONE) {
   3758             if (cpu_cosq_config_p != NULL) {
   3759                 sal_free(cpu_cosq_config_p);
   3760                 cpu_cosq_config_p = NULL;
   3761             }
   3762             _bcm_th_cosq_cleanup(unit);
   3763             return rv;
   3764         }
   3765     }
   3766 #endif /* INCLUDE_PSTATS */
   3767 
   3768     rv = _bcm_oob_init(unit);
   3769     if (rv != BCM_E_NONE) {
   3770         if (cpu_cosq_config_p != NULL) {
   3771             sal_free(cpu_cosq_config_p);
   3772             cpu_cosq_config_p = NULL;
   3773         }
   3774         _bcm_th_cosq_cleanup(unit);
   3775         return rv;
   3776     }
   3777 
   3778 
   3779 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT)
   3780     if(soc_feature(unit, soc_feature_tcb)) {
   3781 #ifdef BCM_TOMAHAWK2_SUPPORT
   3782         rv = bcm_th2_cosq_tcb_init(unit);
   3783 #endif        
   3784     }        
   3785     if (rv != BCM_E_NONE) {
   3786         if (cpu_cosq_config_p != NULL) {
   3787             sal_free(cpu_cosq_config_p);
   3788             cpu_cosq_config_p = NULL;
   3789         }
   3790         _bcm_th_cosq_cleanup(unit);
   3791         return rv;
   3792     }
   3793 #endif
   3794 
   3795 #ifdef BCM_WARM_BOOT_SUPPORT
   3796     if (SOC_WARM_BOOT(unit)) {
   3797         rv = bcm_th_cosq_reinit(unit);
   3798         if (rv != BCM_E_NONE) {
   3799             if (cpu_cosq_config_p != NULL) {
   3800                 sal_free(cpu_cosq_config_p);
   3801                 cpu_cosq_config_p = NULL;
   3802             }
   3803             _bcm_th_cosq_cleanup(unit);
   3804         }
   3805     /*
   3806      * COVERITY
   3807      *
   3808      * This checker will not be True.
   3809      * cpu_cosq_config_p pointer is assigned to
   3810      * _bcm_th_cosq_cpu_cosq_config global data
   3811      * structure.
   3812      */
   3813     /* coverity[resource_leak] */
   3814         return rv;
   3815     } else {
   3816         rv = _bcm_th_cosq_wb_alloc(unit);
   3817         if (rv != BCM_E_NONE) {
   3818             if (cpu_cosq_config_p != NULL) {
   3819                 sal_free(cpu_cosq_config_p);
   3820                 cpu_cosq_config_p = NULL;
   3821             }
   3822             _bcm_th_cosq_cleanup(unit);
   3823             return rv;
   3824         }
   3825     }
   3826 #endif /* BCM_WARM_BOOT_SUPPORT */
   3827 
   3828     /* Assign default init values for CPU info */
   3829     for (i = 0; i < NUM_CPU_COSQ(unit); i++) {
   3830         if (_bcm_th_cosq_cpu_cosq_config[unit][i] == NULL) {
   3831             if (cpu_cosq_config_p != NULL) {
   3832                 sal_free(cpu_cosq_config_p);
   3833                 cpu_cosq_config_p = NULL;
   3834             }
   3835             _bcm_th_cosq_cleanup(unit);
   3836             return BCM_E_MEMORY;
   3837         }
   3838         sal_memset(_bcm_th_cosq_cpu_cosq_config[unit][i], 0,
   3839                    sizeof(_bcm_th_cosq_cpu_cosq_config_t));
   3840         _bcm_th_cosq_cpu_cosq_config[unit][i]->enable = 1;
   3841     }
   3842 
   3843     /* Add default entries for PORT_COS_MAP memory profile */
   3844     rv = bcm_th_cosq_config_set(unit, numq);
   3845     if (rv != BCM_E_NONE) {
   3846         if (cpu_cosq_config_p != NULL) {
   3847             sal_free(cpu_cosq_config_p);
   3848             cpu_cosq_config_p = NULL;
   3849         }
   3850         _bcm_th_cosq_cleanup(unit);
   3851         return rv;
   3852     }
   3853 
   3854     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   3855         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   3856             if (si->epipe_xpe_map[pipe] & (1 << xpe)) {
   3857                 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, MMU_WRED_CONFIGm,
   3858                                                   xpe, pipe);
   3859                 rv = soc_mem_clear(unit, mem, COPYNO_ALL, 1);
   3860                 if (rv != SOC_E_NONE) {
   3861                     if (cpu_cosq_config_p != NULL) {
   3862                         sal_free(cpu_cosq_config_p);
   3863                         cpu_cosq_config_p = NULL;
   3864                     }
   3865                     _bcm_th_cosq_cleanup(unit);
   3866                     return rv;
   3867                 }
   3868             }
   3869         }
   3870     }
   3871 
   3872     /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */
   3873     sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green));
   3874     sal_memset(&entry_tcp_yellow,0, sizeof(entry_tcp_yellow));
   3875     sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red));
   3876     sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green));
   3877     sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow));
   3878     sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red));
   3879     sal_memset(&entry_ecn_green, 0, sizeof(entry_ecn_green));
   3880     sal_memset(&entry_ecn_yellow,0, sizeof(entry_ecn_yellow));
   3881     sal_memset(&entry_ecn_red, 0, sizeof(entry_ecn_red));
   3882     entries[0] = &entry_tcp_green;
   3883     entries[1] = &entry_tcp_yellow;
   3884     entries[2] = &entry_tcp_red;
   3885     entries[3] = &entry_nontcp_green;
   3886     entries[4] = &entry_nontcp_yellow;
   3887     entries[5] = &entry_nontcp_red;
   3888     entries[6] = &entry_ecn_green;
   3889     entries[7] = &entry_ecn_yellow;
   3890     entries[8] = &entry_ecn_red;
   3891 
   3892     for (ii = 0; ii < 9; ii++) {
   3893         soc_mem_field32_set(unit, wred_mems[ii], entries[ii],
   3894                             MIN_THDf, 0xffff);
   3895         soc_mem_field32_set(unit, wred_mems[ii], entries[ii],
   3896                             MAX_THDf, 0xffff);
   3897     }
   3898     profile_index = 0xffffffff;
   3899     wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_WRED_CONFIGm)[0];
   3900     wred_prof_count = soc_mem_index_count(unit, wred_config_mem);
   3901 
   3902     /* In TH Profile table duplicate across all pipes all (related) xpes.
   3903      * Ref count needs to be updated too */
   3904     wred_prof_count *= (2 * NUM_PIPE(unit));
   3905     while(wred_prof_count) {
   3906         if (profile_index == 0xffffffff) {
   3907             rv = soc_profile_mem_add(unit, _bcm_th_wred_profile[unit],
   3908                                      entries, 1, &profile_index);
   3909         } else {
   3910             rv = soc_profile_mem_reference(unit, _bcm_th_wred_profile[unit],
   3911                                            profile_index, 0);
   3912         }
   3913         if (rv != SOC_E_NONE) {
   3914             if (cpu_cosq_config_p != NULL) {
   3915                 sal_free(cpu_cosq_config_p);
   3916                 cpu_cosq_config_p = NULL;
   3917             }
   3918             _bcm_th_cosq_cleanup(unit);
   3919             return rv;
   3920         }
   3921         wred_prof_count -= 1;
   3922     }
   3923 
   3924     for (i = 0; i < _BCM_TH_NUM_WRED_RESOLUTION_TABLE; i++) {
   3925         if (i == 0) {
   3926             _bcm_th_wred_resolution_tbl[i] = 1;
   3927         } else {
   3928             _bcm_th_wred_resolution_tbl[i] = 0;
   3929         }
   3930     }
   3931 
   3932 
   3933     /* Add default entries for PRIO2COS_PROFILE register profile */
   3934     sal_memset(rval64s, 0, sizeof(rval64s));
   3935     prval64s[0] = rval64s;
   3936     profile_index = 0xffffffff;
   3937     PBMP_PORT_ITER(unit, port) {
   3938         if (profile_index == 0xffffffff) {
   3939             rv = soc_profile_reg_add(unit, _bcm_th_prio2cos_profile[unit],
   3940                                      prval64s, 16, &profile_index);
   3941         } else {
   3942             rv = soc_profile_reg_reference(unit, _bcm_th_prio2cos_profile[unit],
   3943                                            profile_index, 0);
   3944         }
   3945         if (rv == SOC_E_NONE) {
   3946             rv = soc_reg32_get(unit, PORT_LLFC_CFGr, port, 0, &rval);
   3947             soc_reg_field_set(unit, PORT_LLFC_CFGr, &rval, PROFILE_INDEXf,
   3948                               profile_index/16);
   3949             rv = soc_reg32_set(unit, PORT_LLFC_CFGr, port, 0, rval);
   3950         }
   3951         if (rv != SOC_E_NONE) {
   3952             if (cpu_cosq_config_p != NULL) {
   3953                 sal_free(cpu_cosq_config_p);
   3954                 cpu_cosq_config_p = NULL;
   3955             }
   3956             _bcm_th_cosq_cleanup(unit);
   3957             return rv;
   3958         }
   3959     }
   3960 
   3961     _BCM_TH_MMU_INFO(unit)->gport_tree_created = FALSE;
   3962     PBMP_ALL_ITER(unit, port) {
   3963         if (IS_LB_PORT(unit, port)) {
   3964             continue;
   3965         }
   3966         rv = _bcm_th_cosq_gport_tree_create(unit, port);
   3967         if (rv != BCM_E_NONE) {
   3968             if (cpu_cosq_config_p != NULL) {
   3969                 sal_free(cpu_cosq_config_p);
   3970                 cpu_cosq_config_p = NULL;
   3971             }
   3972             _bcm_th_cosq_cleanup(unit);
   3973             return rv;
   3974         }
   3975     }
   3976     _BCM_TH_MMU_INFO(unit)->gport_tree_created = TRUE;
   3977 
   3978     rv = _bcm_th_cosq_gport_default_config(unit);
   3979     if (rv != BCM_E_NONE) {
   3980         if (cpu_cosq_config_p != NULL) {
   3981             sal_free(cpu_cosq_config_p);
   3982             cpu_cosq_config_p = NULL;
   3983         }
   3984         _bcm_th_cosq_cleanup(unit);
   3985         return rv;
   3986     }
   3987 
   3988     sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t));
   3989     bst_callbks.resolve_index = &_bcm_th_bst_index_resolve;
   3990     bst_callbks.reverse_resolve_index =
   3991         &_bcm_th_cosq_bst_map_resource_to_gport_cos;
   3992     rv = _bcm_bst_attach(unit, &bst_callbks);
   3993     if (rv != BCM_E_NONE) {
   3994         if (cpu_cosq_config_p != NULL) {
   3995             sal_free(cpu_cosq_config_p);
   3996             cpu_cosq_config_p = NULL;
   3997         }
   3998         _bcm_th_cosq_cleanup(unit);
   3999         return rv;
   4000     }
   4001 
   4002     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
   4003         rv = _bcm_pfc_deadlock_init(unit);
   4004         if (rv != BCM_E_NONE) {
   4005             if (cpu_cosq_config_p != NULL) {
   4006                 sal_free(cpu_cosq_config_p);
   4007                 cpu_cosq_config_p = NULL;
   4008             }
   4009             _bcm_th_cosq_cleanup(unit);
   4010             return rv;
   4011         }
   4012     }
   4013 
   4014     rv = soc_th_mmu_get_shared_size(unit,
   4015                      _BCM_TH_MMU_INFO(unit)->ing_shared_limit,
   4016                      _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit,
   4017                      _BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit);
   4018     if (rv != SOC_E_NONE) {
   4019         if (cpu_cosq_config_p != NULL) {
   4020             sal_free(cpu_cosq_config_p);
   4021             cpu_cosq_config_p = NULL;
   4022         }
   4023         _bcm_th_cosq_cleanup(unit);
   4024         return rv;
   4025     }
   4026     
   4027     /* reset time_domain ref_count so that entries can be added upon
   4028      * rc */
   4029     time_domain_info[unit][0].ref_count = 466;
   4030     time_domain_info[unit][1].ref_count = 0;
   4031     time_domain_info[unit][2].ref_count = 0;
   4032     time_domain_info[unit][3].ref_count = 0;
   4033     return BCM_E_NONE;
   4034 }
   4035 
   4036 /*
   4037  * Function:
   4038  *     bcm_th_cosq_port_sched_set
   4039  * Purpose:
   4040  *     Set up class-of-service policy and corresponding weights and delay
   4041  * Parameters:
   4042  *     unit    - (IN) unit number
   4043  *     pbm     - (IN) port bitmap
   4044  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   4045  *     weights - (IN) Weights for each COS queue
   4046  *     delay   - This parameter is not used
   4047  * Returns:
   4048  *     BCM_E_XXX
   4049  */
   4050 int
   4051 bcm_th_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
   4052                            int mode, const int *weights, int delay)
   4053 {
   4054     bcm_port_t port;
   4055     int num_weights, i;
   4056 
   4057     BCM_PBMP_ITER(pbm, port) {
   4058         num_weights = _TH_NUM_COS(unit);
   4059         for (i = 0; i < num_weights; i++) {
   4060             BCM_IF_ERROR_RETURN
   4061                 (_bcm_th_cosq_sched_set(unit, port, i, mode, weights[i]));
   4062         }
   4063     }
   4064 
   4065     return BCM_E_NONE;
   4066 }
   4067 
   4068 /*
   4069  * Function:
   4070  *     bcm_th_cosq_port_sched_get
   4071  * Purpose:
   4072  *     Retrieve class-of-service policy and corresponding weights and delay
   4073  * Parameters:
   4074  *     unit     - (IN) unit number
   4075  *     pbm      - (IN) port bitmap
   4076  *     mode     - (OUT) Scheduling mode (BCM_COSQ_XXX)
   4077  *     weights  - (OUT) Weights for each COS queue
   4078  *     delay    - This parameter is not used
   4079  * Returns:
   4080  *     BCM_E_XXX
   4081  */
   4082 int
   4083 bcm_th_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
   4084                            int *mode, int *weights, int *delay)
   4085 {
   4086     bcm_port_t port;
   4087     int i, num_weights;
   4088 
   4089     BCM_PBMP_ITER(pbm, port) {
   4090         if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) {
   4091             continue;
   4092         }
   4093         num_weights = _TH_NUM_COS(unit);
   4094         for (i = 0; i < num_weights; i++) {
   4095             BCM_IF_ERROR_RETURN(
   4096                 _bcm_th_cosq_sched_get(unit, port, i, mode, &weights[i]));
   4097         }
   4098     }
   4099 
   4100     return BCM_E_NONE;
   4101 }
   4102 
   4103 /*
   4104  * Function:
   4105  *     bcm_th_cosq_sched_weight_max_get
   4106  * Purpose:
   4107  *     Retrieve maximum weights for given COS policy
   4108  * Parameters:
   4109  *     unit    - (IN) unit number
   4110  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   4111  *     weight_max - (OUT) Maximum weight for COS queue.
   4112  * Returns:
   4113  *     BCM_E_XXX
   4114  */
   4115 int
   4116 bcm_th_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   4117 {
   4118     switch (mode) {
   4119     case BCM_COSQ_STRICT:
   4120         *weight_max = BCM_COSQ_WEIGHT_STRICT;
   4121         break;
   4122     case BCM_COSQ_ROUND_ROBIN:
   4123     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   4124     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   4125          /* In TH the maximum weight will be 127 */
   4126         *weight_max =
   4127             (1 << soc_mem_field_length(unit, Q_SCHED_L0_WEIGHT_MEMm,
   4128                                        WEIGHTf)) - 1;
   4129         break;
   4130     default:
   4131         return BCM_E_PARAM;
   4132     }
   4133 
   4134     return BCM_E_NONE;
   4135 }
   4136 
   4137 /*
   4138  * Function:
   4139  *     bcm_th_cosq_port_bandwidth_set
   4140  * Purpose:
   4141  *     Configure COS queue bandwidth control
   4142  * Parameters:
   4143  *     unit          - (IN) unit number
   4144  *     port          - (IN) port number or GPORT identifier
   4145  *     cosq          - (IN) COS queue number
   4146  *     min_quantum   - (IN)
   4147  *     max_quantum   - (IN)
   4148  *     burst_quantum - (IN)
   4149  *     flags         - (IN)
   4150  * Returns:
   4151  *     BCM_E_XXX
   4152  * Notes:
   4153  *     If port is any form of local port, cosq is the hardware queue index.
   4154  */
   4155 int
   4156 bcm_th_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   4157                                bcm_cos_queue_t cosq,
   4158                                uint32 min_quantum, uint32 max_quantum,
   4159                                uint32 burst_quantum, uint32 flags)
   4160 {
   4161     uint32 burst_min, burst_max;
   4162 
   4163     if (cosq < 0) {
   4164         return BCM_E_PARAM;
   4165     }
   4166 
   4167     if (BCM_GPORT_IS_SET(port) &&
   4168         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   4169           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4170           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4171           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   4172         return BCM_E_UNAVAIL;
   4173     }
   4174 
   4175     burst_min = (min_quantum > 0) ?
   4176           _bcm_td_default_burst_size(unit, port, min_quantum) : 0;
   4177 
   4178     burst_max = (max_quantum > 0) ?
   4179           _bcm_td_default_burst_size(unit, port, max_quantum) : 0;
   4180 
   4181     return _bcm_th_cosq_bucket_set(unit, port, cosq, min_quantum, max_quantum,
   4182                                     burst_min, burst_max, flags);
   4183 }
   4184 
   4185 /*
   4186  * Function:
   4187  *     bcm_th_cosq_port_bandwidth_get
   4188  * Purpose:
   4189  *     Get COS queue bandwidth control configuration
   4190  * Parameters:
   4191  *     unit          - (IN) unit number
   4192  *     port          - (IN) port number or GPORT identifier
   4193  *     cosq          - (IN) COS queue number
   4194  *     min_quantum   - (OUT)
   4195  *     max_quantum   - (OUT)
   4196  *     burst_quantum - (OUT)
   4197  *     flags         - (OUT)
   4198  * Returns:
   4199  *     BCM_E_XXX
   4200  * Notes:
   4201  *     If port is any form of local port, cosq is the hardware queue index.
   4202  */
   4203 int
   4204 bcm_th_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   4205                                bcm_cos_queue_t cosq,
   4206                                uint32 *min_quantum, uint32 *max_quantum,
   4207                                uint32 *burst_quantum, uint32 *flags)
   4208 {
   4209     uint32 kbit_burst_min;
   4210 
   4211     if (cosq < -1) {
   4212         return BCM_E_PARAM;
   4213     }
   4214 
   4215     if (BCM_GPORT_IS_SET(port) &&
   4216         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   4217           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4218           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4219           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   4220         return BCM_E_UNAVAIL;
   4221     }
   4222 
   4223     BCM_IF_ERROR_RETURN(_bcm_th_cosq_bucket_get(unit, port, cosq,
   4224                         min_quantum, max_quantum, &kbit_burst_min,
   4225                         burst_quantum, flags));
   4226     return BCM_E_NONE;
   4227 }
   4228 
   4229 int
   4230 bcm_th_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4231                          int pps)
   4232 {
   4233     uint32 min, max, burst, burst_min, flags;
   4234     bcm_port_t  local_port =  port;
   4235 
   4236     if (!IS_CPU_PORT(unit, port)) {
   4237         return BCM_E_PORT;
   4238     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   4239         return BCM_E_PARAM;
   4240     }
   4241 
   4242     if (BCM_GPORT_IS_SET(port) &&
   4243         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   4244           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4245           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4246           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   4247         return BCM_E_UNAVAIL;
   4248     }
   4249 
   4250     BCM_IF_ERROR_RETURN
   4251         (_bcm_th_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min,
   4252                                     &burst, &flags));
   4253     min = pps;
   4254     burst_min = (min > 0) ?
   4255           _bcm_td_default_burst_size(unit, local_port, min) : 0;
   4256     burst = burst_min;
   4257 
   4258     return _bcm_th_cosq_bucket_set(unit, port, cosq, min, pps, burst_min,
   4259                                    burst, flags | BCM_COSQ_BW_PACKET_MODE);
   4260 }
   4261 
   4262 int
   4263 bcm_th_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4264                          int *pps)
   4265 {
   4266     uint32 min, max, burst, flags;
   4267 
   4268     if (!IS_CPU_PORT(unit, port)) {
   4269         return BCM_E_PORT;
   4270     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   4271         return BCM_E_PARAM;
   4272     }
   4273 
   4274     if (BCM_GPORT_IS_SET(port) &&
   4275         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   4276           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4277           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4278           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   4279         return BCM_E_UNAVAIL;
   4280     }
   4281 
   4282     BCM_IF_ERROR_RETURN
   4283         (_bcm_th_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst,
   4284                                  &flags));
   4285     *pps = max;
   4286 
   4287     return BCM_E_NONE;
   4288 }
   4289 
   4290 int
   4291 bcm_th_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4292                            int burst)
   4293 {
   4294     uint32 min, max, cur_burst, flags;
   4295 
   4296     if (!IS_CPU_PORT(unit, port)) {
   4297         return BCM_E_PORT;
   4298     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   4299         return BCM_E_PARAM;
   4300     }
   4301 
   4302     if (BCM_GPORT_IS_SET(port) &&
   4303         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   4304           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4305           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4306           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   4307         return BCM_E_UNAVAIL;
   4308     }
   4309 
   4310     BCM_IF_ERROR_RETURN
   4311         (_bcm_th_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst,
   4312                                  &cur_burst, &flags));
   4313 
   4314     /* Replace the current BURST setting, keep PPS the same */
   4315 
   4316     return _bcm_th_cosq_bucket_set(unit, port, cosq, min, max, burst, burst,
   4317                                    flags | BCM_COSQ_BW_PACKET_MODE);
   4318     return BCM_E_NONE;
   4319 }
   4320 
   4321 int
   4322 bcm_th_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   4323                            int *burst)
   4324 {
   4325     uint32 min, max, cur_burst, cur_burst_min, flags;
   4326 
   4327     if (!IS_CPU_PORT(unit, port)) {
   4328         return BCM_E_PORT;
   4329     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   4330         return BCM_E_PARAM;
   4331     }
   4332 
   4333     if (BCM_GPORT_IS_SET(port) &&
   4334         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   4335           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   4336           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   4337           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   4338         return BCM_E_PARAM;
   4339     }
   4340 
   4341     BCM_IF_ERROR_RETURN
   4342         (_bcm_th_cosq_bucket_get(unit, port, cosq, &min, &max,
   4343                                  &cur_burst_min, &cur_burst, &flags));
   4344     *burst = cur_burst;
   4345     return BCM_E_NONE;
   4346 }
   4347 
   4348 /*
   4349  * Function:
   4350  *     bcm_th_cosq_gport_traverse
   4351  * Purpose:
   4352  *     Walks through the valid COSQ GPORTs and calls
   4353  *     the user supplied callback function for each entry.
   4354  * Parameters:
   4355  *     unit       - (IN) unit number
   4356  *     trav_fn    - (IN) Callback function.
   4357  *     user_data  - (IN) User data to be passed to callback function
   4358  * Returns:
   4359  *     BCM_E_NONE - Success.
   4360  *     BCM_E_XXX
   4361  */
   4362 int
   4363 bcm_th_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb,
   4364                            void *user_data)
   4365 {
   4366     _bcm_th_cosq_port_info_t *port_info = NULL;
   4367     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
   4368     bcm_module_t my_modid, modid_out;
   4369     bcm_port_t port, port_out, local_port;
   4370     bcm_gport_t gport;
   4371     int id, rv = SOC_E_NONE;
   4372 
   4373     if (_bcm_th_cosq_port_info[unit] == NULL) {
   4374         return BCM_E_INIT;
   4375     }
   4376     if (_bcm_th_cosq_cpu_port_info[unit] == NULL) {
   4377         return BCM_E_INIT;
   4378     }
   4379 
   4380     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   4381     PBMP_ALL_ITER(unit, port) {
   4382         BCM_IF_ERROR_RETURN
   4383             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   4384                                      my_modid, port, &modid_out, &port_out));
   4385         BCM_GPORT_MODPORT_SET(gport, modid_out, port_out);
   4386 
   4387         BCM_IF_ERROR_RETURN
   4388             (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   4389 
   4390         if (IS_CPU_PORT(unit, local_port)) {
   4391             cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][local_port];
   4392         } else {
   4393             port_info = &_bcm_th_cosq_port_info[unit][local_port];
   4394         }
   4395         if (!IS_CPU_PORT(unit, local_port)) {
   4396             for (id = 0; id < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; id++) {
   4397                 if (port_info->ucast[id].numq == 0) {
   4398                     continue;
   4399                 }
   4400                 rv = cb(unit, gport, port_info->ucast[id].numq,
   4401                         BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
   4402                         port_info->ucast[id].gport, user_data);
   4403 #ifdef BCM_CB_ABORT_ON_ERR
   4404                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4405                     return rv;
   4406                 }
   4407 #else
   4408                 /*
   4409                  * If CB_ABORT_ON_ERR is not defined don't return error
   4410                  * and continue.
   4411                  */
   4412                 rv = BCM_E_NONE;
   4413 #endif
   4414             }
   4415         }
   4416         if (IS_CPU_PORT(unit, local_port)) {
   4417             for (id = 0; id < _BCM_TH_NUM_CPU_MCAST_QUEUE; id++) {
   4418                 if (cpu_port_info->mcast[id].numq == 0) {
   4419                     continue;
   4420                 }
   4421                 rv = cb(unit, gport, cpu_port_info->mcast[id].numq,
   4422                         BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   4423                         cpu_port_info->mcast[id].gport, user_data);
   4424 #ifdef BCM_CB_ABORT_ON_ERR
   4425                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4426                     return rv;
   4427                 }
   4428 #else
   4429                 /*
   4430                  * If CB_ABORT_ON_ERR is not defined don't return error
   4431                  * and continue.
   4432                  */
   4433                 rv = BCM_E_NONE;
   4434 #endif
   4435             }
   4436         } else {
   4437             for (id = 0; id < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; id++) {
   4438                 if (port_info->mcast[id].numq == 0) {
   4439                     continue;
   4440                 }
   4441                 rv = cb(unit, gport, port_info->mcast[id].numq,
   4442                         BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   4443                         port_info->mcast[id].gport, user_data);
   4444 #ifdef BCM_CB_ABORT_ON_ERR
   4445                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4446                     return rv;
   4447                 }
   4448 #else
   4449                 /*
   4450                  * If CB_ABORT_ON_ERR is not defined don't return error
   4451                  * and continue.
   4452                  */
   4453                 rv = BCM_E_NONE;
   4454 #endif
   4455             }
   4456         }
   4457         for (id = 0; id < _BCM_TH_NUM_SCHEDULER_PER_PORT; id++) {
   4458             if (IS_CPU_PORT(unit, local_port)) {
   4459                 if (cpu_port_info->sched[id].numq == 0) {
   4460                     continue;
   4461                 }
   4462                 rv = cb(unit, gport, cpu_port_info->sched[id].numq,
   4463                         BCM_COSQ_GPORT_SCHEDULER,
   4464                         cpu_port_info->sched[id].gport, user_data);
   4465             } else {
   4466                 if (port_info->sched[id].numq == 0) {
   4467                     continue;
   4468                 }
   4469                 rv = cb(unit, gport, port_info->sched[id].numq,
   4470                         BCM_COSQ_GPORT_SCHEDULER,
   4471                         port_info->sched[id].gport, user_data);
   4472             }
   4473 #ifdef BCM_CB_ABORT_ON_ERR
   4474             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4475                 return rv;
   4476             }
   4477 #else
   4478             /*
   4479              * If CB_ABORT_ON_ERR is not defined don't return error
   4480              * and continue.
   4481              */
   4482             rv = BCM_E_NONE;
   4483 #endif
   4484         }
   4485     }
   4486     return rv;
   4487 }
   4488 
   4489 /*
   4490  * Function:
   4491  *     bcm_cosq_gport_traverse_by_port
   4492  * Purpose:
   4493  *     Walks through the valid COSQ GPORTs belong to a port and calls
   4494  *     the user supplied callback function for each entry.
   4495  * Parameters:
   4496  *     unit       - (IN) unit number
   4497  *     port       - (IN) port number or GPORT identifier
   4498  *     trav_fn    - (IN) Callback function.
   4499  *     user_data  - (IN) User data to be passed to callback function
   4500  * Returns:
   4501  *     BCM_E_NONE - Success.
   4502  *     BCM_E_XXX
   4503  */
   4504 int
   4505 bcm_th_cosq_gport_traverse_by_port(int unit, bcm_gport_t port,
   4506                            bcm_cosq_gport_traverse_cb cb,
   4507                            void *user_data)
   4508 {
   4509     _bcm_th_cosq_port_info_t *port_info = NULL;
   4510     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
   4511     bcm_module_t my_modid, modid_out;
   4512     bcm_port_t port_out, local_port;
   4513     bcm_gport_t gport;
   4514     int id, rv = SOC_E_NONE;
   4515 
   4516     if (_bcm_th_cosq_port_info[unit] == NULL) {
   4517         return BCM_E_INIT;
   4518     }
   4519     if (_bcm_th_cosq_cpu_port_info[unit] == NULL) {
   4520         return BCM_E_INIT;
   4521     }
   4522 
   4523     if (BCM_GPORT_IS_SET(port) &&
   4524         (!BCM_GPORT_IS_LOCAL(port) &&
   4525           !BCM_GPORT_IS_DEVPORT(port) &&
   4526           !BCM_GPORT_IS_MODPORT(port))) {
   4527         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
   4528                   "Invalid gport type\n")));
   4529         return BCM_E_PARAM;
   4530     }
   4531 
   4532     BCM_IF_ERROR_RETURN
   4533         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   4534 
   4535     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   4536 
   4537     BCM_IF_ERROR_RETURN
   4538         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   4539                                  my_modid, port, &modid_out, &port_out));
   4540     BCM_GPORT_MODPORT_SET(gport, modid_out, port_out);
   4541 
   4542     if (IS_CPU_PORT(unit, local_port)) {
   4543         cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][local_port];
   4544     } else {
   4545         port_info = &_bcm_th_cosq_port_info[unit][local_port];
   4546     }
   4547     if (!IS_CPU_PORT(unit, local_port)) {
   4548         for (id = 0; id < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; id++) {
   4549             if (port_info->ucast[id].numq == 0) {
   4550                 continue;
   4551             }
   4552             rv = cb(unit, gport, port_info->ucast[id].numq,
   4553                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
   4554                     port_info->ucast[id].gport, user_data);
   4555 #ifdef BCM_CB_ABORT_ON_ERR
   4556             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4557                 return rv;
   4558             }
   4559 #else
   4560             /*
   4561              * If CB_ABORT_ON_ERR is not defined don't return error
   4562              * and continue.
   4563              */
   4564             rv = BCM_E_NONE;
   4565 #endif
   4566         }
   4567     }
   4568     if (IS_CPU_PORT(unit, local_port)) {
   4569         for (id = 0; id < _BCM_TH_NUM_CPU_MCAST_QUEUE; id++) {
   4570             if (cpu_port_info->mcast[id].numq == 0) {
   4571                 continue;
   4572             }
   4573             rv = cb(unit, gport, cpu_port_info->mcast[id].numq,
   4574                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   4575                     cpu_port_info->mcast[id].gport, user_data);
   4576 #ifdef BCM_CB_ABORT_ON_ERR
   4577             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4578                 return rv;
   4579             }
   4580 #else
   4581             /*
   4582              * If CB_ABORT_ON_ERR is not defined don't return error
   4583              * and continue.
   4584              */
   4585             rv = BCM_E_NONE;
   4586 #endif
   4587         }
   4588     } else {
   4589         for (id = 0; id < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; id++) {
   4590             if (port_info->mcast[id].numq == 0) {
   4591                 continue;
   4592             }
   4593             rv = cb(unit, gport, port_info->mcast[id].numq,
   4594                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   4595                     port_info->mcast[id].gport, user_data);
   4596 #ifdef BCM_CB_ABORT_ON_ERR
   4597             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4598                 return rv;
   4599             }
   4600 #else
   4601             /*
   4602              * If CB_ABORT_ON_ERR is not defined don't return error
   4603              * and continue.
   4604              */
   4605             rv = BCM_E_NONE;
   4606 #endif
   4607         }
   4608     }
   4609     for (id = 0; id < _BCM_TH_NUM_SCHEDULER_PER_PORT; id++) {
   4610         if (IS_CPU_PORT(unit, local_port)) {
   4611             if (cpu_port_info->sched[id].numq == 0) {
   4612                 continue;
   4613             }
   4614             rv = cb(unit, gport, cpu_port_info->sched[id].numq,
   4615                     BCM_COSQ_GPORT_SCHEDULER,
   4616                     cpu_port_info->sched[id].gport, user_data);
   4617         } else {
   4618             if (port_info->sched[id].numq == 0) {
   4619                 continue;
   4620             }
   4621             rv = cb(unit, gport, port_info->sched[id].numq,
   4622                     BCM_COSQ_GPORT_SCHEDULER,
   4623                     port_info->sched[id].gport, user_data);
   4624         }
   4625 #ifdef BCM_CB_ABORT_ON_ERR
   4626         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   4627             return rv;
   4628         }
   4629 #else
   4630         /*
   4631          * If CB_ABORT_ON_ERR is not defined don't return error
   4632          * and continue.
   4633          */
   4634         rv = BCM_E_NONE;
   4635 #endif
   4636     }
   4637 
   4638     return rv;
   4639 }
   4640 
   4641 
   4642 /*
   4643  * Function:
   4644  *     bcm_th_cosq_gport_sched_get
   4645  * Purpose:
   4646  *     Get COS queue schedular setting
   4647  * Parameters:
   4648  *     unit     - (IN) unit number
   4649  *     gport    - (IN) GPORT identifier
   4650  *     cosq     - (IN) COS queue to get, -1 for any queue
   4651  *     mode     - (OUT) Scheduling mode (BCM_COSQ_XXX)
   4652  *     weights  - (OUT) Weights for queue
   4653  * Returns:
   4654  *     BCM_E_XXX
   4655  */
   4656 int
   4657 bcm_th_cosq_gport_sched_get(int unit, bcm_gport_t gport,
   4658                             bcm_cos_queue_t cosq, int *mode, int *weight)
   4659 {
   4660     _bcm_th_cosq_node_t *node = NULL;
   4661     int local_port = -1, cpu_mc_base = 0;
   4662     soc_info_t *si = &SOC_INFO(unit);
   4663 
   4664     if (BCM_GPORT_IS_SET(gport)) {
   4665         if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   4666              BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4667              BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4668 
   4669             BCM_IF_ERROR_RETURN
   4670                  (_bcm_th_cosq_node_get(unit, gport, NULL, &local_port, NULL, &node));
   4671 
   4672             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4673                 /* For Non-CPU and non-LB ports, num UC queues are 10 */
   4674                 cosq = node->hw_index % si->port_num_cosq[local_port];
   4675             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4676                 /* For Non-CPU ports, num MC queues are 10
   4677                  * For CPU ports, num MC queues are 48
   4678                  */
   4679                 if (IS_CPU_PORT(unit, local_port)) {
   4680                     cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   4681                     cosq = (node->hw_index - cpu_mc_base) %
   4682                            _BCM_TH_NUM_CPU_MCAST_QUEUE;
   4683                 } else {
   4684                     cosq = node->hw_index % si->port_num_cosq[local_port];
   4685                 }
   4686             } else {
   4687                 /* For all ports, total scheduler nodes(L0) are 10 */
   4688                 cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT;
   4689             }
   4690             BCM_IF_ERROR_RETURN(
   4691                 _bcm_th_cosq_sched_get(unit, gport, cosq, mode, weight));
   4692             return BCM_E_NONE;
   4693         } else {
   4694             BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport,
   4695                                                                &local_port));
   4696 
   4697             if ((cosq < 0) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) {
   4698                 return BCM_E_PARAM;
   4699             }
   4700 
   4701             BCM_IF_ERROR_RETURN(
   4702                 _bcm_th_cosq_sched_get(unit, local_port, cosq, mode, weight));
   4703             return BCM_E_NONE;
   4704         }
   4705     } else {
   4706         return BCM_E_PORT;
   4707     }
   4708 
   4709     return BCM_E_NOT_FOUND;
   4710 }
   4711 
   4712 /*
   4713  * Function:
   4714  *     bcm_th_cosq_gport_sched_set
   4715  * Purpose:
   4716  *     Set up class-of-service policy and corresponding weights and delay
   4717  * Parameters:
   4718  *     unit    - (IN) unit number
   4719  *     gport   - (IN) GPORT ID
   4720  *     cosq    - (IN) COS queue to configure
   4721  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   4722  *     weight - (IN) Weight for COS queue
   4723  * Returns:
   4724  *     BCM_E_XXX
   4725  */
   4726 int
   4727 bcm_th_cosq_gport_sched_set(int unit, bcm_gport_t gport,
   4728                            bcm_cos_queue_t cosq, int mode, int weight)
   4729 {
   4730     _bcm_th_cosq_node_t *node = NULL;
   4731     soc_info_t *si = &SOC_INFO(unit);
   4732     int local_port = -1, cpu_mc_base = 0;
   4733 
   4734     if (BCM_GPORT_IS_SET(gport)) {
   4735         if (BCM_GPORT_IS_SCHEDULER(gport) ||
   4736             BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4737             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4738 
   4739             BCM_IF_ERROR_RETURN
   4740                  (_bcm_th_cosq_node_get(unit, gport, NULL, &local_port,
   4741                                         NULL, &node));
   4742 
   4743             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4744                 /* For Non-CPU and non-LB ports, num UC queues are 10 */
   4745                 cosq = node->hw_index % si->port_num_cosq[local_port];
   4746             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4747                 /* For Non-CPU ports, num MC queues are 10
   4748                  * For CPU ports, num MC queues are 48
   4749                  */
   4750                 if (IS_CPU_PORT(unit, local_port)) {
   4751                     cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   4752                     cosq = (node->hw_index - cpu_mc_base) %
   4753                            _BCM_TH_NUM_CPU_MCAST_QUEUE;
   4754                 } else {
   4755                     cosq = node->hw_index % si->port_num_cosq[local_port];
   4756                 }
   4757             } else {
   4758                 /* For all ports, total scheduler nodes(L0) are 10 */
   4759                 cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT;
   4760             }
   4761             BCM_IF_ERROR_RETURN
   4762                 (_bcm_th_cosq_sched_set(unit, gport, cosq, mode, weight));
   4763             return BCM_E_NONE;
   4764         } else {
   4765             BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport,
   4766                                                                &local_port));
   4767 
   4768             if ((cosq < 0) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) {
   4769                 return BCM_E_PARAM;
   4770             }
   4771 
   4772             BCM_IF_ERROR_RETURN
   4773                 (_bcm_th_cosq_sched_set(unit, local_port, cosq, mode, weight));
   4774             return BCM_E_NONE;
   4775         }
   4776     } else {
   4777         return BCM_E_PORT;
   4778     }
   4779 
   4780     return BCM_E_NOT_FOUND;
   4781 }
   4782 
   4783 /*
   4784  * Function:
   4785  *     bcm_th_cosq_gport_bandwidth_set
   4786  * Purpose:
   4787  *     Configure COS queue bandwidth control
   4788  * Parameters:
   4789  *     unit   - (IN) unit number
   4790  *     gport  - (IN) GPORT identifier
   4791  *     cosq   - (IN) COS queue to configure, -1 for all COS queues
   4792  *     kbits_sec_min - (IN) minimum bandwidth, kbits/sec
   4793  *     kbits_sec_max - (IN) maximum bandwidth, kbits/sec
   4794  *     flags  - (IN) BCM_COSQ_BW_*
   4795  * Returns:
   4796  *     BCM_E_XXX
   4797  */
   4798 int
   4799 bcm_th_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
   4800                                 bcm_cos_queue_t cosq, uint32 kbits_sec_min,
   4801                                 uint32 kbits_sec_max, uint32 flags)
   4802 {
   4803     int i, start_cos=0, end_cos=0, local_port;
   4804     _bcm_th_cosq_node_t *node = NULL;
   4805     uint32 burst_min, burst_max;
   4806 
   4807     BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport,
   4808                                                        &local_port));
   4809     if (BCM_GPORT_IS_SET(gport)) {
   4810         if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   4811           BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4812           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4813             BCM_IF_ERROR_RETURN
   4814                 (_bcm_th_cosq_node_get(unit, gport, NULL,
   4815                                         NULL, NULL, &node));
   4816             if (node != NULL) {
   4817                 start_cos = end_cos = node->hw_index;
   4818             } else {
   4819                 cosq = 0;
   4820             }
   4821         } else {
   4822             if (cosq < 0) {
   4823                 return BCM_E_PARAM;
   4824             }
   4825             start_cos = end_cos = cosq;
   4826         }
   4827     } else {
   4828         if (cosq < 0) {
   4829             return BCM_E_PARAM;
   4830         }
   4831         start_cos = end_cos = cosq;
   4832     }
   4833 
   4834     burst_min = (kbits_sec_min > 0) ?
   4835           _bcm_td_default_burst_size(unit, local_port, kbits_sec_min) : 0;
   4836 
   4837     burst_max = (kbits_sec_max > 0) ?
   4838           _bcm_td_default_burst_size(unit, local_port, kbits_sec_max) : 0;
   4839 
   4840     for (i = start_cos; i <= end_cos; i++) {
   4841         BCM_IF_ERROR_RETURN
   4842             (_bcm_th_cosq_bucket_set(unit, gport, i, kbits_sec_min,
   4843                          kbits_sec_max, burst_min, burst_max, flags));
   4844     }
   4845     return BCM_E_NONE;
   4846 }
   4847 
   4848 /*
   4849  * Function:
   4850  *     bcm_th_cosq_gport_bandwidth_get
   4851  * Purpose:
   4852  *     Get COS queue bandwidth control configuration
   4853  * Parameters:
   4854  *     unit   - (IN) unit number
   4855  *     gport  - (IN) GPORT identifier
   4856  *     cosq   - (IN) COS queue to get, -1 for any COS queue
   4857  *     kbits_sec_min - (OUT) minimum bandwidth, kbits/sec
   4858  *     kbits_sec_max - (OUT) maximum bandwidth, kbits/sec
   4859  *     flags  - (OUT) BCM_COSQ_BW_*
   4860  * Returns:
   4861  *     BCM_E_XXX
   4862  */
   4863 int
   4864 bcm_th_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
   4865                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
   4866                                 uint32 *kbits_sec_max, uint32 *flags)
   4867 {
   4868     uint32 kbits_sec_burst;
   4869 
   4870     BCM_IF_ERROR_RETURN
   4871         (_bcm_th_cosq_bucket_get(unit, gport, cosq,
   4872                                  kbits_sec_min, kbits_sec_max,
   4873                                  &kbits_sec_burst, &kbits_sec_burst, flags));
   4874     return BCM_E_NONE;
   4875 }
   4876 
   4877 /*
   4878  * Function:
   4879  *     bcm_th_cosq_gport_bandwidth_burst_set
   4880  * Purpose:
   4881  *     Configure COS queue bandwidth burst setting
   4882  * Parameters:
   4883  *      unit        - (IN) unit number
   4884  *      gport       - (IN) GPORT identifier
   4885  *      cosq        - (IN) COS queue to configure, -1 for all COS queues
   4886  *      kbits_burst - (IN) maximum burst, kbits
   4887  * Returns:
   4888  *      BCM_E_XXX
   4889  */
   4890 int
   4891 bcm_th_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport,
   4892                                       bcm_cos_queue_t cosq,
   4893                                       uint32 kbits_burst_min,
   4894                                       uint32 kbits_burst_max)
   4895 {
   4896     int i, start_cos=0, end_cos=0;
   4897     uint32 kbits_sec_min, kbits_sec_max, kbits_sec_burst, flags;
   4898     bcm_port_t local_port;
   4899 
   4900     BCM_IF_ERROR_RETURN
   4901         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   4902 
   4903     start_cos = end_cos = cosq;
   4904 
   4905     if (cosq == BCM_COS_INVALID) {
   4906         start_cos = 0;
   4907         end_cos = (IS_CPU_PORT(unit, local_port)) ?
   4908                    NUM_CPU_COSQ(unit) - 1 : SOC_PORT_NUM_COSQ(unit, local_port)
   4909                    - 1;
   4910     }
   4911 
   4912     if (BCM_GPORT_IS_SET(gport)) {
   4913         if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   4914              BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4915              BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4916             start_cos = end_cos = 0;
   4917         }
   4918     }
   4919 
   4920     for (i = start_cos; i <= end_cos; i++) {
   4921         BCM_IF_ERROR_RETURN
   4922             (_bcm_th_cosq_bucket_get(unit, gport, i, &kbits_sec_min,
   4923                                      &kbits_sec_max, &kbits_sec_burst,
   4924                                      &kbits_sec_burst, &flags));
   4925         BCM_IF_ERROR_RETURN
   4926             (_bcm_th_cosq_bucket_set(unit, gport, i, kbits_sec_min,
   4927                                      kbits_sec_max, kbits_burst_min,
   4928                                      kbits_burst_max, flags));
   4929     }
   4930     return BCM_E_NONE;
   4931 }
   4932 
   4933 /*
   4934  * Function:
   4935  *     bcm_th_cosq_gport_bandwidth_burst_get
   4936  * Purpose:
   4937  *     Get COS queue bandwidth burst setting
   4938  * Parameters:
   4939  *     unit        - (IN) unit number
   4940  *     gport       - (IN) GPORT identifier
   4941  *     cosq        - (IN) COS queue to get, -1 for Queue 0
   4942  *     kbits_burst - (OUT) maximum burst, kbits
   4943  * Returns:
   4944  *     BCM_E_XXX
   4945  */
   4946 int
   4947 bcm_th_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport,
   4948                                       bcm_cos_queue_t cosq,
   4949                                       uint32 *kbits_burst_min,
   4950                                       uint32 *kbits_burst_max)
   4951 {
   4952     uint32 kbits_sec_min, kbits_sec_max, flags;
   4953 
   4954     if (cosq < -1) {
   4955         return BCM_E_PARAM;
   4956     }
   4957 
   4958     BCM_IF_ERROR_RETURN
   4959         (_bcm_th_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
   4960                                  &kbits_sec_min, &kbits_sec_max, kbits_burst_min,
   4961                                  kbits_burst_max, &flags));
   4962 
   4963     return BCM_E_NONE;
   4964 }
   4965 
   4966 int
   4967 bcm_th_cosq_discard_set(int unit, uint32 flags)
   4968 {
   4969     bcm_port_t port;
   4970 
   4971     if (_bcm_th_cosq_port_info[unit] == NULL) {
   4972         return BCM_E_INIT;
   4973     }
   4974 
   4975     if (flags & ~(BCM_COSQ_DISCARD_DEVICE |
   4976                   BCM_COSQ_DISCARD_NONTCP |
   4977                   BCM_COSQ_DISCARD_COLOR_ALL |
   4978                   BCM_COSQ_DISCARD_PORT |
   4979                   BCM_COSQ_DISCARD_TCP |
   4980                   BCM_COSQ_DISCARD_COLOR_GREEN |
   4981                   BCM_COSQ_DISCARD_COLOR_YELLOW |
   4982                   BCM_COSQ_DISCARD_COLOR_RED |
   4983                   BCM_COSQ_DISCARD_CAP_AVERAGE |
   4984                   BCM_COSQ_DISCARD_ENABLE |
   4985                   BCM_COSQ_DISCARD_MARK_CONGESTION)) {
   4986         return BCM_E_PARAM;
   4987     }
   4988 
   4989     flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL);
   4990 
   4991     PBMP_PORT_ITER(unit, port) {
   4992         BCM_IF_ERROR_RETURN
   4993             (_bcm_th_cosq_wred_set(unit, port, 0, BCM_COSQ_BUFFER_ID_INVALID, 
   4994                                    flags, 0, 0, 0, 0,
   4995                                    FALSE, BCM_COSQ_DISCARD_PORT, 1, 0, 0));
   4996     }
   4997 
   4998     return BCM_E_NONE;
   4999 }
   5000 
   5001 int
   5002 bcm_th_cosq_discard_get(int unit, uint32 *flags)
   5003 {
   5004     bcm_port_t port;
   5005 
   5006     PBMP_PORT_ITER(unit, port) {
   5007         *flags = 0;
   5008         /* use setting from hardware cosq index 0 of the first port */
   5009         return _bcm_th_cosq_wred_get(unit, port, 0, BCM_COSQ_BUFFER_ID_INVALID, 
   5010                                      flags, NULL, NULL, NULL,
   5011                                      NULL, BCM_COSQ_DISCARD_PORT, NULL, NULL,
   5012                                      NULL);
   5013     }
   5014 
   5015     return BCM_E_NOT_FOUND;
   5016 }
   5017 
   5018 /*
   5019  * Function:
   5020  *     bcm_th_cosq_discard_port_set
   5021  * Purpose:
   5022  *     Configure port WRED setting
   5023  * Parameters:
   5024  *     unit          - (IN) unit number
   5025  *     port          - (IN) port number or GPORT identifier
   5026  *     cosq          - (IN) COS queue number
   5027  *     color         - (IN)
   5028  *     drop_start    - (IN)
   5029  *     drop_slot     - (IN)
   5030  *     average_time  - (IN)
   5031  * Returns:
   5032  *     BCM_E_XXX
   5033  * Notes:
   5034  *     If port is any form of local port, cosq is the hardware queue index.
   5035  *     Same as TD2 except for Reg changes.
   5036  */
   5037 int
   5038 bcm_th_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5039                              uint32 color, int drop_start, int drop_slope,
   5040                              int average_time)
   5041 {
   5042     bcm_port_t local_port;
   5043     bcm_pbmp_t pbmp;
   5044     int gain;
   5045     uint32 min_thresh, max_thresh, shared_limit, xpe_map;
   5046     uint32 bits, flags = 0;
   5047     int numq, i;
   5048 
   5049     if (drop_start < 0 || drop_start > 100 ||
   5050         drop_slope < 0 || drop_slope > 90) {
   5051         return BCM_E_PARAM;
   5052     }
   5053 
   5054     /*
   5055      * average queue size is reculated every 1us, the formula is
   5056      * avg_qsize(t + 1) =
   5057      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   5058      * gain = log2(average_time)
   5059      */
   5060     bits = average_time & 0xffff;
   5061     if (bits != 0) {
   5062         bits |= bits >> 1;
   5063         bits |= bits >> 2;
   5064         bits |= bits >> 4;
   5065         bits |= bits >> 8;
   5066         gain = _shr_popcount(bits) - 1;
   5067     } else {
   5068         gain = 0;
   5069     }
   5070 
   5071     /*
   5072      * per-port cell limit may be disabled.
   5073      * per-port per-cos cell limit may be set to use dynamic method.
   5074      * therefore drop_start percentage is based on per-device total shared
   5075      * cells.
   5076      */
   5077     xpe_map = SOC_INFO(unit).ipipe_xpe_map[0]|SOC_INFO(unit).ipipe_xpe_map[1];
   5078     _TH_ARRAY_MIN(_BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, NUM_XPE(unit),
   5079                   xpe_map, shared_limit);
   5080     min_thresh = ((drop_start * shared_limit) + (100 - 1)) / 100;
   5081 
   5082     /* Calculate the max threshold. For a given slope (angle in
   5083      * degrees), determine how many packets are in the range from
   5084      * 0% drop probability to 100% drop probability. Add that
   5085      * number to the min_treshold to the the max_threshold.
   5086      */
   5087     max_thresh = min_thresh + _bcm_th_angle_to_cells(drop_slope);
   5088     if (max_thresh > TH_WRED_CELL_FIELD_MAX) {
   5089         max_thresh = TH_WRED_CELL_FIELD_MAX;
   5090     }
   5091 
   5092     if (BCM_GPORT_IS_SET(port)) {
   5093         numq = 1;
   5094         for (i = 0; i < numq; i++) {
   5095             BCM_IF_ERROR_RETURN
   5096                 (_bcm_th_cosq_wred_set(unit, port, cosq + i, 
   5097                                        BCM_COSQ_BUFFER_ID_INVALID, color,
   5098                                        min_thresh, max_thresh, 100, gain,
   5099                                        TRUE, flags, 1, 0, 0));
   5100         }
   5101     } else {
   5102         if (port == -1) {
   5103             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   5104         } else if (!SOC_PORT_VALID(unit, port)) {
   5105             return BCM_E_PORT;
   5106         } else {
   5107             BCM_PBMP_PORT_SET(pbmp, port);
   5108         }
   5109 
   5110         BCM_PBMP_ITER(pbmp, local_port) {
   5111             numq = 1;
   5112             for (i = 0; i < numq; i++) {
   5113                 BCM_IF_ERROR_RETURN
   5114                     (_bcm_th_cosq_wred_set(unit, local_port, cosq + i,
   5115                                            BCM_COSQ_BUFFER_ID_INVALID, color, 
   5116                                            min_thresh, max_thresh, 100, gain,
   5117                                            TRUE, 0, 1, 0, 0));
   5118             }
   5119         }
   5120     }
   5121 
   5122     return BCM_E_NONE;
   5123 }
   5124 
   5125 /*
   5126  * Function:
   5127  *     bcm_th_cosq_discard_port_get
   5128  * Purpose:
   5129  *     Get port WRED setting
   5130  * Parameters:
   5131  *     unit          - (IN) unit number
   5132  *     port          - (IN) port number or GPORT identifier
   5133  *     cosq          - (IN) COS queue number
   5134  *     color         - (OUT)
   5135  *     drop_start    - (OUT)
   5136  *     drop_slot     - (OUT)
   5137  *     average_time  - (OUT)
   5138  * Returns:
   5139  *     BCM_E_XXX
   5140  * Notes:
   5141  *     If port is any form of local port, cosq is the hardware queue index.
   5142  *     Same as TD2 except for Reg changes.
   5143  */
   5144 int
   5145 bcm_th_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   5146                              uint32 color, int *drop_start, int *drop_slope,
   5147                              int *average_time)
   5148 {
   5149     bcm_port_t local_port;
   5150     bcm_pbmp_t pbmp;
   5151     int gain, drop_prob;
   5152     uint32 min_thresh, max_thresh, shared_limit, xpe_map;
   5153     int refresh_time = 0;
   5154 
   5155     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   5156         return BCM_E_PARAM;
   5157     }
   5158 
   5159     if (BCM_GPORT_IS_SET(port)) {
   5160         local_port = port;
   5161     } else {
   5162         if (port == -1) {
   5163             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   5164         } else if (!SOC_PORT_VALID(unit, port)) {
   5165             return BCM_E_PORT;
   5166         } else {
   5167             BCM_PBMP_PORT_SET(pbmp, port);
   5168         }
   5169         BCM_PBMP_ITER(pbmp, local_port) {
   5170             break;
   5171         }
   5172     }
   5173 
   5174     BCM_IF_ERROR_RETURN
   5175         (_bcm_th_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq,
   5176                                BCM_COSQ_BUFFER_ID_INVALID,
   5177                                &color, &min_thresh, &max_thresh, &drop_prob,
   5178                                &gain, 0, &refresh_time, NULL, NULL));
   5179 
   5180     /*
   5181      * average queue size is reculated every 8us, the formula is
   5182      * avg_qsize(t + 1) =
   5183      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   5184      */
   5185     *average_time = (1 << gain);
   5186 
   5187     xpe_map = SOC_INFO(unit).ipipe_xpe_map[0]|SOC_INFO(unit).ipipe_xpe_map[1];
   5188     _TH_ARRAY_MIN(_BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, NUM_XPE(unit),
   5189                   xpe_map, shared_limit);
   5190 
   5191     if (min_thresh > shared_limit) {
   5192         min_thresh = shared_limit;
   5193     }
   5194 
   5195     if (max_thresh > shared_limit) {
   5196         max_thresh = shared_limit;
   5197     }
   5198 
   5199     *drop_start = min_thresh * 100 / shared_limit;
   5200 
   5201     /* Calculate the slope using the min and max threshold.
   5202      * The angle is calculated knowing drop probability at min
   5203      * threshold is 0% and drop probability at max threshold is 100%.
   5204      */
   5205     *drop_slope = _bcm_th_cells_to_angle(max_thresh - min_thresh);
   5206 
   5207     return BCM_E_NONE;
   5208 }
   5209 
   5210 /*
   5211  * Function:
   5212  *     bcm_th_cosq_gport_discard_set
   5213  * Purpose:
   5214  *     Configure port WRED setting
   5215  * Parameters:
   5216  *     unit    - (IN) unit number
   5217  *     port    - (IN) GPORT identifier
   5218  *     cosq    - (IN) COS queue to configure, -1 for all COS queues
   5219  *     buffer  - (IN) XPE ID
   5220  *     discard - (IN) discard settings
   5221  * Returns:
   5222  *     BCM_E_XXX
   5223  */
   5224 int
   5225 bcm_th_cosq_gport_discard_set(int unit, bcm_gport_t gport,
   5226                               bcm_cos_queue_t cosq,
   5227                               bcm_cosq_buffer_id_t buffer,
   5228                               bcm_cosq_gport_discard_t *discard)
   5229 {
   5230     int numq, i;
   5231     uint32 min_thresh, max_thresh, flags = 0;
   5232     int cell_size, cell_field_max;
   5233     bcm_port_t local_port = -1;
   5234 
   5235     /* Time Domain */
   5236     /* the reasonable range of refresh_time  is from 1 to 64 */
   5237     if (discard == NULL ||
   5238         discard->gain < 0 || discard->gain > 15 ||
   5239         discard->drop_probability < 0 || discard->drop_probability > 100 ||
   5240         discard->profile_id > 3 ||
   5241         discard->refresh_time <= 0 || discard->refresh_time > 64) {
   5242         return BCM_E_PARAM;
   5243     }
   5244 
   5245     if (discard == NULL ||
   5246         discard->gain < 0 || discard->gain > 15 ||
   5247         discard->drop_probability < 0 || discard->drop_probability > 100 ||
   5248         (discard->min_thresh > discard->max_thresh) ||
   5249         (discard->min_thresh < 0)) {
   5250         return BCM_E_PARAM;
   5251     }
   5252 
   5253     cell_size = _TH_MMU_BYTES_PER_CELL;
   5254     cell_field_max = 0xffff;
   5255 
   5256     min_thresh = discard->min_thresh;
   5257     max_thresh = discard->max_thresh;
   5258     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   5259         /* Convert bytes to cells */
   5260         min_thresh += (cell_size - 1);
   5261         min_thresh /= cell_size;
   5262 
   5263         max_thresh += (cell_size - 1);
   5264         max_thresh /= cell_size;
   5265 
   5266         if ((min_thresh > cell_field_max) ||
   5267             (max_thresh > cell_field_max)) {
   5268             return BCM_E_PARAM;
   5269         }
   5270     } else if (discard->flags & BCM_COSQ_DISCARD_PACKETS) {
   5271         /* Packet mode not supported */
   5272         return BCM_E_PARAM;
   5273     } else {
   5274         /* Lower layer function will update thresh when these flags are
   5275          * configured, this interface only allow such opration when
   5276          * BCM_COSQ_DISCARD_BYTES is also configured.
   5277          */
   5278         if (discard->flags & (BCM_COSQ_DISCARD_COLOR_ALL |
   5279             BCM_COSQ_DISCARD_TCP |
   5280             BCM_COSQ_DISCARD_NONTCP |
   5281             BCM_COSQ_DISCARD_ECT_MARKED |
   5282             BCM_COSQ_DISCARD_RESPONSIVE_DROP |
   5283             BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) {
   5284             return BCM_E_PARAM;
   5285         }
   5286     }
   5287 
   5288     if (gport != BCM_GPORT_INVALID) {
   5289         BCM_IF_ERROR_RETURN
   5290             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   5291         if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) {
   5292             return BCM_E_PORT;
   5293         }
   5294         if ((cosq < -1) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) {
   5295             return BCM_E_PARAM;
   5296         }
   5297     }
   5298 
   5299     numq = 1;
   5300 
   5301     for (i = 0; i < numq; i++) {
   5302         BCM_IF_ERROR_RETURN
   5303             (_bcm_th_cosq_wred_set(unit, gport, cosq + i, buffer,
   5304                                    discard->flags, min_thresh, max_thresh,
   5305                                    discard->drop_probability, discard->gain,
   5306                                    FALSE, flags, discard->refresh_time,
   5307                                    discard->profile_id, discard->use_queue_group));
   5308     }
   5309 
   5310     return BCM_E_NONE;
   5311 }
   5312 
   5313 /*
   5314  * Function:
   5315  *     bcm_th_cosq_gport_discard_get
   5316  * Purpose:
   5317  *     Get port WRED setting
   5318  * Parameters:
   5319  *     unit    - (IN) unit number
   5320  *     port    - (IN) GPORT identifier
   5321  *     cosq    - (IN) COS queue to get, -1 for any queue
   5322  *     buffer  - (IN) XPE ID
   5323  *     discard - (OUT) discard settings
   5324  * Returns:
   5325  *     BCM_E_XXX
   5326  */
   5327 int
   5328 bcm_th_cosq_gport_discard_get(int unit, bcm_gport_t gport,
   5329                               bcm_cos_queue_t cosq,
   5330                               bcm_cosq_buffer_id_t buffer,
   5331                               bcm_cosq_gport_discard_t *discard)
   5332 {
   5333     uint32 min_thresh, max_thresh;
   5334     bcm_port_t local_port = -1;
   5335 
   5336     if (discard == NULL) {
   5337         return BCM_E_PARAM;
   5338     }
   5339 
   5340     if (discard->flags & BCM_COSQ_DISCARD_PACKETS) {
   5341         /* Packet mode not supported */
   5342         return BCM_E_PARAM;
   5343     }
   5344 
   5345     if (gport != BCM_GPORT_INVALID) {
   5346         BCM_IF_ERROR_RETURN
   5347             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   5348         if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) {
   5349             return BCM_E_PORT;
   5350         }
   5351         if ((cosq < -1) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) {
   5352             return BCM_E_PARAM;
   5353         }
   5354     }
   5355 
   5356     BCM_IF_ERROR_RETURN
   5357         (_bcm_th_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq, buffer,
   5358                                &discard->flags, &min_thresh, &max_thresh,
   5359                                &discard->drop_probability, &discard->gain,
   5360                                0, &discard->refresh_time,
   5361                                &discard->profile_id, &discard->use_queue_group));
   5362 
   5363     /* Convert number of cells to number of bytes */
   5364     discard->min_thresh = min_thresh * _TH_MMU_BYTES_PER_CELL;
   5365     discard->max_thresh = max_thresh * _TH_MMU_BYTES_PER_CELL;
   5366 
   5367     return BCM_E_NONE;
   5368 }
   5369 
   5370 int
   5371 bcm_th_pfc_deadlock_ignore_pfc_xoff_gen(int unit, int priority,
   5372                                         bcm_port_t port, uint32 *rval32)
   5373 {
   5374     uint32 profile_index, fc_class;
   5375     uint32 rval, uc_cos_bmp;
   5376     uint64 rval64[16], *rval64s[1];
   5377     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
   5378 
   5379     rval64s[0] = rval64;
   5380     BCM_IF_ERROR_RETURN
   5381         (soc_reg32_get(unit, port_fc_reg, port, 0, &rval));
   5382     profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16;
   5383 
   5384     BCM_IF_ERROR_RETURN
   5385         (soc_profile_reg_get(unit, _bcm_th_prio2cos_profile[unit],
   5386                              profile_index, 16, rval64s));
   5387 
   5388     for (fc_class = 0; fc_class < _BCM_TH_NUM_PFC_CLASS; ++fc_class ) {
   5389 
   5390         uc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[fc_class],
   5391                                            UC_COS_BMPf);
   5392         if (uc_cos_bmp & (1 << priority)) {
   5393             *rval32 = uc_cos_bmp;
   5394             return BCM_E_NONE;
   5395         }
   5396     }
   5397 
   5398     return BCM_E_NOT_FOUND;
   5399 }
   5400 
   5401 STATIC int
   5402 _bcm_th_pfc_deadlock_hw_cos_index_get(int unit, bcm_cos_t priority,
   5403                                       int *hw_cos_index)
   5404 {
   5405     int i, cos_val;
   5406     uint32 rval = 0;
   5407     _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL;
   5408     _bcm_pfc_hw_resorces_t *hw_res = NULL;
   5409 
   5410     pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit);
   5411     hw_res = &pfc_deadlock_control->hw_regs_fields;
   5412 
   5413     SOC_IF_ERROR_RETURN(
   5414         soc_reg32_get(unit, hw_res->chip_config[0], REG_PORT_ANY, 0, &rval));
   5415 
   5416     for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) {
   5417         cos_val = soc_reg_field_get(unit, hw_res->chip_config[0], rval,
   5418                                     hw_res->cos_field[i]);
   5419         if ((cos_val == priority) &&
   5420             (pfc_deadlock_control->hw_cos_idx_inuse[i] == TRUE)) {
   5421             *hw_cos_index = i;
   5422             return BCM_E_NONE;
   5423         }
   5424     }
   5425     return BCM_E_NOT_FOUND;
   5426 }
   5427 
   5428 /* Routine to begin recovery when a Port is deaclared to be in Deadlock by
   5429  * Hardware
   5430  */
   5431 int
   5432 bcm_th_pfc_deadlock_recovery_start(int unit, bcm_port_t port, int priority)
   5433 {
   5434     soc_info_t *si;
   5435     uint32 rval, setval, uc_cos_bmp = 0;
   5436     int rv, phy_port, pipe, local_mmu_port, mmu_port, cos = 0;
   5437     uint64 rval64, temp_rval64, temp_mask64, temp_en64;
   5438     _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL;
   5439     _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL;
   5440     _bcm_pfc_hw_resorces_t *hw_res = NULL;
   5441 
   5442     bcm_port_t local_port = -1;
   5443 
   5444     BCM_IF_ERROR_RETURN
   5445         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   5446 
   5447     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5448 
   5449     si = &SOC_INFO(unit);
   5450     phy_port = si->port_l2p_mapping[local_port];
   5451     mmu_port = si->port_p2m_mapping[phy_port];
   5452     local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1);
   5453 
   5454     pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit);
   5455     if (pfc_deadlock_control == NULL) {
   5456         return BCM_E_INIT;
   5457     }
   5458     hw_res = &pfc_deadlock_control->hw_regs_fields;
   5459 
   5460     pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority);
   5461     if (pfc_deadlock_pri_config->priority != priority) {
   5462         return BCM_E_NOT_FOUND;
   5463     }
   5464 
   5465     COMPILER_64_ZERO(temp_en64);
   5466     COMPILER_64_ZERO(temp_mask64);
   5467     COMPILER_64_ZERO(temp_rval64);
   5468 
   5469     if (local_port >= MAX_PORT(unit)) {
   5470         return BCM_E_PARAM; /* Process for valid ports */
   5471     }
   5472     if (local_mmu_port < 32) {
   5473         COMPILER_64_SET(temp_rval64, 0, (1 << local_mmu_port));
   5474     } else {
   5475         COMPILER_64_SET(temp_rval64, (1 << (local_mmu_port - 32)), 0);
   5476     }
   5477     COMPILER_64_OR(temp_mask64, temp_rval64);
   5478     COMPILER_64_OR(temp_en64, temp_rval64);
   5479 
   5480     LOG_INFO(BSL_LS_BCM_COSQ,
   5481              (BSL_META_U(unit,
   5482                          "PFC Deadlock Detected: Cos %d port=%d\n"),
   5483                          priority, local_port));
   5484 
   5485     rv = _bcm_th_pfc_deadlock_hw_cos_index_get(unit, priority, &cos);
   5486     if (!BCM_SUCCESS(rv)) {
   5487         return BCM_E_FAIL;
   5488     }
   5489     /* 2.a: Mask the Intr DD_TIMER_MASK_A|_B by setting 1 (pbmp) */
   5490     COMPILER_64_ZERO(rval64);
   5491 
   5492     SOC_IF_ERROR_RETURN(
   5493         soc_reg_get(unit, hw_res->timer_mask[cos], pipe,
   5494                     0, &rval64));
   5495 
   5496     COMPILER_64_OR(rval64, temp_mask64);
   5497     SOC_IF_ERROR_RETURN(
   5498         soc_reg_set(unit, hw_res->timer_mask[cos], pipe,
   5499                     0, rval64));
   5500 
   5501     /* 2.b: Turn timer off DD_TIMER_ENABLE_A|_B by setting 0 (pbmp) */
   5502     COMPILER_64_ZERO(rval64);
   5503 
   5504     SOC_IF_ERROR_RETURN(
   5505         soc_reg_get(unit, hw_res->timer_en[cos], pipe,
   5506                     0, &rval64));
   5507 
   5508     COMPILER_64_NOT(temp_en64);
   5509     COMPILER_64_AND(rval64, temp_en64);
   5510     SOC_IF_ERROR_RETURN(
   5511         soc_reg_set(unit, hw_res->timer_en[cos], pipe,
   5512                     0, rval64));
   5513 
   5514     /* 2.c: For that port, set ignore_pfc_xoff = 1 (per port reg) */
   5515     setval = 0;
   5516     SOC_IF_ERROR_RETURN(
   5517         soc_reg32_get(unit, hw_res->port_config, local_port, 0, &setval));
   5518     priority = pfc_deadlock_control->pfc_cos2pri[cos];
   5519 
   5520     rval = bcm_th_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority,
   5521                                                    local_port, &uc_cos_bmp);
   5522     if(rval != BCM_E_NONE) {
   5523         rval = 0;
   5524         rval |= (1 << priority);
   5525     } else {
   5526         rval = 0;
   5527         rval |= uc_cos_bmp;
   5528     }
   5529     setval |= rval;
   5530 
   5531     SOC_IF_ERROR_RETURN(
   5532         soc_reg32_set(unit, hw_res->port_config, local_port, 0, setval));
   5533 
   5534     return BCM_E_NONE;
   5535 }
   5536 
   5537 
   5538 /* Routine to Reset the recovery state of a port and config the port back in
   5539  * original state
   5540  */
   5541 int
   5542 bcm_th_pfc_deadlock_recovery_exit(int unit, bcm_port_t port, int priority)
   5543 {
   5544     soc_info_t *si;
   5545     int rv, phy_port, mmu_port, local_mmu_port, pipe, cos = 0;
   5546     _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL;
   5547     _bcm_pfc_deadlock_config_t *pfc_deadlock_pri_config = NULL;
   5548     uint64 rval64, temp_rval64, temp_mask64, temp_en64;
   5549     uint32 rval, setval, uc_cos_bmp;
   5550     _bcm_pfc_hw_resorces_t *hw_res = NULL;
   5551     bcm_port_t local_port = -1;
   5552 
   5553     si = &SOC_INFO(unit);
   5554     pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit);
   5555     if (pfc_deadlock_control == NULL) {
   5556         return BCM_E_INIT;
   5557     }
   5558     hw_res = &pfc_deadlock_control->hw_regs_fields;
   5559 
   5560     pfc_deadlock_pri_config = _BCM_PFC_DEADLOCK_CONFIG(unit, priority);
   5561     if (pfc_deadlock_pri_config->priority != priority) {
   5562         return BCM_E_NOT_FOUND;
   5563     }
   5564 
   5565     BCM_IF_ERROR_RETURN
   5566         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   5567 
   5568     if (local_port >= MAX_PORT(unit)) {
   5569         return BCM_E_PARAM; /* Process for valid ports */
   5570     }
   5571     phy_port = si->port_l2p_mapping[local_port];
   5572     mmu_port = si->port_p2m_mapping[phy_port];
   5573     local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1);
   5574 
   5575     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5576 
   5577     COMPILER_64_ZERO(temp_en64);
   5578     COMPILER_64_ZERO(temp_mask64);
   5579     COMPILER_64_ZERO(temp_rval64);
   5580 
   5581     if (local_mmu_port < 32) {
   5582         COMPILER_64_SET(temp_rval64, 0, (1 << local_mmu_port));
   5583     } else {
   5584         COMPILER_64_SET(temp_rval64, (1 << (local_mmu_port - 32)), 0);
   5585     }
   5586     COMPILER_64_OR(temp_mask64, temp_rval64);
   5587     COMPILER_64_OR(temp_en64, temp_rval64);
   5588 
   5589     rv = _bcm_th_pfc_deadlock_hw_cos_index_get(unit, priority, &cos);
   5590     if (!BCM_SUCCESS(rv)) {
   5591         return BCM_E_FAIL;
   5592     }
   5593     LOG_INFO(BSL_LS_BCM_COSQ,
   5594              (BSL_META_U(unit,
   5595                          "PFC Deadlock Recovery ends: Prio %d port=%d\n"),
   5596                          priority, port));
   5597 
   5598 
   5599     /* 3.a: For that port, set ignore_pfc_xoff = 0 (per port reg) */
   5600     setval = 0;
   5601     SOC_IF_ERROR_RETURN(
   5602         soc_reg32_get(unit, hw_res->port_config, local_port, 0, &setval));
   5603 
   5604     rval = bcm_th_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority,
   5605                                                  local_port, &uc_cos_bmp);
   5606     if(rval != BCM_E_NONE) {
   5607         setval &= ~(1 << priority);
   5608     } else {
   5609         setval &= ~uc_cos_bmp;
   5610     }
   5611     SOC_IF_ERROR_RETURN(
   5612         soc_reg32_set(unit, hw_res->port_config, local_port, 0, setval));
   5613 
   5614      /* 3.b: Mask the Intr DD_TIMER_MASK_A|_B by setting 0 (pbmp) */
   5615     COMPILER_64_ZERO(rval64);
   5616 
   5617     SOC_IF_ERROR_RETURN(
   5618         soc_reg_get(unit, hw_res->timer_mask[cos], pipe,
   5619                     0, &rval64));
   5620 
   5621     COMPILER_64_NOT(temp_mask64);
   5622     COMPILER_64_AND(rval64, temp_mask64);
   5623     SOC_IF_ERROR_RETURN(
   5624         soc_reg_set(unit, hw_res->timer_mask[cos], pipe, 0, rval64));
   5625 
   5626     /* 3.c: Turn timer on DD_TIMER_ENABLE_A|_B by setting 1 (pbmp) */
   5627     if (BCM_PBMP_MEMBER(pfc_deadlock_pri_config->enabled_ports,
   5628                         local_port)) {
   5629         COMPILER_64_ZERO(rval64);
   5630 
   5631         SOC_IF_ERROR_RETURN(
   5632             soc_reg_get(unit, hw_res->timer_en[cos], pipe,
   5633                         0, &rval64));
   5634 
   5635         COMPILER_64_OR(rval64, temp_en64);
   5636         SOC_IF_ERROR_RETURN(
   5637             soc_reg_set(unit, hw_res->timer_en[cos], pipe, 0, rval64));
   5638     }
   5639 
   5640     return BCM_E_NONE;
   5641 }
   5642 
   5643 /* Flow control APIs */
   5644 
   5645 /*
   5646  * Function:
   5647  *     _bcm_th_cosq_port_fc_get
   5648  * Purpose:
   5649  *     Get the UC|MC gport values associated with
   5650  *     the given PFC/SAFC class.
   5651  * Parameters:
   5652  *     unit             - (IN) unit number
   5653  *     port             - (IN) port number
   5654  *     fc_class       - (IN) PFC/SAFC internal priority class
   5655  *     gport_list       - (OUT) UC|MC gport list
   5656  *     gport_count      - (OUT) gport count
   5657  * Returns:
   5658  *     BCM_E_XXX
   5659  */
   5660 STATIC int
   5661 _bcm_th_cosq_port_fc_get(int unit, bcm_gport_t local_port,
   5662                          int fc_class, bcm_gport_t *gport_list,
   5663                          int *gport_count)
   5664 {
   5665     int hw_cosq, count = 0;
   5666     uint32 profile_index;
   5667     uint32 rval, uc_cos_bmp, mc_cos_bmp;
   5668     uint64 rval64[16], *rval64s[1];
   5669     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
   5670 
   5671     if ((gport_list == NULL) || (gport_count == NULL)) {
   5672         return BCM_E_PARAM;
   5673     }
   5674 
   5675     rval64s[0] = rval64;
   5676     BCM_IF_ERROR_RETURN
   5677         (soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval));
   5678     profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16;
   5679 
   5680     BCM_IF_ERROR_RETURN
   5681         (soc_profile_reg_get(unit, _bcm_th_prio2cos_profile[unit],
   5682                              profile_index, 16, rval64s));
   5683 
   5684     uc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[fc_class],
   5685                                        UC_COS_BMPf);
   5686     mc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[fc_class],
   5687                                        MC_COS_BMPf);
   5688 
   5689     for (hw_cosq = 0; hw_cosq < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; hw_cosq++) {
   5690         if (!(uc_cos_bmp & (1 << hw_cosq))) {
   5691             continue;
   5692         }
   5693         BCM_IF_ERROR_RETURN
   5694             (_bcm_th_cosq_port_cos_resolve(unit, local_port, hw_cosq,
   5695                                            _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5696                                            &gport_list[count++]));
   5697     }
   5698 
   5699     for (hw_cosq = 0; hw_cosq < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; hw_cosq++) {
   5700         if (!(mc_cos_bmp & (1 << hw_cosq))) {
   5701             continue;
   5702         }
   5703         BCM_IF_ERROR_RETURN
   5704             (_bcm_th_cosq_port_cos_resolve(unit, local_port, hw_cosq,
   5705                                            _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5706                                            &gport_list[count++]));
   5707     }
   5708 
   5709     if (count == 0) {
   5710         return BCM_E_NOT_FOUND;
   5711     }
   5712 
   5713     *gport_count = count;
   5714 
   5715     return BCM_E_NONE;
   5716 }
   5717 
   5718 /*
   5719  * Function:
   5720  *    _bcm_th_cosq_port_fc_profile_set
   5721  * Purpose:
   5722  *     Set PFC/SAFC Prio 2 Cos Map and set the profile index for the Port
   5723  * Parameters:
   5724  *     unit         - (IN) unit number
   5725  *     port         - (IN) GPORT identifier
   5726  *     fc_class   - (IN) Input Class
   5727  *     uc_cos_bmp   - (IN) UC Cos bitmap array
   5728  *     mc_cos_bmp   - (IN) MC Cos bitmap array
   5729  *     num_class   - (IN) Number of input class
   5730  * Returns:
   5731  *     BCM_E_XXX
   5732  */
   5733 STATIC int
   5734 _bcm_th_cosq_port_fc_profile_set(int unit, bcm_port_t local_port,
   5735                 int *fc_class, uint32 *uc_cos_bmp, uint32 *mc_cos_bmp,
   5736                 int num_class)
   5737 {
   5738     uint32 profile_index, old_profile_index;
   5739     uint32 rval;
   5740     uint64 rval64[16], *rval64s[1];
   5741     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
   5742     int entry, cur_class;
   5743     uint32 cur_uc_bmp, cur_mc_bmp;
   5744 
   5745     if ((fc_class == NULL) ||
   5746         (uc_cos_bmp == NULL) ||
   5747         (mc_cos_bmp == NULL)) {
   5748         return BCM_E_PARAM;
   5749     }
   5750 
   5751     rval64s[0] = rval64;
   5752     BCM_IF_ERROR_RETURN
   5753         (soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval));
   5754 
   5755     old_profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16;
   5756 
   5757     BCM_IF_ERROR_RETURN
   5758         (soc_profile_reg_get(unit, _bcm_th_prio2cos_profile[unit],
   5759                              old_profile_index, 16, rval64s));
   5760 
   5761     for (entry = 0; entry < num_class; entry++) {
   5762         cur_class = fc_class[entry];
   5763         cur_uc_bmp = uc_cos_bmp[entry];
   5764         cur_mc_bmp = mc_cos_bmp[entry];
   5765         soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class],
   5766                               UC_COS_BMPf, cur_uc_bmp);
   5767         soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[cur_class],
   5768                               MC_COS_BMPf, cur_mc_bmp);
   5769 
   5770     }
   5771 
   5772     BCM_IF_ERROR_RETURN
   5773         (soc_profile_reg_add(unit, _bcm_th_prio2cos_profile[unit], rval64s,
   5774                              16, &profile_index));
   5775 
   5776     soc_reg_field_set(unit, port_fc_reg, &rval, PROFILE_INDEXf,
   5777                       profile_index / 16);
   5778 
   5779     BCM_IF_ERROR_RETURN
   5780         (soc_profile_reg_delete(unit, _bcm_th_prio2cos_profile[unit],
   5781                                 old_profile_index));
   5782 
   5783     BCM_IF_ERROR_RETURN
   5784         (soc_reg32_set(unit, port_fc_reg, local_port, 0, rval));
   5785 
   5786     return BCM_E_NONE;
   5787 }
   5788 
   5789 /*
   5790  * Function:
   5791  *      _bcm_th_fc_status_map_gport
   5792  * Purpose:
   5793  *      Set mapping in PFC/SAFC for gport, and update
   5794  *      uc_cos_bmp/mc_cos_bmp with gport cosq.
   5795  * Parameters:
   5796  *      unit        - (IN) unit number
   5797  *      port        - (IN) port number
   5798  *      gport       - (IN) gport to be mapped
   5799  *      uc_cos_map     - (OUT) unicast hw_cosq of gport
   5800  *      mc_cos_map     - (OUT) multicast hw_cosq of gport
   5801  * Returns:
   5802  *      BCM_E_XXX
   5803  */
   5804 STATIC int
   5805 _bcm_th_fc_status_map_gport(int unit, bcm_port_t port,
   5806                 bcm_gport_t gport, uint32 *uc_cos_bmp, uint32 *mc_cos_bmp)
   5807 {
   5808     _bcm_th_cosq_node_t *node = NULL;
   5809     bcm_port_t local_port = -1;
   5810     bcm_cos_queue_t cosq = -1;
   5811 
   5812     BCM_IF_ERROR_RETURN
   5813         (_bcm_th_cosq_node_get(unit, gport, NULL, &local_port, NULL,
   5814                                &node));
   5815 
   5816     if (node == NULL) {
   5817         return BCM_E_PARAM;
   5818     }
   5819 
   5820     if (local_port < 0) {
   5821         return BCM_E_PARAM;
   5822     }
   5823 
   5824     if (local_port != port) {
   5825         return BCM_E_PARAM;
   5826     }
   5827 
   5828     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5829         cosq = node->hw_index %
   5830                    _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
   5831         *uc_cos_bmp |= 1 << cosq;
   5832     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5833         cosq = node->hw_index %
   5834                    _BCM_TH_NUM_MCAST_QUEUE_PER_PORT;
   5835         *mc_cos_bmp |= 1 << cosq;
   5836     }
   5837 
   5838     return BCM_E_NONE;
   5839 }
   5840 
   5841 /*
   5842  * Function:
   5843  *     bcm_th_cosq_port_pfc_op
   5844  * Purpose:
   5845  *     Set PFC Prio 2 Cos Map and set the profile index for the Port
   5846  * Parameters:
   5847  *     unit     - (IN) unit number
   5848  *     port     - (IN) GPORT identifier
   5849  *     sctype   - (IN) Input Class
   5850  *     op       - (IN) Operation to be performed (ADD|SET|CLEAR)
   5851  *     gport    - (IN) Gport/Cos array
   5852  *     gport_ct - (IN) Count of values in the array
   5853  * Returns:
   5854  *     BCM_E_XXX
   5855  */
   5856 int
   5857 bcm_th_cosq_port_pfc_op(int unit, bcm_port_t port,
   5858                         bcm_switch_control_t sctype, _bcm_cosq_op_t op,
   5859                         bcm_gport_t *gport, int gport_count)
   5860 {
   5861     bcm_port_t local_port;
   5862     int type = -1, class = -1, index, hw_cosq, hw_cosq1;
   5863     uint32 profile_index, old_profile_index;
   5864     uint32 rval, fval, cos_bmp;
   5865     uint64 rval64[16], *rval64s[1];
   5866     _bcm_th_cosq_node_t *node;
   5867     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
   5868     soc_field_t field = INVALIDf;
   5869     soc_info_t *si = &SOC_INFO(unit);
   5870     int rv = SOC_E_NONE;
   5871 
   5872     if (gport_count < 0) {
   5873         return BCM_E_PARAM;
   5874     }
   5875 
   5876     BCM_IF_ERROR_RETURN
   5877         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   5878 
   5879     BCM_IF_ERROR_RETURN(_bcm_th_cosq_pfc_class_resolve(sctype, &type, &class));
   5880 
   5881     cos_bmp = 0;
   5882 
   5883     if (type == _BCM_TH_COSQ_TYPE_MCAST) {
   5884         field = MC_COS_BMPf;
   5885     } else {
   5886         field = UC_COS_BMPf;
   5887     }
   5888 
   5889     for (index = 0; index < gport_count; index++) {
   5890         hw_cosq = hw_cosq1 = -1;
   5891         if (BCM_GPORT_IS_SET(gport[index]) &&
   5892             ((BCM_GPORT_IS_SCHEDULER(gport[index])) ||
   5893               BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport[index]) ||
   5894               BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport[index]))) {
   5895             BCM_IF_ERROR_RETURN
   5896                 (_bcm_th_cosq_node_get(unit, gport[index], NULL,
   5897                                        NULL, NULL, &node));
   5898             if (BCM_GPORT_IS_SCHEDULER(gport[index])) {
   5899                 hw_cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT;
   5900             } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport[index])) {
   5901                 if (type != _BCM_TH_COSQ_TYPE_UCAST) {
   5902                     return BCM_E_PARAM;
   5903                 }
   5904                 hw_cosq = node->hw_index % si->port_num_cosq[local_port];
   5905             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport[index])) {
   5906                 if (type != _BCM_TH_COSQ_TYPE_MCAST) {
   5907                     return BCM_E_PARAM;
   5908                 }
   5909                 hw_cosq = node->hw_index % si->port_num_cosq[local_port];
   5910             }
   5911         } else {
   5912             /* Find hardware index for given local_port, cosq */
   5913             hw_cosq = gport[index] % 10;
   5914         }
   5915         cos_bmp |= 1 << hw_cosq;
   5916     }
   5917 
   5918     rval64s[0] = rval64;
   5919     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval));
   5920 
   5921     if (op == _BCM_COSQ_OP_CLEAR || cos_bmp != 0) {
   5922         old_profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16;
   5923 
   5924         BCM_IF_ERROR_RETURN
   5925             (soc_profile_reg_get(unit, _bcm_th_prio2cos_profile[unit],
   5926                                  old_profile_index, 16, rval64s));
   5927         if (op == _BCM_COSQ_OP_SET) {
   5928             soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class],
   5929                                   field, cos_bmp);
   5930         } else if (op == _BCM_COSQ_OP_CLEAR || cos_bmp != 0) {
   5931             fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class],
   5932                                          field);
   5933             if (op == _BCM_COSQ_OP_ADD) {
   5934                 fval |= cos_bmp;
   5935             } else { /* _BCM_COSQ_OP_DELETE */
   5936                 fval = 0;
   5937             }
   5938             soc_reg64_field32_set(unit, PRIO2COS_PROFILEr, &rval64[class],
   5939                                   field, fval);
   5940         }
   5941         BCM_IF_ERROR_RETURN
   5942             (soc_profile_reg_delete(unit, _bcm_th_prio2cos_profile[unit],
   5943                                     old_profile_index));
   5944         rv = soc_profile_reg_add(unit, _bcm_th_prio2cos_profile[unit], rval64s,
   5945                                  16, &profile_index);
   5946         if (rv != BCM_E_NONE) {
   5947             SOC_IF_ERROR_RETURN
   5948                 (soc_profile_reg_reference(unit, _bcm_th_prio2cos_profile[unit],
   5949                                            old_profile_index, 16));
   5950             return rv;
   5951         }
   5952         soc_reg_field_set(unit, port_fc_reg, &rval, PROFILE_INDEXf,
   5953                           profile_index / 16);
   5954     }
   5955     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, port_fc_reg, local_port, 0, rval));
   5956 
   5957     return BCM_E_NONE;
   5958 }
   5959 
   5960 /*
   5961  * Function:
   5962  *     bcm_th_cosq_port_pfc_get
   5963  * Purpose:
   5964  *     Get PFC Prio2Cos Map for a given Traffic Class
   5965  * Parameters:
   5966  *     unit     - (IN) unit number
   5967  *     port     - (IN) GPORT identifier
   5968  *     sctype   - (IN) Input Traffic Class
   5969  *     gport    - (OUT) Gport/Cos array
   5970  *     gport_ct - (IN) Input Count of gport required
   5971  *     actual_gport_ct - (OUT) Actual Count of gport/cos in the array
   5972  * Returns:
   5973  *     BCM_E_XXX
   5974  */
   5975 int
   5976 bcm_th_cosq_port_pfc_get(int unit, bcm_port_t port,
   5977                          bcm_switch_control_t sctype,
   5978                          bcm_gport_t *gport, int gport_count,
   5979                          int *actual_gport_count)
   5980 {
   5981     bcm_port_t local_port;
   5982     int type = 0, class = -1, hw_cosq, count = 0;
   5983     uint32 profile_index;
   5984     uint32 rval, cos_bmp;
   5985     uint64 rval64[16], *rval64s[1];
   5986     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
   5987     soc_field_t field = INVALIDf;
   5988 
   5989     if (gport == NULL || gport_count <= 0 || actual_gport_count == NULL) {
   5990         return BCM_E_PARAM;
   5991     }
   5992 
   5993     BCM_IF_ERROR_RETURN
   5994         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   5995 
   5996     BCM_IF_ERROR_RETURN(_bcm_th_cosq_pfc_class_resolve(sctype, &type, &class));
   5997 
   5998     rval64s[0] = rval64;
   5999     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval));
   6000     profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16;
   6001 
   6002     if (type == _BCM_TH_COSQ_TYPE_MCAST) {
   6003         field = MC_COS_BMPf;
   6004     } else {
   6005         field = UC_COS_BMPf;
   6006     }
   6007 
   6008     BCM_IF_ERROR_RETURN
   6009         (soc_profile_reg_get(unit, _bcm_th_prio2cos_profile[unit],
   6010                              profile_index, 16, rval64s));
   6011 
   6012     cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILEr, rval64[class],
   6013                                     field);
   6014     for (hw_cosq = 0; hw_cosq < 10; hw_cosq++) {
   6015         if (!(cos_bmp & (1 << hw_cosq))) {
   6016             continue;
   6017         }
   6018         gport[count++] = hw_cosq;
   6019 
   6020         if (count == gport_count) {
   6021             break;
   6022         }
   6023     }
   6024     if (count == 0) {
   6025         return BCM_E_NOT_FOUND;
   6026     }
   6027     *actual_gport_count = count;
   6028 
   6029     return BCM_E_NONE;
   6030 }
   6031 
   6032 /*
   6033  * Function:
   6034  *     bcm_th_cosq_pfc_class_mapping_set
   6035  * Purpose:
   6036  *     Set PFC mapping for port.
   6037  *     PFC class is mapped to cosq or scheduler node gports.
   6038  * Parameters:
   6039  *     unit             - (IN) unit number
   6040  *     port             - (IN) port number
   6041  *     array_count      - (IN) count of mapping
   6042  *     mapping_array    - (IN) mappings
   6043  * Returns:
   6044  *     BCM_E_XXX
   6045  */
   6046 int
   6047 bcm_th_cosq_pfc_class_mapping_set(int unit, bcm_gport_t port,
   6048                                   int array_count,
   6049                                   bcm_cosq_pfc_class_mapping_t *mapping_array)
   6050 {
   6051     int index, count;
   6052     int cur_class = 0;
   6053     int pfc_class[_BCM_TH_NUM_PFC_CLASS];
   6054     bcm_gport_t cur_gport = 0;
   6055     uint32 uc_cos_bmp[_BCM_TH_NUM_PFC_CLASS] = {0};
   6056     uint32 mc_cos_bmp[_BCM_TH_NUM_PFC_CLASS] = {0};
   6057     bcm_port_t local_port = -1;
   6058 
   6059     BCM_IF_ERROR_RETURN
   6060         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   6061 
   6062     if (local_port < 0) {
   6063         return BCM_E_PORT;
   6064     }
   6065 
   6066     if (IS_CPU_PORT(unit, local_port)) {
   6067         return BCM_E_PORT;
   6068     }
   6069 
   6070     if ((array_count < 0) || (array_count > _BCM_TH_NUM_PFC_CLASS)) {
   6071         return BCM_E_PARAM;
   6072     }
   6073 
   6074     if (mapping_array == NULL) {
   6075         return BCM_E_PARAM;
   6076     }
   6077 
   6078     for (count = 0; count < array_count; count++) {
   6079         cur_class = mapping_array[count].class_id;
   6080         if ((cur_class < 0) || (cur_class >= _BCM_TH_NUM_PFC_CLASS)) {
   6081             return BCM_E_PARAM;
   6082         } else {
   6083             uc_cos_bmp[cur_class] = 0;
   6084             mc_cos_bmp[cur_class] = 0;
   6085         }
   6086 
   6087         for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) {
   6088             cur_gport = mapping_array[count].gport_list[index];
   6089             if (cur_gport == BCM_GPORT_INVALID) {
   6090                 break;
   6091             }
   6092 
   6093             if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) ||
   6094                 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport))) {
   6095                 BCM_IF_ERROR_RETURN
   6096                     (_bcm_th_fc_status_map_gport(unit, local_port, cur_gport,
   6097                                                    &uc_cos_bmp[cur_class],
   6098                                                    &mc_cos_bmp[cur_class]));
   6099             } else {
   6100                 return BCM_E_PARAM;
   6101             }
   6102         }
   6103     }
   6104 
   6105     for (index = 0; index < _BCM_TH_NUM_PFC_CLASS; index++) {
   6106         pfc_class[index] = index;
   6107     }
   6108     BCM_IF_ERROR_RETURN
   6109         (_bcm_th_cosq_port_fc_profile_set(unit, local_port, pfc_class,
   6110                                           uc_cos_bmp, mc_cos_bmp,
   6111                                           _BCM_TH_NUM_PFC_CLASS));
   6112 
   6113     return BCM_E_NONE;
   6114 }
   6115 
   6116 /*
   6117  * Function:
   6118  *     bcm_th_cosq_pfc_class_mapping_get
   6119  * Purpose:
   6120  *     Get PFC mapping for port.
   6121  *     Retrieves cosq or scheduler node gports
   6122  *     associated to PFC classes.
   6123  * Parameters:
   6124  *     unit             - (IN) unit number
   6125  *     port             - (IN) port number
   6126  *     array_max        - (IN) max retrieve count
   6127  *     mapping_array    - (OUT) mappings
   6128  *     array_count      - (OUT) retrieved mapping count
   6129  * Returns:
   6130  *     BCM_E_XXX
   6131  */
   6132 int
   6133 bcm_th_cosq_pfc_class_mapping_get(int unit, bcm_gport_t port,
   6134                                   int array_max,
   6135                                   bcm_cosq_pfc_class_mapping_t *mapping_array,
   6136                                   int *array_count)
   6137 {
   6138     int rv = 0;
   6139     int cur_class = 0;
   6140     int actual_gport_count, class_count = 0;
   6141     bcm_port_t local_port = -1;
   6142 
   6143     BCM_IF_ERROR_RETURN
   6144         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   6145 
   6146     if (local_port < 0) {
   6147         return BCM_E_PORT;
   6148     }
   6149 
   6150     if (IS_CPU_PORT(unit, local_port)) {
   6151         return BCM_E_PORT;
   6152     }
   6153 
   6154     if (((mapping_array == NULL) && (array_max > 0)) ||
   6155         ((mapping_array != NULL) && (array_max <= 0)) ||
   6156         (array_count == NULL)) {
   6157         return BCM_E_PARAM;
   6158     }
   6159 
   6160     if (array_max <= 0) {
   6161         *array_count = _BCM_TH_NUM_PFC_CLASS;
   6162         return BCM_E_NONE;
   6163     }
   6164 
   6165     for (cur_class = 0; cur_class < _BCM_TH_NUM_PFC_CLASS; cur_class++) {
   6166         actual_gport_count = 0;
   6167         rv = _bcm_th_cosq_port_fc_get(unit, local_port, cur_class,
   6168                                       mapping_array[class_count].gport_list,
   6169                                       &actual_gport_count);
   6170 
   6171         if (rv == BCM_E_NONE) {
   6172             mapping_array[class_count].class_id = cur_class;
   6173             if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) {
   6174                 mapping_array[class_count].gport_list[actual_gport_count] =
   6175                                                         BCM_GPORT_INVALID;
   6176             }
   6177             class_count++;
   6178         } else if (rv != BCM_E_NOT_FOUND) {
   6179             return rv;
   6180         }
   6181 
   6182         if (class_count == array_max) {
   6183             break;
   6184         }
   6185     }
   6186 
   6187     *array_count = class_count;
   6188     if (class_count == 0) {
   6189         return BCM_E_NOT_FOUND;
   6190     }
   6191 
   6192     return BCM_E_NONE;
   6193 }
   6194 
   6195 
   6196 /*
   6197  * Function:
   6198  *      bcm_th_port_priority_group_mapping_set
   6199  * Purpose:
   6200  *      Assign a Priority Group for the input priority.
   6201  * Parameters:
   6202  *      unit       - (IN) device id.
   6203  *      gport     - (IN) generic port.
   6204  *      prio       - (IN) input priority.
   6205  *      priority_group  - (IN) PG ID that the input priority mapped to.
   6206  * Returns:
   6207  *      BCM_E_XXX
   6208  */
   6209 int
   6210 bcm_th_port_priority_group_mapping_set(int unit, bcm_gport_t gport,
   6211                                         int prio, int priority_group)
   6212 {
   6213     bcm_port_t port;
   6214     uint32 value;
   6215     int field_count;
   6216     soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   6217                             PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf};
   6218     soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   6219                             PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf};
   6220 
   6221     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
   6222         return BCM_E_UNAVAIL;
   6223     }
   6224     /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */
   6225     if ((prio < TH_SAFC_INPUT_PRIORITY_MIN) || 
   6226         (prio > TH_SAFC_INPUT_PRIORITY_MAX)) {
   6227         return BCM_E_PARAM;
   6228     }
   6229 
   6230     if ((priority_group < TH_PRIOROTY_GROUP_ID_MIN) || 
   6231         (priority_group > TH_PRIOROTY_GROUP_ID_MAX)) {
   6232         return BCM_E_PARAM;
   6233     }
   6234 
   6235     BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, &port));
   6236     if (!SOC_PORT_VALID(unit, port)) {
   6237         return BCM_E_PORT;
   6238     }
   6239     field_count = COUNTOF(fields_0);
   6240     if (prio < field_count) {
   6241         /* input priority 0~7 */
   6242         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value));
   6243         soc_reg_field_set(unit, THDI_PORT_PRI_GRP0r, &value, 
   6244                           fields_0[prio], priority_group);
   6245         BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP0r(unit, port, value));
   6246     } else {
   6247         /* input priority 8~15 */
   6248         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value));
   6249         soc_reg_field_set(unit, THDI_PORT_PRI_GRP1r, &value, 
   6250                           fields_1[prio - field_count], priority_group);
   6251         BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PRI_GRP1r(unit, port, value));
   6252     }
   6253 
   6254     return BCM_E_NONE;
   6255 }
   6256 
   6257 /*
   6258  * Function:
   6259  *      bcm_th_port_priority_group_mapping_get
   6260  * Purpose:
   6261  *      Get the assigned Priority Group ID of the input priority.
   6262  * Parameters:
   6263  *      unit       - (IN) device id.
   6264  *      gport     - (IN) generic port.
   6265  *      prio       - (IN) input priority.
   6266  *      priority_group  - (OUT) PG ID that the input priority mapped to.
   6267  * Returns:
   6268  *      BCM_E_XXX
   6269  */
   6270 int
   6271 bcm_th_port_priority_group_mapping_get(int unit, bcm_gport_t gport,
   6272                                         int prio, int *priority_group)
   6273 {
   6274     bcm_port_t port;
   6275     uint32 value;
   6276     int field_count;
   6277     soc_field_t fields_0[]={PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   6278                             PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf};
   6279     soc_field_t fields_1[]={PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   6280                             PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf};
   6281 
   6282     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
   6283         return BCM_E_UNAVAIL;
   6284     }
   6285     if (priority_group == NULL) {
   6286         return BCM_E_PARAM;
   6287     }
   6288     /* PFC : 0-7, SAFC : 0-15. Taking the larger range for comparison */
   6289     if ((prio < TH_SAFC_INPUT_PRIORITY_MIN) || 
   6290         (prio > TH_SAFC_INPUT_PRIORITY_MAX)) {
   6291         return BCM_E_PARAM;
   6292     }
   6293 
   6294     BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, &port));
   6295     if (!SOC_PORT_VALID(unit, port)) {
   6296         return BCM_E_PORT;
   6297     }
   6298     field_count = COUNTOF(fields_0);
   6299     if (prio < field_count) {
   6300         /* input priority 0~7 */
   6301         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP0r(unit, port, &value));
   6302         *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP0r,
   6303                                             value, fields_0[prio]);
   6304     } else {
   6305         /* input priority 8~15 */
   6306         BCM_IF_ERROR_RETURN(READ_THDI_PORT_PRI_GRP1r(unit, port, &value));
   6307         *priority_group = soc_reg_field_get(unit, THDI_PORT_PRI_GRP1r,
   6308                                             value, 
   6309                                             fields_1[prio - field_count]);
   6310     }
   6311 
   6312     return BCM_E_NONE;
   6313 }
   6314 
   6315 /*
   6316  * Function:
   6317  *      bcm_th_port_priority_group_config_set
   6318  * Purpose:
   6319  *      Set the port priority group configuration.
   6320  * Parameters:
   6321  *      unit       - (IN) device id.
   6322  *      gport     - (IN) generic port.
   6323  *      priority_group - (IN) priority group id.
   6324  *      prigrp_config  - (IN) structure describes port PG configuration.
   6325  * Returns:
   6326  *      BCM_E_XXX
   6327  */
   6328 int
   6329 bcm_th_port_priority_group_config_set(int unit, bcm_gport_t gport,
   6330     int priority_group, bcm_port_priority_group_config_t *prigrp_config)
   6331 {
   6332     bcm_port_t port;
   6333     uint32 rval, pri_bmp;
   6334 
   6335     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
   6336         return BCM_E_UNAVAIL;
   6337     }
   6338     if ((priority_group < TH_PRIOROTY_GROUP_ID_MIN) || 
   6339         (priority_group > TH_PRIOROTY_GROUP_ID_MAX)) {
   6340         return BCM_E_PARAM;
   6341     }
   6342     if (prigrp_config == NULL) {
   6343         return BCM_E_PARAM;
   6344     }
   6345     if (prigrp_config->shared_pool_xoff_enable ||
   6346         prigrp_config->shared_pool_discard_enable ||
   6347         prigrp_config->priority_enable_vector_mask) {
   6348         return BCM_E_UNAVAIL;
   6349     }
   6350     BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, &port));
   6351     if (!SOC_PORT_VALID(unit, port)) {
   6352         return BCM_E_PORT;
   6353     }
   6354 
   6355     SOC_IF_ERROR_RETURN(READ_THDI_INPUT_PORT_XON_ENABLESr(unit, port, &rval));
   6356     pri_bmp = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval,
   6357                                 PORT_PRI_XON_ENABLEf);
   6358 
   6359     if (prigrp_config->pfc_transmit_enable) {
   6360         pri_bmp |= (1 << priority_group);
   6361     } else {
   6362         pri_bmp &= ~(1 << priority_group);
   6363     }
   6364     /* To cover higher 8 PFC classes that have no corresponding PG. */
   6365     if ((pri_bmp & 0xff) == 0) {
   6366         pri_bmp = 0;
   6367     }
   6368 
   6369     soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 
   6370                                 PORT_PRI_XON_ENABLEf, pri_bmp);
   6371     BCM_IF_ERROR_RETURN(WRITE_THDI_INPUT_PORT_XON_ENABLESr(unit, port, rval));
   6372 
   6373     return BCM_E_NONE;
   6374 }
   6375 
   6376 /*
   6377  * Function:
   6378  *      bcm_th_port_priority_group_config_get
   6379  * Purpose:
   6380  *      Get the port priority group configuration.
   6381  * Parameters:
   6382  *      unit       - (IN) device id.
   6383  *      gport     - (IN) generic port.
   6384  *      priority_group - (IN) priority group id.
   6385  *      prigrp_config  - (OUT) structure describes port PG configuration.
   6386  * Returns:
   6387  *      BCM_E_XXX
   6388  */
   6389 int
   6390 bcm_th_port_priority_group_config_get(int unit, bcm_gport_t gport,
   6391     int priority_group, bcm_port_priority_group_config_t *prigrp_config)
   6392 {
   6393     bcm_port_t port;
   6394     uint32 rval, pri_bmp;
   6395 
   6396     if (!soc_feature(unit, soc_feature_priority_flow_control)) {
   6397         return BCM_E_UNAVAIL;
   6398     }
   6399     if ((priority_group < TH_PRIOROTY_GROUP_ID_MIN) || 
   6400         (priority_group > TH_PRIOROTY_GROUP_ID_MAX)) {
   6401         return BCM_E_PARAM;
   6402     }
   6403     if (prigrp_config == NULL) {
   6404         return BCM_E_PARAM;
   6405     }
   6406 
   6407     BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, &port));
   6408     if (!SOC_PORT_VALID(unit, port)) {
   6409         return BCM_E_PORT;
   6410     }
   6411 
   6412     SOC_IF_ERROR_RETURN(READ_THDI_INPUT_PORT_XON_ENABLESr(unit, port, &rval));
   6413     pri_bmp = soc_reg_field_get(unit, THDI_INPUT_PORT_XON_ENABLESr, rval,
   6414                                 PORT_PRI_XON_ENABLEf);
   6415     if (pri_bmp & (1U << priority_group)) {
   6416         prigrp_config->pfc_transmit_enable = 1;
   6417     } else {
   6418         prigrp_config->pfc_transmit_enable = 0;
   6419     }
   6420 
   6421     return BCM_E_NONE;
   6422 }
   6423 
   6424 /*
   6425  * Function:
   6426  *     bcm_th_cosq_gport_add
   6427  * Purpose:
   6428  *     Create a cosq gport structure
   6429  * Parameters:
   6430  *     unit  - (IN) unit number
   6431  *     port  - (IN) port number
   6432  *     numq  - (IN) number of COS queues
   6433  *     flags - (IN) flags (BCM_COSQ_GPORT_XXX)
   6434  *     gport - (OUT) GPORT identifier
   6435  * Returns:
   6436  *     BCM_E_XXX
   6437  */
   6438 int
   6439 bcm_th_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags,
   6440                       bcm_gport_t *gport)
   6441 {
   6442     _bcm_th_cosq_port_info_t *port_info = NULL;
   6443     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
   6444     _bcm_th_cosq_node_t *node;
   6445     uint32 sched_encap;
   6446     bcm_port_t local_port;
   6447     int id;
   6448 
   6449     LOG_INFO(BSL_LS_BCM_COSQ,
   6450              (BSL_META_U(unit,
   6451                          "bcm_th_cosq_gport_add: unit=%d port=0x%x "
   6452                          "numq=%d flags=0x%x\n"),
   6453               unit, port, numq, flags));
   6454 
   6455     if (gport == NULL) {
   6456         return BCM_E_PARAM;
   6457     }
   6458 
   6459     if (_bcm_th_cosq_port_info[unit] == NULL) {
   6460         return BCM_E_INIT;
   6461     }
   6462 
   6463     if (_bcm_th_cosq_cpu_port_info[unit] == NULL) {
   6464         return BCM_E_INIT;
   6465     }
   6466 
   6467     BCM_IF_ERROR_RETURN
   6468         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
   6469 
   6470     if (local_port < 0 || IS_LB_PORT(unit, local_port)) {
   6471         return BCM_E_PORT;
   6472     }
   6473 
   6474     if (IS_CPU_PORT(unit, local_port)) {
   6475         cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][local_port];
   6476     } else  {
   6477         port_info = &_bcm_th_cosq_port_info[unit][local_port];
   6478     }
   6479     switch (flags) {
   6480         case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   6481             if (IS_CPU_PORT(unit, local_port)) {
   6482                 return BCM_E_PARAM;
   6483             }
   6484             if (numq != 1) {
   6485                 return BCM_E_PARAM;
   6486             }
   6487             for (id = 0; id < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; id++) {
   6488                 if ((port_info->ucast[id].numq == 0) ||
   6489                     (port_info->ucast[id].in_use == 0)) {
   6490                     break;
   6491                 }
   6492             }
   6493             if (id == _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) {
   6494                 return BCM_E_RESOURCE;
   6495             }
   6496             BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   6497             node = &port_info->ucast[id];
   6498             node->level = SOC_TH_NODE_LVL_L1;
   6499             break;
   6500         case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   6501             if (numq != 1) {
   6502                 return BCM_E_PARAM;
   6503             }
   6504             if (IS_CPU_PORT(unit, local_port)) {
   6505                 for (id = 0; id < _BCM_TH_NUM_CPU_MCAST_QUEUE; id++) {
   6506                     if ((cpu_port_info->mcast[id].numq == 0) ||
   6507                         (cpu_port_info->mcast[id].in_use == 0)) {
   6508                         break;
   6509                     }
   6510                 }
   6511                 if (id == _BCM_TH_NUM_CPU_MCAST_QUEUE) {
   6512                     return BCM_E_RESOURCE;
   6513                 }
   6514             } else {
   6515                 for (id = 0; id < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; id++) {
   6516                     if ((port_info->mcast[id].numq == 0) ||
   6517                         (port_info->mcast[id].in_use == 0)) {
   6518                         break;
   6519                     }
   6520                 }
   6521                 if (id == _BCM_TH_NUM_MCAST_QUEUE_PER_PORT) {
   6522                     return BCM_E_RESOURCE;
   6523                 }
   6524             }
   6525             BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   6526             if (IS_CPU_PORT(unit, local_port)) {
   6527                 node = &cpu_port_info->mcast[id];
   6528             } else {
   6529                 node = &port_info->mcast[id];
   6530             }
   6531             node->level = SOC_TH_NODE_LVL_L1;
   6532             break;
   6533         case BCM_COSQ_GPORT_SCHEDULER:
   6534         case 0:
   6535             if (numq <= 0) {
   6536                 return BCM_E_PARAM;
   6537             }
   6538             for (id = 0; id < _BCM_TH_NUM_SCHEDULER_PER_PORT; id++) {
   6539                 if (IS_CPU_PORT(unit, local_port)) {
   6540                     if (cpu_port_info->sched[id].numq == 0) {
   6541                         break;
   6542                     }
   6543                 } else {
   6544                     if (port_info->sched[id].numq == 0) {
   6545                         break;
   6546                     }
   6547                 }
   6548             }
   6549             if (id == _BCM_TH_NUM_SCHEDULER_PER_PORT) {
   6550                 return BCM_E_RESOURCE;
   6551             }
   6552 
   6553             sched_encap = (id << 16) | local_port;
   6554             BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   6555             if (IS_CPU_PORT(unit, local_port)) {
   6556                 node = &cpu_port_info->sched[id];
   6557             } else {
   6558                 node = &port_info->sched[id];
   6559             }
   6560             node->level = SOC_TH_NODE_LVL_L0;
   6561             break;
   6562         default:
   6563             return BCM_E_UNAVAIL;
   6564     }
   6565 
   6566     node->gport = *gport;
   6567     node->numq = numq;
   6568     node->in_use = 1;
   6569 
   6570     LOG_INFO(BSL_LS_BCM_COSQ,
   6571              (BSL_META_U(unit,
   6572                          "                       gport=0x%x\n"),
   6573               *gport));
   6574 
   6575     return BCM_E_NONE;
   6576 }
   6577 
   6578 STATIC int
   6579 _bcm_th_cosq_rx_queue_channel_set(int unit,
   6580                                   bcm_cos_queue_t parent_cos,
   6581                                   bcm_cos_queue_t queue_id,
   6582                                   int enable)
   6583 {
   6584 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT)
   6585 
   6586     if(soc_feature(unit, soc_feature_cmicm) ||
   6587        soc_feature(unit, soc_feature_cmicx)) {
   6588         int pci_cmc = SOC_PCI_CMC(unit);
   6589         int chan_id = -1;
   6590         int start_chan_id = 0;
   6591         uint32 chan_off;
   6592         uint32 reg_addr, reg_val;
   6593         uint32 ix;
   6594 
   6595         if (parent_cos == 0) {
   6596             chan_id = 1;
   6597         } else if (parent_cos == 1) {
   6598             chan_id = 2;
   6599         } else if (parent_cos == 2) {
   6600             chan_id = 3;
   6601         } else if (parent_cos == 3) {
   6602             chan_id = 0;
   6603         } else {
   6604             return BCM_E_PARAM;
   6605         }
   6606 
   6607         if (!SHR_BITGET(CPU_ARM_QUEUE_BITMAP(unit, pci_cmc), queue_id)) {
   6608             return BCM_E_PARAM;
   6609         }
   6610 
   6611         for (ix = start_chan_id; ix < (start_chan_id + BCM_RX_CHANNELS); ix++) {
   6612             chan_off = ix % BCM_RX_CHANNELS;
   6613             soc_dma_cos_ctrl_reg_addr_get(unit, pci_cmc, chan_off,
   6614                                           queue_id, &reg_addr);
   6615             reg_val = soc_pci_read(unit, reg_addr);
   6616 
   6617             if (enable == 1) {
   6618                 if (ix == (uint32)chan_id) {
   6619                     reg_val |= ((uint32)1 << (queue_id % 32));
   6620                 } else {
   6621                     /* Clear all other channels */
   6622                     reg_val &= ~((uint32)1 << (queue_id % 32));
   6623                 }
   6624             } else {
   6625                 if (ix == (uint32)chan_id) {
   6626                     reg_val &= ~((uint32)1 << (queue_id % 32));
   6627                 }
   6628             }
   6629             /* Incoporate the reserved queues (if any on this device)
   6630              * into the CMIC programming,  */
   6631             reg_val |=
   6632                 CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc)[queue_id / 32];
   6633             soc_pci_write(unit, reg_addr, reg_val);
   6634         }
   6635     }
   6636 #endif
   6637     return BCM_E_NONE;
   6638 }
   6639 
   6640 /*
   6641  * This function does two things:
   6642  * 1. Tests whether the corresponding COS_BMP bit is set or not.
   6643  * 2. Tests whether the queue corresponding to given cos is
   6644  *     mapped to correct L0 or not.
   6645  *
   6646  * L0.0 is associated with CMC0 CH1(Rx) (pci)
   6647  * L0.1 is associated with CMC0 CH2(Rx) (pci)
   6648  * L0.2 is associated with CMC0 CH3(Rx) (pci)
   6649  * L0.3 is associated with CMC0 CH0(Rx) (pci)
   6650  * L0.7 is associated with CMC1 CH1(Rx) (uC0)
   6651  * L0.8 is associated with CMC2 CH1(Rx) (uC1)
   6652  * L0.9 is reserved
   6653  */
   6654 int
   6655 bcm_th_rx_queue_channel_set_test(int unit,
   6656                                  bcm_cos_queue_t queue_id,
   6657                                  bcm_rx_chan_t chan_id)
   6658 {
   6659 #if defined(BCM_CMICM_SUPPORT) || defined(BCM_CMICX_SUPPORT)
   6660     if(soc_feature(unit, soc_feature_cmicm) ||
   6661        soc_feature(unit, soc_feature_cmicx)) {
   6662         int pci_cmc = SOC_PCI_CMC(unit);
   6663         uint32 reg_val;
   6664         uint32 bit;
   6665         _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
   6666         bcm_gport_t cpu_l0_gport = -1;
   6667             bcm_gport_t parent_gport = -1;
   6668 
   6669         if ((chan_id < 0) || (chan_id >= BCM_RX_CHANNELS)) {
   6670             /* Return error for non- pci_cmc channels */
   6671             return BCM_E_PARAM;
   6672         }
   6673 
   6674         if (_bcm_th_cosq_cpu_port_info[unit] == NULL) {
   6675             return BCM_E_INIT;
   6676         }
   6677 
   6678         cpu_port_info = _bcm_th_cosq_cpu_port_info[unit];
   6679 
   6680         if (chan_id == 0) {
   6681             /* l0.3 gport */
   6682             cpu_l0_gport = cpu_port_info->sched[3].gport;
   6683         } else if (chan_id == 1) {
   6684             /* l0.0 gport */
   6685             cpu_l0_gport = cpu_port_info->sched[0].gport;
   6686         } else if (chan_id == 2) {
   6687             /* l0.1 gport */
   6688             cpu_l0_gport = cpu_port_info->sched[1].gport;
   6689         } else if (chan_id == 3) {
   6690             /* l0.2 gport */
   6691             cpu_l0_gport = cpu_port_info->sched[2].gport;
   6692         }
   6693 
   6694         if (queue_id < 0) { /* All COS Queues */
   6695             for (queue_id = 0; queue_id < NUM_CPU_COSQ(unit); queue_id++) {
   6696                 soc_dma_cos_ctrl_queue_get(unit, pci_cmc, chan_id,
   6697                                            queue_id, &reg_val);
   6698 
   6699                 bit = 1 << (queue_id % 32);
   6700                 if (reg_val & bit) {
   6701                     /* find the parent gport of this queue
   6702                        if parent gport is not equal to l0 gport
   6703                        for this channel return error */
   6704                     parent_gport = cpu_port_info->mcast[queue_id].parent_gport;
   6705                     if (parent_gport != cpu_l0_gport) {
   6706                         return BCM_E_PARAM;
   6707                     }
   6708                 }
   6709             }
   6710         } else {
   6711             soc_dma_cos_ctrl_queue_get(unit, pci_cmc, chan_id,
   6712                                            queue_id, &reg_val);
   6713             bit = 1 << (queue_id % 32);
   6714             if (reg_val & bit) {
   6715                 /* find the parent gport of this queue
   6716                    if parent gport is not equal to l0 gport
   6717                    for this channel return error */
   6718                 parent_gport = cpu_port_info->mcast[queue_id].parent_gport;
   6719                 if (parent_gport != cpu_l0_gport) {
   6720                     return BCM_E_PARAM;
   6721                 }
   6722             } else {
   6723                 return BCM_E_PARAM;
   6724             }
   6725         }
   6726     }
   6727 #endif
   6728     return BCM_E_NONE;
   6729 }
   6730 
   6731 #ifdef BCM_WARM_BOOT_SUPPORT
   6732 STATIC int
   6733 _bcm_cosq_rx_queue_channel_reinit(int unit)
   6734 {
   6735     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
   6736     int idx;
   6737     /*
   6738      * L0.0 is associated with CMC0 CH1(Rx) (pci)
   6739      * L0.1 is associated with CMC0 CH2(Rx) (pci)
   6740      * L0.2 is associated with CMC0 CH3(Rx) (pci)
   6741      * L0.3 is associated with CMC0 CH0(Rx) (pci)
   6742      */
   6743     bcm_gport_t sched_gport[4];
   6744     bcm_cos_queue_t parent_cos;
   6745 
   6746     cpu_port_info = _bcm_th_cosq_cpu_port_info[unit];
   6747     if (cpu_port_info == NULL) {
   6748         return BCM_E_INIT;
   6749     }
   6750 
   6751     for (idx = 0; idx < 4; idx++) {
   6752         sched_gport[idx] = cpu_port_info->sched[idx].gport;
   6753     }
   6754 
   6755     for (idx = 0; idx < _BCM_TH_NUM_CPU_MCAST_QUEUE; idx++) {
   6756         parent_cos = -1;
   6757         if (cpu_port_info->mcast[idx].parent_gport == sched_gport[0]) {
   6758             parent_cos = 0;
   6759         } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[1]) {
   6760             parent_cos = 1;
   6761         } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[2]) {
   6762             parent_cos = 2;
   6763         } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[3]) {
   6764             parent_cos = 3;
   6765         }
   6766         if ((parent_cos >= 0) && (parent_cos < 4)) {
   6767             BCM_IF_ERROR_RETURN
   6768                 (_bcm_th_cosq_rx_queue_channel_set(unit, parent_cos, idx, 1));
   6769         }
   6770     }
   6771     return BCM_E_NONE;
   6772 }
   6773 #endif
   6774 
   6775 /* Function to attach any of the 48 L1 MC Queue to one of the 10 L0 nodes
   6776  */
   6777 STATIC int
   6778 bcm_th_cosq_cpu_gport_attach(int unit, bcm_gport_t input_gport,
   6779                              bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   6780 {
   6781     bcm_port_t parent_port, input_port;
   6782     _bcm_th_cosq_node_t *input_node = NULL, *parent_node = NULL;
   6783     int phy_port, mmu_port;
   6784     int input_cos = 0, parent_cos = 0;
   6785     int cpu_sched_base = 0, cpu_mc_base = 0;
   6786     soc_info_t *si = &SOC_INFO(unit);
   6787 
   6788     /* Post Default tree created, expected Input Gport is of MC Gport
   6789      * and expected Parent Gport is new L0 Parent
   6790      */
   6791     if (_BCM_TH_MMU_INFO(unit)->gport_tree_created == FALSE) {
   6792         if (((BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) &&
   6793              (!BCM_GPORT_IS_SCHEDULER(parent_gport))) ||
   6794             (!(BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) &&
   6795              (!BCM_GPORT_IS_SCHEDULER(input_gport)))) {
   6796             return BCM_E_PARAM;
   6797         }
   6798     } else if ((!BCM_GPORT_IS_SCHEDULER(parent_gport)) ||
   6799         (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   6800         return BCM_E_PARAM;
   6801     }
   6802     BCM_IF_ERROR_RETURN
   6803         (_bcm_th_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   6804                                &input_node));
   6805     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   6806         BCM_IF_ERROR_RETURN
   6807             (_bcm_th_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL,
   6808                                    &parent_node));
   6809     } else {
   6810         BCM_IF_ERROR_RETURN
   6811             (_bcm_th_cosq_localport_resolve(unit, parent_gport, &parent_port));
   6812         parent_node = NULL;
   6813     }
   6814 
   6815     if (!IS_CPU_PORT(unit, parent_port)) {
   6816         return BCM_E_PARAM;
   6817     }
   6818 
   6819     /* Return BCM_E_EXISTS when queue to be attached is
   6820        already attached to the given gport */
   6821     if ((_BCM_TH_MMU_INFO(unit)->gport_tree_created == TRUE) &&
   6822         (input_node->parent_gport == parent_gport)) {
   6823         return BCM_E_EXISTS;
   6824     }
   6825 
   6826     phy_port = si->port_l2p_mapping[input_port];
   6827     mmu_port = si->port_p2m_mapping[phy_port];
   6828     cpu_sched_base = mmu_port * _BCM_TH_NUM_SCHEDULER_PER_PORT;
   6829     input_cos = cosq % _BCM_TH_NUM_CPU_MCAST_QUEUE;
   6830     input_node->parent_gport = parent_port;
   6831 
   6832     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   6833         cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   6834         parent_cos = (parent_node->hw_index - cpu_sched_base) %
   6835                      _BCM_TH_NUM_CPU_MCAST_QUEUE;
   6836         SOC_IF_ERROR_RETURN
   6837             (soc_th_cosq_cpu_parent_set(unit, input_cos, SOC_TH_NODE_LVL_L1,
   6838                                         parent_cos));
   6839         if ((parent_cos >= 0) && (parent_cos < 4)) {
   6840             BCM_IF_ERROR_RETURN
   6841                 (_bcm_th_cosq_rx_queue_channel_set(unit, parent_cos, input_cos, 1));
   6842         }
   6843         input_node->parent_gport = parent_node->gport;
   6844         if (_BCM_TH_MMU_INFO(unit)->gport_tree_created == FALSE) {
   6845             input_node->hw_index = cpu_mc_base + input_cos;
   6846         }
   6847     } else {
   6848         input_node->hw_index = cpu_sched_base + input_cos;
   6849     }
   6850 
   6851     return BCM_E_NONE;
   6852 }
   6853 
   6854 /* Function to detach any of the 48 L1 MC Queue from its parent 10 L0 nodes
   6855  * Post detach, L1 MC queue is attached to Parent L0.9 node
   6856  */
   6857 STATIC int
   6858 bcm_th_cosq_cpu_gport_detach(int unit, bcm_gport_t input_gport,
   6859                              bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   6860 {
   6861     bcm_port_t parent_port, input_port;
   6862     _bcm_th_cosq_node_t *input_node = NULL, *parent_node = NULL;
   6863     int phy_port, mmu_port;
   6864     int input_cos = 0, parent_cos = 0, config_cos = 0;
   6865     int cpu_mc_base = 0, cpu_sched_base = 0;
   6866     soc_info_t *si = &SOC_INFO(unit);
   6867 
   6868     /* Post Default tree created, expected Input Gport is of MC Gport
   6869      * and expected Parent Gport is new L0 Parent
   6870      */
   6871     if ((!BCM_GPORT_IS_SCHEDULER(parent_gport)) ||
   6872         (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   6873         return BCM_E_PARAM;
   6874     }
   6875     BCM_IF_ERROR_RETURN
   6876         (_bcm_th_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   6877                                &input_node));
   6878     BCM_IF_ERROR_RETURN
   6879         (_bcm_th_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL,
   6880                                &parent_node));
   6881 
   6882     if (!IS_CPU_PORT(unit, parent_port)) {
   6883         return BCM_E_PARAM;
   6884     }
   6885 
   6886     /* Return BCM_E_PARAM when queue to be detached is
   6887        not attached to the given gport */
   6888     if (input_node->parent_gport != parent_gport) {
   6889         return BCM_E_PARAM;
   6890     }
   6891 
   6892     phy_port = si->port_l2p_mapping[input_port];
   6893     mmu_port = si->port_p2m_mapping[phy_port];
   6894     cpu_sched_base = mmu_port * _BCM_TH_NUM_SCHEDULER_PER_PORT;
   6895     parent_cos = (parent_node->hw_index - cpu_sched_base) %
   6896                 _BCM_TH_NUM_CPU_MCAST_QUEUE;
   6897     cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   6898     input_cos = (input_node->hw_index - cpu_mc_base) %
   6899                 _BCM_TH_NUM_CPU_MCAST_QUEUE;
   6900 
   6901     /* Reset parent to L0.9 */
   6902     SOC_IF_ERROR_RETURN
   6903         (soc_th_cosq_cpu_parent_get(unit, input_cos, SOC_TH_NODE_LVL_L1,
   6904                                     &config_cos));
   6905     if (config_cos != parent_cos) {
   6906         /* Error when detaching from wrong Parent (L0 level) */
   6907         return BCM_E_PARAM;
   6908     }
   6909 
   6910     /*
   6911      * L0.0 is associated with CMC0 CH1(Rx)
   6912      * L0.1 is associated with CMC0 CH2(Rx)
   6913      * L0.2 is associated with CMC0 CH3(Rx)
   6914      * L0.3 is associated with CMC0 CH0(Rx)
   6915      */
   6916     if ((parent_cos >= 0) && (parent_cos < 4)) {
   6917         BCM_IF_ERROR_RETURN
   6918             (_bcm_th_cosq_rx_queue_channel_set(unit, parent_cos, input_cos, 0));
   6919     }
   6920 
   6921     /* Reset parent to L0.9 */
   6922     SOC_IF_ERROR_RETURN
   6923         (soc_th_cosq_cpu_parent_set(unit, input_cos, SOC_TH_NODE_LVL_L1,
   6924                                     _BCM_TH_NUM_SCHEDULER_PER_PORT - 1));
   6925     input_node->parent_gport =
   6926         _BCM_TH_MMU_INFO(unit)->_bcm_th_cpu_port_info->
   6927             sched[_BCM_TH_NUM_SCHEDULER_PER_PORT -1].gport;
   6928 
   6929     return BCM_E_NONE;
   6930 }
   6931 
   6932 /*
   6933  * Function:
   6934  *     bcm_th_cosq_gport_attach
   6935  * Purpose:
   6936  *     Attach sched_port to the specified index (cosq) of input_port
   6937  * Parameters:
   6938  *     unit         - (IN) unit number
   6939  *     input_gport  - (IN) GPORT id, that will attach to parent gport
   6940  *     parent_gport - (IN) Parent Gport to which current gport will be attached
   6941  *     cosq         - (IN) COS queue to attach to (-1 for first available cosq)
   6942  * Returns:
   6943  *     BCM_E_XXX
   6944  */
   6945 int
   6946 bcm_th_cosq_gport_attach(int unit, bcm_gport_t input_gport,
   6947                          bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   6948 {
   6949     _bcm_th_cosq_node_t *input_node = NULL, *parent_node = NULL;
   6950     bcm_port_t input_port, parent_port;
   6951     int phy_port, mmu_port;
   6952     int input_hw_index = -1, parent_hw_index = -1;
   6953     soc_info_t *si = &SOC_INFO(unit);
   6954 
   6955     LOG_INFO(BSL_LS_BCM_COSQ,
   6956              (BSL_META_U(unit,
   6957                          "bcm_th_cosq_gport_attach: unit=%d parent_gport=0x%x "
   6958                          "input_gport=0x%x cosq=%d\n"),
   6959               unit, parent_gport, input_gport, cosq));
   6960 
   6961     if (!(BCM_GPORT_IS_SCHEDULER(input_gport) ||
   6962           BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) ||
   6963           BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   6964         return BCM_E_PARAM;
   6965     }
   6966 
   6967     BCM_IF_ERROR_RETURN
   6968         (_bcm_th_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   6969                                &input_node));
   6970 
   6971     if (!input_node) {
   6972         return BCM_E_PARAM;
   6973     }
   6974     if (input_port < 0) {
   6975         return BCM_E_PORT;
   6976     }
   6977 
   6978     if (IS_CPU_PORT(unit, input_port)) {
   6979         return bcm_th_cosq_cpu_gport_attach(unit, input_gport,
   6980                                                 parent_gport, cosq);
   6981     } else if (_BCM_TH_MMU_INFO(unit)->gport_tree_created == TRUE) {
   6982         return BCM_E_PARAM;
   6983     }
   6984 
   6985     phy_port = si->port_l2p_mapping[input_port];
   6986     mmu_port = si->port_p2m_mapping[phy_port];
   6987 
   6988     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   6989         BCM_IF_ERROR_RETURN
   6990             (_bcm_th_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL,
   6991                                    &parent_node));
   6992     } else {
   6993         BCM_IF_ERROR_RETURN
   6994             (_bcm_th_cosq_localport_resolve(unit, parent_gport, &parent_port));
   6995         parent_node = NULL;
   6996     }
   6997 
   6998     if (input_port != parent_port) {
   6999         return BCM_E_PARAM;
   7000     }
   7001 
   7002     /* TH - Scheduler heirarchy is fixed. Hence check for wrong config. */
   7003     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) {
   7004         input_node->hw_index = (mmu_port * _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) +
   7005                                cosq;
   7006         input_hw_index = input_node->hw_index %
   7007                          _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
   7008     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) {
   7009         input_node->hw_index = (mmu_port * _BCM_TH_NUM_MCAST_QUEUE_PER_PORT) +
   7010                                cosq;
   7011         input_hw_index = input_node->hw_index %
   7012                          _BCM_TH_NUM_MCAST_QUEUE_PER_PORT;
   7013     } else {
   7014         input_node->hw_index = (mmu_port * _BCM_TH_NUM_SCHEDULER_PER_PORT) +
   7015                                cosq;
   7016         input_hw_index = input_node->hw_index %
   7017                          _BCM_TH_NUM_SCHEDULER_PER_PORT;
   7018     }
   7019 
   7020     if (parent_node) {
   7021         parent_hw_index = parent_node->hw_index %
   7022                           _BCM_TH_NUM_SCHEDULER_PER_PORT;
   7023         if (input_hw_index != parent_hw_index) {
   7024             return BCM_E_PARAM;
   7025         }
   7026     }
   7027 
   7028     if (BCM_GPORT_IS_SCHEDULER(input_gport)) {
   7029         BCM_IF_ERROR_RETURN
   7030             (bcm_esw_port_gport_get(unit, input_port,
   7031                                     &(input_node->parent_gport)));
   7032     } else if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) ||
   7033                (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   7034         input_node->parent_gport = parent_gport;
   7035     }
   7036 
   7037     return BCM_E_NONE;
   7038 }
   7039 
   7040 /*
   7041  * Function:
   7042  *     bcm_th_cosq_gport_detach
   7043  * Purpose:
   7044  *     Detach sched_port from the specified index (cosq) of input_port
   7045  * Parameters:
   7046  *     unit        - (IN) unit number
   7047  *     input_port  - (IN) scheduler GPORT identifier
   7048  *     parent_port - (IN) GPORT to detach from
   7049  *     cosq        - (IN) COS queue to detach from
   7050  * Returns:
   7051  *     BCM_E_XXX
   7052  */
   7053 int
   7054 bcm_th_cosq_gport_detach(int unit, bcm_gport_t input_gport,
   7055                          bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   7056 {
   7057     _bcm_th_cosq_node_t *input_node = NULL, *parent_node = NULL;
   7058     bcm_port_t input_port, parent_port;
   7059     int input_hw_index = -1, parent_hw_index = -1;
   7060 
   7061     LOG_INFO(BSL_LS_BCM_COSQ,
   7062              (BSL_META_U(unit,
   7063                          "bcm_th_cosq_gport_detach: unit=%d input_gport=0x%x "
   7064                          "parent_gport=0x%x cosq=%d\n"),
   7065               unit, input_gport, parent_gport, cosq));
   7066 
   7067     if (!(BCM_GPORT_IS_SCHEDULER(input_gport) ||
   7068           BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) ||
   7069           BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   7070         return BCM_E_PARAM;
   7071     }
   7072 
   7073     BCM_IF_ERROR_RETURN
   7074         (_bcm_th_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   7075                                &input_node));
   7076 
   7077     if (!input_node) {
   7078         return BCM_E_PARAM;
   7079     }
   7080 
   7081     if (_BCM_TH_MMU_INFO(unit)->gport_tree_created == TRUE) {
   7082         if (IS_CPU_PORT(unit, input_port)) {
   7083             return bcm_th_cosq_cpu_gport_detach(unit, input_gport,
   7084                                                 parent_gport, cosq);
   7085         } else {
   7086             return BCM_E_PARAM;
   7087         }
   7088     }
   7089 
   7090     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   7091         BCM_IF_ERROR_RETURN
   7092             (_bcm_th_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL,
   7093                                    &parent_node));
   7094     } else {
   7095         BCM_IF_ERROR_RETURN
   7096             (_bcm_th_cosq_localport_resolve(unit, parent_gport, &parent_port));
   7097         parent_node = NULL;
   7098     }
   7099 
   7100     if (input_port != parent_port) {
   7101         return BCM_E_PARAM;
   7102     }
   7103 
   7104     /* TH - Scheduler heirarchy is fixed. Hence check for wrong config. */
   7105     if (parent_node) {
   7106         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) {
   7107             input_hw_index = input_node->hw_index %
   7108                              _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
   7109         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) {
   7110             input_hw_index = input_node->hw_index %
   7111                              _BCM_TH_NUM_MCAST_QUEUE_PER_PORT;
   7112         } else {
   7113             input_hw_index = input_node->hw_index %
   7114                              _BCM_TH_NUM_SCHEDULER_PER_PORT;
   7115         }
   7116 
   7117         parent_hw_index = parent_node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT;
   7118 
   7119         if (input_hw_index != parent_hw_index) {
   7120             return BCM_E_PARAM;
   7121         }
   7122     }
   7123 
   7124     return BCM_E_NONE;
   7125 }
   7126 
   7127 /*
   7128  * Function:
   7129  *     bcm_th_cosq_gport_attach_get
   7130  * Purpose:
   7131  *     Get attached status of a scheduler port
   7132  * Parameters:
   7133  *     unit       - (IN) unit number
   7134  *     sched_port - (IN) scheduler GPORT identifier
   7135  *     input_port - (OUT) GPORT to attach to
   7136  *     cosq       - (OUT) COS queue to attached to
   7137  * Returns:
   7138  *     BCM_E_XXX
   7139  * Notes:
   7140  */
   7141 int
   7142 bcm_th_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport,
   7143                              bcm_gport_t *input_gport, bcm_cos_queue_t *cosq)
   7144 {
   7145     _bcm_th_cosq_node_t *node = NULL;
   7146     int numq = -1, cpu_mc_base = 0;
   7147     bcm_port_t local_port = -1;
   7148     soc_info_t *si = &SOC_INFO(unit);
   7149 
   7150     if (!(BCM_GPORT_IS_SET(sched_gport) ||
   7151           BCM_GPORT_IS_SCHEDULER(sched_gport) ||
   7152           BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) ||
   7153           BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport))) {
   7154         return BCM_E_PARAM;
   7155     }
   7156 
   7157     BCM_IF_ERROR_RETURN
   7158         (_bcm_th_cosq_node_get(unit, sched_gport, NULL, &local_port, NULL,
   7159                                &node));
   7160     if (node == NULL) {
   7161         return BCM_E_PARAM;
   7162     }
   7163 
   7164     if (local_port < 0) {
   7165         return BCM_E_PARAM;
   7166     }
   7167 
   7168     if (BCM_GPORT_IS_SCHEDULER(sched_gport)) {
   7169         *cosq = node->hw_index % _BCM_TH_NUM_SCHEDULER_PER_PORT;
   7170     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport)) {
   7171         *cosq = node->hw_index % _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
   7172     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)) {
   7173         if (IS_CPU_PORT(unit, local_port)) {
   7174             cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   7175             numq = _BCM_TH_NUM_CPU_MCAST_QUEUE;
   7176             *cosq = (node->hw_index - cpu_mc_base) % numq;
   7177         } else {
   7178             numq = _BCM_TH_NUM_MCAST_QUEUE_PER_PORT;
   7179             *cosq = node->hw_index % numq;
   7180         }
   7181     } else {
   7182         return BCM_E_PARAM;
   7183     }
   7184     *input_gport = node->parent_gport;
   7185 
   7186     return BCM_E_NONE;
   7187 }
   7188 
   7189 /*
   7190  * Function:
   7191  *      bcm_th_cosq_gport_child_get
   7192  * Purpose:
   7193  *      Get the child node GPORT atatched to N-th index (cosq)
   7194  *      of the scheduler GPORT.
   7195  * Parameters:
   7196  *      unit       - (IN)  Unit number.
   7197  *      in_gport   - (IN)  Scheduler GPORT ID.
   7198  *      cosq       - (IN)  COS queue attached to.
   7199  *      out_gport  - (OUT) child GPORT ID.
   7200  * Returns:
   7201  *      BCM_E_XXX
   7202  * Notes:
   7203  */
   7204 int
   7205 bcm_th_cosq_gport_child_get(int unit, bcm_gport_t in_gport,
   7206                             bcm_cos_queue_t cosq,
   7207                             bcm_gport_t *out_gport)
   7208 {
   7209     _bcm_th_cosq_node_t *tmp_node = NULL;
   7210     bcm_port_t local_port = -1;
   7211     _bcm_th_cosq_cpu_port_info_t *port_info = NULL;
   7212     int index = -1, cpu_mc_base = 0;
   7213     soc_info_t *si = &SOC_INFO(unit);
   7214 
   7215     if (out_gport == NULL) {
   7216         return BCM_E_PARAM;
   7217     }
   7218 
   7219     BCM_IF_ERROR_RETURN
   7220         (_bcm_th_cosq_localport_resolve(unit, in_gport, &local_port));
   7221 
   7222     if (!SOC_PORT_VALID(unit, local_port)) {
   7223         return BCM_E_PORT;
   7224     }
   7225 
   7226     /* This API is only implemented to CPU ports because
   7227        for all other ports we have fixed hierarchy */
   7228     if (!IS_CPU_PORT(unit, local_port)) {
   7229         return BCM_E_PARAM;
   7230     }
   7231 
   7232     if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) {
   7233         return BCM_E_PARAM;
   7234     }
   7235 
   7236     if (_bcm_th_cosq_cpu_port_info[unit] == NULL) {
   7237         return BCM_E_INIT;
   7238     }
   7239 
   7240     port_info = _bcm_th_cosq_cpu_port_info[unit];
   7241     cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   7242 
   7243     if (BCM_GPORT_IS_SCHEDULER(in_gport)) {
   7244         for (index = 0; index < _BCM_TH_NUM_CPU_MCAST_QUEUE; index++) {
   7245             if (port_info->mcast[index].parent_gport == in_gport) {
   7246                 if (cosq == ((port_info->mcast[index].hw_index - cpu_mc_base) %
   7247                              _BCM_TH_NUM_CPU_MCAST_QUEUE)) {
   7248                     tmp_node = &port_info->mcast[index];
   7249                     break;
   7250                 }
   7251             }
   7252         }
   7253     } else {
   7254         return BCM_E_PARAM;
   7255     }
   7256 
   7257     if (tmp_node == NULL) {
   7258         return BCM_E_NOT_FOUND;
   7259     }
   7260 
   7261     *out_gport = tmp_node->gport;
   7262 
   7263     return BCM_E_NONE;
   7264 }
   7265 
   7266 #ifdef DEAD_CODE
   7267 /*
   7268  * Function:
   7269  *     bcm_th_cosq_gport_delete
   7270  * Purpose:
   7271  *     Destroy a cosq gport structure
   7272  * Parameters:
   7273  *     unit  - (IN) unit number
   7274  *     gport - (IN) GPORT identifier
   7275  * Returns:
   7276  *     BCM_E_XXX
   7277  */
   7278 int
   7279 bcm_th_cosq_gport_delete(int unit, bcm_gport_t gport)
   7280 {
   7281     _bcm_th_cosq_node_t *node = NULL;
   7282     _bcm_th_cosq_port_info_t *port_info = NULL;
   7283     int local_port, i;
   7284 
   7285     LOG_INFO(BSL_LS_BCM_COSQ,
   7286              (BSL_META_U(unit,
   7287                          "bcm_th_cosq_gport_delete: unit=%d gport=0x%x\n"),
   7288               unit, gport));
   7289 
   7290     if (_bcm_th_cosq_port_info[unit] == NULL) {
   7291         return BCM_E_INIT;
   7292     }
   7293 
   7294     
   7295     if (gport == -2) {
   7296         bcm_th_cosq_sw_dump(unit);
   7297     }
   7298 
   7299     if (BCM_GPORT_IS_SCHEDULER(gport) ||
   7300           BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   7301           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7302         BCM_IF_ERROR_RETURN
   7303             (_bcm_th_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   7304 
   7305         if (node->in_use == 0) {
   7306             return BCM_E_UNAVAIL;
   7307         }
   7308     }
   7309 
   7310     BCM_IF_ERROR_RETURN
   7311         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   7312 
   7313     if (!SOC_PORT_VALID(unit, local_port)) {
   7314         return BCM_E_PORT;
   7315     }
   7316     port_info = &_bcm_th_cosq_port_info[unit][local_port];
   7317 
   7318     for (i = 0; i < _BCM_TH_NUM_SCHEDULER_PER_PORT; i++) {
   7319         port_info->sched[i].in_use = 0;
   7320         port_info->sched[i].numq = 0;
   7321     }
   7322     for (i = 0; i < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; i++) {
   7323         port_info->ucast[i].in_use = 0;
   7324         port_info->ucast[i].numq = 0;
   7325     }
   7326     for (i = 0; i < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; i++) {
   7327         port_info->mcast[i].in_use = 0;
   7328         port_info->mcast[i].numq = 0;
   7329     }
   7330     return BCM_E_NONE;
   7331 }
   7332 #endif
   7333 
   7334 /*
   7335  * Function:
   7336  *     _bcm_th_cosq_mapping_set
   7337  * Purpose:
   7338  *     Set COS queue for the specified priority of an ingress port
   7339  * Parameters:
   7340  *     unit     - (IN) unit number
   7341  *     ing_port - (IN) ingress port
   7342  *     gport    - (IN) queue group GPORT identifier
   7343  *     priority - (IN) priority value to map
   7344  *     flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   7345  *     gport    - (IN) queue group GPORT identifier
   7346  *     cosq     - (IN) COS queue number
   7347  * Returns:
   7348  *     BCM_E_XXX
   7349  */
   7350 STATIC int
   7351 _bcm_th_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   7352                          uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq)
   7353 {
   7354     bcm_port_t local_port, out_port;
   7355     bcm_cos_queue_t hw_cosq;
   7356     int rv, idx;
   7357     soc_field_t field[2] = {INVALIDf, INVALIDf}; /* [0]:UC, [1]:MC cos */
   7358     void *entries[1];
   7359     cos_map_sel_entry_t cos_map_sel_entry;
   7360     port_cos_map_entry_t cos_map_entries[_TH_MMU_NUM_INT_PRI];
   7361     uint32 old_index, new_index;
   7362 
   7363     BCM_IF_ERROR_RETURN
   7364         (_bcm_th_cosq_localport_resolve(unit, ing_port, &local_port));
   7365 
   7366     if (gport != -1) {
   7367         BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport,
   7368                                                            &out_port));
   7369     }
   7370 
   7371     switch (flags) {
   7372         case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   7373             if (gport == -1) {
   7374                 hw_cosq = cosq;
   7375             } else {
   7376                 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7377                     return BCM_E_PARAM;
   7378                 }
   7379                 BCM_IF_ERROR_RETURN
   7380                     (_bcm_th_cosq_index_resolve
   7381                      (unit, gport, cosq, _BCM_TH_COSQ_INDEX_STYLE_COS,
   7382                       NULL, &hw_cosq, NULL));
   7383             }
   7384             hw_cosq %= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
   7385             field[0] = UC_COS1f;
   7386             break;
   7387         case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   7388             if (gport == -1) {
   7389                 hw_cosq = cosq;
   7390             } else {
   7391                 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7392                     return BCM_E_PARAM;
   7393                 }
   7394                 BCM_IF_ERROR_RETURN
   7395                     (_bcm_th_cosq_index_resolve
   7396                      (unit, gport, cosq, _BCM_TH_COSQ_INDEX_STYLE_COS,
   7397                       NULL, &hw_cosq, NULL));
   7398             }
   7399             hw_cosq %= _BCM_TH_NUM_MCAST_QUEUE_PER_PORT;
   7400             field[0] = MC_COS1f;
   7401             break;
   7402         case (BCM_COSQ_GPORT_UCAST_QUEUE_GROUP |
   7403               BCM_COSQ_GPORT_MCAST_QUEUE_GROUP):
   7404             if (gport == -1) {
   7405                 hw_cosq = cosq;
   7406             } else {
   7407                 return BCM_E_PARAM;
   7408             }
   7409             hw_cosq %= _BCM_TH_NUM_SCHEDULER_PER_PORT;
   7410             field[0] = UC_COS1f;
   7411             field[1] = MC_COS1f;
   7412             break;
   7413         default:
   7414             return BCM_E_PARAM;
   7415     }
   7416 
   7417     entries[0] = &cos_map_entries;
   7418 
   7419     BCM_IF_ERROR_RETURN
   7420         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   7421                            &cos_map_sel_entry));
   7422     old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   7423                                     SELECTf);
   7424     old_index *= _TH_MMU_NUM_INT_PRI;
   7425 
   7426     BCM_IF_ERROR_RETURN
   7427         (soc_profile_mem_get(unit, _bcm_th_cos_map_profile[unit],
   7428                              old_index, _TH_MMU_NUM_INT_PRI, entries));
   7429 
   7430     for (idx = 0; idx < 2; idx++) {
   7431         if (field[idx] != INVALIDf) {
   7432             soc_mem_field32_set(unit, PORT_COS_MAPm,
   7433                                 &cos_map_entries[priority],
   7434                                 field[idx], hw_cosq);
   7435         }
   7436     }
   7437 
   7438     soc_mem_lock(unit, PORT_COS_MAPm);
   7439 
   7440     rv = soc_profile_mem_delete(unit, _bcm_th_cos_map_profile[unit],
   7441                                 old_index);
   7442     if (BCM_FAILURE(rv)) {
   7443         soc_mem_unlock(unit, PORT_COS_MAPm);
   7444         return rv;
   7445     }
   7446 
   7447     rv = soc_profile_mem_add(unit, _bcm_th_cos_map_profile[unit], entries,
   7448                              _TH_MMU_NUM_INT_PRI, &new_index);
   7449 
   7450     soc_mem_unlock(unit, PORT_COS_MAPm);
   7451 
   7452     if (BCM_FAILURE(rv)) {
   7453         return rv;
   7454     }
   7455 
   7456     soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf,
   7457                         new_index / _TH_MMU_NUM_INT_PRI);
   7458     BCM_IF_ERROR_RETURN
   7459         (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   7460                             &cos_map_sel_entry));
   7461 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   7462     if (IS_CPU_PORT(unit, local_port)) {
   7463         BCM_IF_ERROR_RETURN
   7464             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   7465                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   7466                                     new_index / _TH_MMU_NUM_INT_PRI));
   7467     }
   7468 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   7469 
   7470     return BCM_E_NONE;
   7471 }
   7472 
   7473 /*
   7474  * Function:
   7475  *     bcm_th_cosq_mapping_set
   7476  * Purpose:
   7477  *     Set which cosq a given priority should fall into
   7478  * Parameters:
   7479  *     unit     - (IN) unit number
   7480  *     gport    - (IN) queue group GPORT identifier
   7481  *     priority - (IN) priority value to map
   7482  *     cosq     - (IN) COS queue to map to
   7483  * Returns:
   7484  *     BCM_E_XXX
   7485  */
   7486 
   7487 int
   7488 bcm_th_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority,
   7489                         bcm_cos_queue_t cosq)
   7490 {
   7491     bcm_pbmp_t pbmp;
   7492     bcm_port_t local_port;
   7493 
   7494     BCM_PBMP_CLEAR(pbmp);
   7495 
   7496     if ((priority < 0) || (priority >= _TH_MMU_NUM_INT_PRI)) {
   7497         return BCM_E_PARAM;
   7498     }
   7499 
   7500     if (cosq < 0) {
   7501         return BCM_E_PARAM;
   7502     }
   7503 
   7504     if (port == -1) {
   7505         /* port value of -1 will cause the cosq mapping set for
   7506            all types of local ports except Loopback ports.
   7507            So we do the sanity check of cos value with Default Number
   7508            of COS */
   7509         if (cosq >= _TH_NUM_COS(unit)) {
   7510             return BCM_E_PARAM;
   7511         }
   7512         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   7513     } else {
   7514         if (BCM_GPORT_IS_SET(port)) {
   7515             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   7516                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   7517                 BCM_GPORT_IS_SCHEDULER(port)) {
   7518                 return BCM_E_PARAM;
   7519             } else if (BCM_GPORT_IS_LOCAL(port)) {
   7520                 local_port = BCM_GPORT_LOCAL_GET(port);
   7521             } else if (BCM_GPORT_IS_MODPORT(port)) {
   7522                 BCM_IF_ERROR_RETURN(
   7523                     bcm_esw_port_local_get(unit, port, &local_port));
   7524             } else {
   7525                 return BCM_E_PARAM;
   7526             }
   7527         } else {
   7528             local_port = port;
   7529         }
   7530 
   7531         if (!SOC_PORT_VALID(unit, local_port)) {
   7532             return BCM_E_PORT;
   7533         }
   7534 
   7535         BCM_PBMP_PORT_ADD(pbmp, local_port);
   7536         if (cosq >= _TH_PORT_NUM_COS(unit, local_port)) {
   7537             return BCM_E_PARAM;
   7538         }
   7539     }
   7540 
   7541     PBMP_ITER(pbmp, local_port) {
   7542         if (IS_LB_PORT(unit, local_port)) {
   7543             continue;
   7544         }
   7545 
   7546         /* If no ETS/gport, map the int prio symmetrically for ucast and
   7547          * mcast */
   7548         BCM_IF_ERROR_RETURN
   7549             (_bcm_th_cosq_mapping_set(unit, local_port,
   7550                                       priority,
   7551                                       BCM_COSQ_GPORT_UCAST_QUEUE_GROUP |
   7552                                       BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   7553                                       -1, cosq));
   7554     }
   7555 
   7556     return BCM_E_NONE;
   7557 }
   7558 
   7559 int
   7560 bcm_th_cosq_gport_mapping_set(int unit, bcm_port_t ing_port,
   7561                               bcm_cos_t int_pri, uint32 flags,
   7562                               bcm_gport_t gport, bcm_cos_queue_t cosq)
   7563 {
   7564     bcm_port_t local_port;
   7565 
   7566     if ((int_pri < 0) || (int_pri >= _TH_MMU_NUM_INT_PRI)) {
   7567         return BCM_E_PARAM;
   7568     }
   7569 
   7570     BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, ing_port,
   7571                                                        &local_port));
   7572 
   7573     if ((cosq < 0) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) {
   7574         return BCM_E_PARAM;
   7575     }
   7576 
   7577     return _bcm_th_cosq_mapping_set(unit, ing_port, int_pri, flags, gport,
   7578                                     cosq);
   7579 }
   7580 
   7581 /* Routine to perform Inverse mapping for given Queue port back to Port/Priority
   7582  * which was defined by default or through cosq_mapping_set functions
   7583  */
   7584 int
   7585 _bcm_th_cosq_inv_mapping_get(int unit, bcm_gport_t gport,
   7586                              bcm_cos_queue_t cosq,
   7587                              uint32 flags, bcm_port_t *ing_port,
   7588                              bcm_cos_t *priority)
   7589 {
   7590     bcm_port_t local_port;
   7591     cos_map_sel_entry_t cos_map_sel_entry;
   7592     void *entries[1];
   7593     int num_queue = 1, index, ii;
   7594     bcm_cos_queue_t in_cosq = BCM_COS_INVALID, pri_cosq = BCM_COS_INVALID;
   7595     bcm_module_t    modid;
   7596     soc_field_t cos_field = INVALIDf;
   7597     port_cos_map_entry_t cos_map_entries[_TH_MMU_NUM_INT_PRI];
   7598 
   7599     if ((flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP) &&
   7600         (flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP)) {
   7601         return BCM_E_PARAM;
   7602     }
   7603 
   7604     if ((ing_port == NULL) || (priority == NULL)) {
   7605         return BCM_E_PARAM;
   7606     }
   7607 
   7608     if (BCM_GPORT_IS_SET(gport)) {
   7609         if (!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) &&
   7610             !(BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) {
   7611             return BCM_E_PARAM;
   7612         }
   7613         BCM_IF_ERROR_RETURN
   7614             (_bcm_th_cosq_node_get(unit, gport, &modid, &local_port,
   7615                                    &in_cosq, NULL));
   7616     } else {
   7617         BCM_IF_ERROR_RETURN
   7618             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   7619         in_cosq = cosq;
   7620     }
   7621 
   7622     if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) {
   7623         return BCM_E_PARAM;
   7624     }
   7625 
   7626     if ((IS_CPU_PORT(unit, local_port)) || (IS_LB_PORT(unit, local_port))) {
   7627         return BCM_E_PARAM;
   7628     }
   7629 
   7630     *ing_port = local_port;
   7631 
   7632     if (flags == BCM_COSQ_GPORT_MCAST_QUEUE_GROUP) {
   7633         cos_field = MC_COS1f;
   7634         num_queue = _BCM_TH_NUM_MCAST_QUEUE_PER_PORT;
   7635     } else {
   7636         cos_field = COSf;
   7637         num_queue = _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
   7638     }
   7639 
   7640     if (in_cosq == BCM_COS_INVALID) {
   7641         return BCM_E_PARAM;
   7642     } else {
   7643         in_cosq %= num_queue;
   7644     }
   7645 
   7646     entries[0] = &cos_map_entries;
   7647     BCM_IF_ERROR_RETURN
   7648         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   7649                            &cos_map_sel_entry));
   7650     index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   7651                                 SELECTf);
   7652     index *= _TH_MMU_NUM_INT_PRI;
   7653 
   7654     BCM_IF_ERROR_RETURN
   7655         (soc_profile_mem_get(unit, _bcm_th_cos_map_profile[unit],
   7656                              index, _TH_MMU_NUM_INT_PRI, entries));
   7657 
   7658     for (ii = 0; ii < _TH_MMU_NUM_INT_PRI; ii++) {
   7659         pri_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm,
   7660                                        &cos_map_entries[ii], cos_field);
   7661         if (pri_cosq == in_cosq) {
   7662             /* Required Cosq found. Break as the index is the priority */
   7663             *priority = ii;
   7664             break;
   7665         }
   7666     }
   7667 
   7668     if (ii == _TH_MMU_NUM_INT_PRI) {
   7669         /* Mapping cannot be found */
   7670         return BCM_E_NOT_FOUND;
   7671     }
   7672 
   7673     return BCM_E_NONE;
   7674 }
   7675 
   7676 /*
   7677  * Function:
   7678  *     bcm_th_cosq_mapping_get
   7679  * Purpose:
   7680  *     Determine which COS queue a given priority currently maps to.
   7681  * Parameters:
   7682  *     unit     - (IN) unit number
   7683  *     gport    - (IN) queue group GPORT identifier
   7684  *     priority - (IN) priority value to map
   7685  *     cosq     - (OUT) COS queue to map to
   7686  * Returns:
   7687  *     BCM_E_XXX
   7688  */
   7689 int
   7690 _bcm_th_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   7691                          uint32 flags, bcm_gport_t *gport,
   7692                          bcm_cos_queue_t *cosq)
   7693 {
   7694     bcm_port_t local_port;
   7695     cos_map_sel_entry_t cos_map_sel_entry;
   7696     _bcm_th_cosq_port_info_t *port_info = NULL;
   7697     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
   7698     _bcm_th_cosq_node_t *node;
   7699     int ii, index, cosq_base = 0;
   7700     void *entry_p;
   7701     bcm_cos_queue_t hw_cosq = BCM_COS_INVALID, node_cosq = BCM_COS_INVALID;
   7702     int numq = -1;
   7703     soc_info_t *si = &SOC_INFO(unit);
   7704 
   7705     if ((flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP) &&
   7706         (flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP)) {
   7707         return BCM_E_PARAM;
   7708     }
   7709 
   7710     BCM_IF_ERROR_RETURN
   7711         (_bcm_th_cosq_localport_resolve(unit, ing_port, &local_port));
   7712 
   7713     if (gport) {
   7714         *gport = BCM_GPORT_INVALID;
   7715     }
   7716 
   7717     *cosq = BCM_COS_INVALID;
   7718 
   7719     BCM_IF_ERROR_RETURN
   7720         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   7721                            &cos_map_sel_entry));
   7722     index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   7723                                 SELECTf);
   7724     index *= _TH_MMU_NUM_INT_PRI;
   7725 
   7726     entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_th_cos_map_profile[unit],
   7727                                     port_cos_map_entry_t *,
   7728                                     index + priority);
   7729     if (IS_CPU_PORT(unit, local_port)) {
   7730         cpu_port_info = &_bcm_th_cosq_cpu_port_info[unit][local_port];
   7731     } else {
   7732         port_info = &_bcm_th_cosq_port_info[unit][local_port];
   7733     }
   7734 
   7735     switch (flags) {
   7736         case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   7737             hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p,
   7738                                           UC_COS1f);
   7739             if ((IS_CPU_PORT(unit, local_port) == FALSE) && (gport)) {
   7740                 for (ii = 0; ii < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; ii++) {
   7741                     node = &port_info->ucast[ii];
   7742                     if (node == NULL) {
   7743                         return BCM_E_NOT_FOUND;
   7744                     }
   7745                     node_cosq = (node->hw_index %
   7746                                  _BCM_TH_NUM_UCAST_QUEUE_PER_PORT);
   7747                     if (node && (node_cosq == hw_cosq)) {
   7748                         *gport = node->gport;
   7749                         *cosq = hw_cosq;
   7750                         break;
   7751                     }
   7752                 }
   7753             } else {
   7754                 *cosq = hw_cosq;
   7755             }
   7756             break;
   7757         case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   7758             hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p,
   7759                                           MC_COS1f);
   7760             if (gport) {
   7761                 if (IS_CPU_PORT(unit, local_port)) {
   7762                     numq = _BCM_TH_NUM_CPU_MCAST_QUEUE;
   7763                     cosq_base = si->port_cosq_base[CMIC_PORT(unit)];
   7764                 } else {
   7765                     numq = _BCM_TH_NUM_MCAST_QUEUE_PER_PORT;
   7766                     cosq_base = 0;
   7767                 }
   7768                 for (ii = 0; ii < numq; ii++) {
   7769                     if (IS_CPU_PORT(unit, local_port)) {
   7770                         node = &cpu_port_info->mcast[ii];
   7771                     } else {
   7772                         node = &port_info->mcast[ii];
   7773                     }
   7774                     if (!node) {
   7775                         return BCM_E_NOT_FOUND;
   7776                     }
   7777                     node_cosq = ((node->hw_index - cosq_base) % numq);
   7778                     if (node_cosq == hw_cosq) {
   7779                         *gport = node->gport;
   7780                         *cosq = hw_cosq;
   7781                         break;
   7782                     }
   7783                 }
   7784             } else {
   7785                 *cosq = hw_cosq;
   7786             }
   7787             break;
   7788         /*
   7789          * COVERITY
   7790          *
   7791          * This default is unreachable. It is kept intentionally
   7792          * as a defensive default for future development.
   7793          */
   7794         /* coverity[dead_error_begin] */
   7795         default:
   7796             return BCM_E_PARAM;
   7797     }
   7798     if (((gport &&
   7799         (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID))) ||
   7800         (*cosq == BCM_COS_INVALID)) {
   7801         return BCM_E_NOT_FOUND;
   7802     }
   7803 
   7804     return BCM_E_NONE;
   7805 }
   7806 
   7807 /*
   7808  * Function:
   7809  *     bcm_th_cosq_mapping_get
   7810  * Purpose:
   7811  *     Determine which COS queue a given priority currently maps to.
   7812  * Parameters:
   7813  *     unit     - (IN) unit number
   7814  *     gport    - (IN) queue group GPORT identifier
   7815  *     priority - (IN) priority value to map
   7816  *     cosq     - (OUT) COS queue to map to
   7817  * Returns:
   7818  *     BCM_E_XXX
   7819  */
   7820 int
   7821 bcm_th_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority,
   7822                         bcm_cos_queue_t *cosq)
   7823 {
   7824     bcm_port_t local_port;
   7825     bcm_pbmp_t pbmp;
   7826 
   7827     if ((priority < 0) || (priority >= _TH_MMU_NUM_INT_PRI)) {
   7828         return BCM_E_PARAM;
   7829     }
   7830 
   7831     BCM_PBMP_CLEAR(pbmp);
   7832 
   7833     if (port == -1) {
   7834         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   7835     } else {
   7836         if (BCM_GPORT_IS_SET(port)) {
   7837             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   7838                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   7839                 BCM_GPORT_IS_SCHEDULER(port)) {
   7840                 return BCM_E_PARAM;
   7841             } else if (BCM_GPORT_IS_LOCAL(port)) {
   7842                 local_port = BCM_GPORT_LOCAL_GET(port);
   7843             } else if (BCM_GPORT_IS_MODPORT(port)) {
   7844                 BCM_IF_ERROR_RETURN
   7845                     (bcm_esw_port_local_get(unit, port, &local_port));
   7846             } else {
   7847                 return BCM_E_PARAM;
   7848             }
   7849         } else {
   7850             local_port = port;
   7851         }
   7852 
   7853         if (!SOC_PORT_VALID(unit, local_port)) {
   7854             return BCM_E_PORT;
   7855         }
   7856 
   7857         BCM_PBMP_PORT_ADD(pbmp, local_port);
   7858     }
   7859 
   7860     PBMP_ITER(pbmp, local_port) {
   7861         if (IS_LB_PORT(unit, local_port)) {
   7862             continue;
   7863         }
   7864 
   7865         BCM_IF_ERROR_RETURN(_bcm_th_cosq_mapping_get(unit, local_port,
   7866                  priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq));
   7867         break;
   7868     }
   7869     return BCM_E_NONE;
   7870 }
   7871 
   7872 int
   7873 bcm_th_cosq_gport_mapping_get(int unit, bcm_port_t ing_port,
   7874                               bcm_cos_t int_pri, uint32 flags,
   7875                               bcm_gport_t *gport, bcm_cos_queue_t *cosq)
   7876 {
   7877     if (gport == NULL || cosq == NULL) {
   7878         return BCM_E_PARAM;
   7879     }
   7880 
   7881     if ((int_pri < 0) || (int_pri >= _TH_MMU_NUM_INT_PRI)) {
   7882         return BCM_E_PARAM;
   7883     }
   7884 
   7885     return _bcm_th_cosq_mapping_get(unit, ing_port, int_pri, flags, gport,
   7886                                     cosq);
   7887 }
   7888 
   7889 
   7890 /*
   7891  * Function:
   7892  *      bcm_th_cosq_field_classifier_get
   7893  * Purpose:
   7894  *      Get classifier type information.
   7895  * Parameters:
   7896  *      unit          - (IN) Unit number.
   7897  *      classifier_id - (IN) Classifier ID
   7898  *      classifier    - (OUT) Classifier info
   7899  * Returns:
   7900  *      BCM_E_xxx
   7901  */
   7902 int
   7903 bcm_th_cosq_field_classifier_get(
   7904     int unit,
   7905     int classifier_id,
   7906     bcm_cosq_classifier_t *classifier)
   7907 {
   7908     if (classifier == NULL) {
   7909         return BCM_E_PARAM;
   7910     }
   7911     sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t));
   7912 
   7913     if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
   7914         classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD;
   7915     }
   7916 
   7917     return BCM_E_NONE;
   7918 }
   7919 
   7920 /*
   7921  * Function:
   7922  *      bcm_th_cosq_field_classifier_id_create
   7923  * Purpose:
   7924  *      Create a cosq classifier.
   7925  * Parameters:
   7926  *      unit          - (IN) Unit number.
   7927  *      classifier    - (IN) Classifier attributes
   7928  *      classifier_id - (OUT) Classifier ID
   7929  * Returns:
   7930  *      BCM_E_xxx
   7931  */
   7932 int
   7933 bcm_th_cosq_field_classifier_id_create(
   7934     int unit,
   7935     bcm_cosq_classifier_t *classifier,
   7936     int *classifier_id)
   7937 {
   7938     int rv;
   7939     int ref_count = 0;
   7940     int ent_per_set = _TH_MMU_NUM_INT_PRI;
   7941     int i;
   7942 
   7943     if (NULL == classifier || NULL == classifier_id) {
   7944         return BCM_E_PARAM;
   7945     }
   7946 
   7947     for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm); i += ent_per_set) {
   7948         rv = soc_profile_mem_ref_count_get(
   7949                 unit, _bcm_th_ifp_cos_map_profile[unit], i, &ref_count);
   7950         if (SOC_FAILURE(rv)) {
   7951             return rv;
   7952         }
   7953         if (0 == ref_count) {
   7954             break;
   7955         }
   7956     }
   7957 
   7958     if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) {
   7959         *classifier_id = 0;
   7960         return BCM_E_RESOURCE;
   7961     }
   7962 
   7963     _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set));
   7964 
   7965     return BCM_E_NONE;
   7966 }
   7967 
   7968 /*
   7969  * Function:
   7970  *      bcm_th_cosq_field_classifier_map_set
   7971  * Purpose:
   7972  *      Set internal priority to ingress field processor CoS queue
   7973  *      override mapping.
   7974  * Parameters:
   7975  *      unit           - (IN) Unit number.
   7976  *      classifier_id  - (IN) Classifier ID
   7977  *      count          - (IN) Number of elements in priority_array and
   7978  *                            cosq_array.
   7979  *      priority_array - (IN) Array of internal priorities
   7980  *      cosq_array     - (IN) Array of COS queues
   7981  * Returns:
   7982  *      BCM_E_xxx
   7983  * Notes:
   7984  *      Supported count value is [0-16] and 48
   7985  *      When count = [0-16]
   7986  *          Array Index [15-0] : Maps Prio[15-0] to UC, MC
   7987  *                               and RQE cos[15-0]
   7988  *      When count = 48
   7989  *      Prio Array Index Map
   7990  *          Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0]
   7991  *          Array Index [31-16] : Maps Prio[15-0] to MC cos[15-0]
   7992  *          Array Index [47-32] : Maps Prio[15-0] to RQE cos[15-0]
   7993  */
   7994 int
   7995 bcm_th_cosq_field_classifier_map_set(
   7996     int unit,
   7997     int classifier_id,
   7998     int count,
   7999     bcm_cos_t *priority_array,
   8000     bcm_cos_queue_t *cosq_array)
   8001 {
   8002     int rv;
   8003     int i;
   8004     int max_entries = _TH_MMU_NUM_INT_PRI;
   8005     uint32 index, new_index;
   8006     void *entries[1];
   8007     ifp_cos_map_entry_t ent_buf[_TH_MMU_NUM_INT_PRI];
   8008     soc_field_t field = -1;
   8009 
   8010     /* Input parameter check. */
   8011     if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
   8012         return BCM_E_PARAM;
   8013     }
   8014 
   8015     if (NULL == priority_array || NULL == cosq_array) {
   8016         return BCM_E_PARAM;
   8017     }
   8018 
   8019     if ((count > max_entries) && (count != (max_entries * 3))) {
   8020         return BCM_E_PARAM;
   8021     }
   8022 
   8023     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries);
   8024     entries[0] = ent_buf;
   8025 
   8026     if (count != (max_entries * 3)) {
   8027         for (i = 0; i < count; i++) {
   8028             if (priority_array[i] < max_entries) {
   8029                 /* When count != max_entries * 3
   8030                    We program the same mapping for all three
   8031                    fields UC/MC/RQE queues.
   8032                    Hence cos_array[i] cannot have value more than
   8033                    equal to 10 */
   8034                 if ((cosq_array[i] < 0) ||
   8035                     (cosq_array[i] >= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT)) {
   8036                     return BCM_E_PARAM;
   8037                 }
   8038                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
   8039                                     IFP_MC_COSf, cosq_array[i]);
   8040                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
   8041                                     IFP_UC_COSf, cosq_array[i]);
   8042                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
   8043                                     IFP_RQE_Q_NUMf, cosq_array[i]);
   8044             }
   8045         }
   8046     } else {
   8047         for (i = 0; i < count; i++) {
   8048             if (priority_array[i] < max_entries) {
   8049                 if (i < max_entries) {
   8050                     /* Number of UCAST queue per port = 10 */
   8051                     if ((cosq_array[i] < 0) ||
   8052                         (cosq_array[i] >= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT)) {
   8053                         return BCM_E_PARAM;
   8054                     }
   8055                     field = IFP_UC_COSf;
   8056                 } else if (i < (max_entries * 2)) {
   8057                     /* Number of MCAST queue per port = 10 */
   8058                     if ((cosq_array[i] < 0) ||
   8059                         (cosq_array[i] >= _BCM_TH_NUM_MCAST_QUEUE_PER_PORT)) {
   8060                         return BCM_E_PARAM;
   8061                     }
   8062                     field = IFP_MC_COSf;
   8063                 } else {
   8064                     /* Number of RQE queue per unit = 11 */
   8065                     if ((cosq_array[i] < 0) ||
   8066                         (cosq_array[i] >= _TH_MMU_NUM_RQE_QUEUES)) {
   8067                         return BCM_E_PARAM;
   8068                     }
   8069                     field = IFP_RQE_Q_NUMf;
   8070                 }
   8071                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
   8072                                     field, cosq_array[i]);
   8073             }
   8074         }
   8075     }
   8076 
   8077     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
   8078 
   8079     rv = soc_profile_mem_delete(unit, _bcm_th_ifp_cos_map_profile[unit],
   8080                                 index * max_entries);
   8081 
   8082     /* If rv = SOC_E_NONE means that there exists a
   8083      * mapping for given classifier_id which is now
   8084      * successfully deleted and we can overwrite.
   8085      * rv = SOC_E_NOT_FOUND means there was no mapping
   8086      * for given classifier_id and we can create a new mapping
   8087      * Otherwise there is something else wrong and we return
   8088      * the error value returned by soc_profile_mem_delete()
   8089      */
   8090     if ((rv != SOC_E_NONE) && (rv != SOC_E_NOT_FOUND)) {
   8091         return rv;
   8092     }
   8093 
   8094     SOC_IF_ERROR_RETURN
   8095         (soc_profile_mem_add(unit, _bcm_th_ifp_cos_map_profile[unit],
   8096                              entries, max_entries, &new_index));
   8097 
   8098     /* If we get (index == new_index / max_entries) means we have
   8099      * a successful mapping operation.
   8100      * But if they are not equal which means there already exists
   8101      * a similar mapping associated with other classifier_id hence
   8102      * we return BCM_E_EXISTS.
   8103      */
   8104 
   8105     if (index != (new_index / max_entries)) {
   8106         SOC_IF_ERROR_RETURN
   8107             (soc_profile_mem_delete(unit, _bcm_th_ifp_cos_map_profile[unit],
   8108                                     new_index));
   8109         return BCM_E_EXISTS;
   8110     }
   8111 
   8112     return BCM_E_NONE;
   8113 }
   8114 
   8115 /*
   8116  * Function:
   8117  *      bcm_th_cosq_field_classifier_map_get
   8118  * Purpose:
   8119  *      Get internal priority to ingress field processor CoS queue
   8120  *      override mapping information.
   8121  * Parameters:
   8122  *      unit           - (IN) Unit number.
   8123  *      classifier_id  - (IN) Classifier ID
   8124  *      array_max      - (IN) Size of priority_array and cosq_array
   8125  *      priority_array - (IN) Array of internal priorities
   8126  *      cosq_array     - (OUT) Array of COS queues
   8127  *      array_count    - (OUT) Size of cosq_array
   8128  * Returns:
   8129  *      BCM_E_xxx
   8130  * Notes:
   8131  *      Supported array_max = [0-16] and 48
   8132  *      When array_max = [0-16]
   8133  *          Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0]
   8134  *      When array_max = 48
   8135  *      Prio Array Index Map
   8136  *          Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0]
   8137  *          Array Index [31-16] : Maps Prio[15-0] to MC cos[15-0]
   8138  *          Array Index [47-32] : Maps Prio[15-0] to RQE cos[15-0]
   8139  */
   8140 int
   8141 bcm_th_cosq_field_classifier_map_get(
   8142     int unit,
   8143     int classifier_id,
   8144     int array_max,
   8145     bcm_cos_t *priority_array,
   8146     bcm_cos_queue_t *cosq_array,
   8147     int *array_count)
   8148 {
   8149     int rv;
   8150     int i;
   8151     int ent_per_set = _TH_MMU_NUM_INT_PRI;
   8152     uint32 index;
   8153     void *entries[1];
   8154     ifp_cos_map_entry_t ent_buf[_TH_MMU_NUM_INT_PRI];
   8155     soc_field_t field = -1;
   8156 
   8157     /* Input parameter check. */
   8158     if (NULL == priority_array || NULL == cosq_array || NULL == array_count) {
   8159         return BCM_E_PARAM;
   8160     }
   8161 
   8162     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set);
   8163     entries[0] = ent_buf;
   8164 
   8165     /* Get profile table entry set base index. */
   8166     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
   8167 
   8168     /* Read out entries from profile table into allocated buffer. */
   8169     rv = soc_profile_mem_get(unit, _bcm_th_ifp_cos_map_profile[unit],
   8170                              index * ent_per_set, ent_per_set, entries);
   8171     if (SOC_FAILURE(rv)) {
   8172         return rv;
   8173     }
   8174 
   8175     if (array_max <= ent_per_set) {
   8176         *array_count = array_max;
   8177     } else if ((array_max > ent_per_set) && (array_max < (ent_per_set * 3))) {
   8178         return BCM_E_PARAM;
   8179     } else {
   8180         *array_count = ent_per_set * 3;
   8181     }
   8182         /* Copy values into API OUT parameters. */
   8183     for (i = 0; i < *array_count; i++) {
   8184         if (priority_array[i % 16] >= _TH_MMU_NUM_INT_PRI) {
   8185             return BCM_E_PARAM;
   8186         }
   8187         if (i < ent_per_set) {
   8188             field = IFP_UC_COSf;
   8189         } else if (i < (ent_per_set * 2)) {
   8190             field = IFP_MC_COSf;
   8191         } else {
   8192             field = IFP_RQE_Q_NUMf;
   8193         }
   8194         cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm,
   8195                                             &ent_buf[priority_array[i]],
   8196                                             field);
   8197     }
   8198 
   8199     return BCM_E_NONE;
   8200 }
   8201 
   8202 /*
   8203  * Function:
   8204  *      bcm_th_cosq_field_classifier_map_clear
   8205  * Purpose:
   8206  *      Delete an internal priority to ingress field processor CoS queue
   8207  *      override mapping profile set.
   8208  * Parameters:
   8209  *      unit          - (IN) Unit number.
   8210  *      classifier_id - (IN) Classifier ID
   8211  * Returns:
   8212  *      BCM_E_xxx
   8213  */
   8214 int
   8215 bcm_th_cosq_field_classifier_map_clear(int unit, int classifier_id)
   8216 {
   8217     int ent_per_set = _TH_MMU_NUM_INT_PRI;
   8218     uint32 index;
   8219 
   8220     /* Get profile table entry set base index. */
   8221     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
   8222 
   8223     /* Delete the profile entries set. */
   8224     SOC_IF_ERROR_RETURN
   8225         (soc_profile_mem_delete(unit,
   8226                                 _bcm_th_ifp_cos_map_profile[unit],
   8227                                 index * ent_per_set));
   8228     return BCM_E_NONE;
   8229 }
   8230 
   8231 /*
   8232  * Function:
   8233  *      bcm_th_cosq_field_classifier_id_destroy
   8234  * Purpose:
   8235  *      Free resource associated with this field classifier id.
   8236  * Parameters:
   8237  *      unit          - (IN) Unit number.
   8238  *      classifier_id - (IN) Classifier ID
   8239  * Returns:
   8240  *      BCM_E_xxx
   8241  */
   8242 int
   8243 bcm_th_cosq_field_classifier_id_destroy(int unit, int classifier_id)
   8244 {
   8245     return BCM_E_NONE;
   8246 }
   8247 
   8248 STATIC int
   8249 _bcm_th_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   8250                             bcm_cosq_control_t type, int arg)
   8251 {
   8252     bcm_port_t local_port;
   8253     int pipe, startq;
   8254     uint32 max_val;
   8255     uint32 max_val2;
   8256     uint32 entry[SOC_MAX_MEM_WORDS];
   8257     uint32 entry2[SOC_MAX_MEM_WORDS];
   8258     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
   8259     soc_field_t fld_limit = INVALIDf;
   8260     int granularity = 1;
   8261     int from_cos, to_cos, ci;
   8262     int egr_db_shd_size[_TH_XPES_PER_DEV], egr_qe_shd_size[_TH_XPES_PER_DEV];
   8263     int cur_val;
   8264     int limit;
   8265     int disable_queuing = 0;
   8266     int uc_qlimit_enable = 0, mc_qlimit_enable = 0;
   8267 
   8268     if (arg < 0) {
   8269         return BCM_E_PARAM;
   8270     }
   8271 
   8272     arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL;
   8273 
   8274     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   8275         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
   8276         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8277             BCM_IF_ERROR_RETURN
   8278                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   8279                                              _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8280                                              &local_port, &startq, NULL));
   8281             SOC_IF_ERROR_RETURN
   8282                 (soc_port_pipe_get(unit, local_port, &pipe));
   8283         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8284             return BCM_E_PARAM;
   8285         }
   8286         else {
   8287             if (cosq == BCM_COS_INVALID) {
   8288                 from_cos = to_cos = 0;
   8289             } else {
   8290                 from_cos = to_cos = cosq;
   8291             }
   8292 
   8293             BCM_IF_ERROR_RETURN
   8294                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   8295             if (local_port < 0) {
   8296                 return BCM_E_PORT;
   8297             }
   8298             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8299             for (ci = from_cos; ci <= to_cos; ci++) {
   8300                 BCM_IF_ERROR_RETURN
   8301                     (_bcm_th_cosq_index_resolve
   8302                      (unit, local_port, ci, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8303                       NULL, &startq, NULL));
   8304             }
   8305         }
   8306         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe];
   8307         mem2 = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_Q_TO_QGRP_MAPm)[pipe];
   8308     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
   8309                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
   8310         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8311             return BCM_E_PARAM;
   8312         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8313             BCM_IF_ERROR_RETURN
   8314                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   8315                                              _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8316                                              &local_port, &startq, NULL));
   8317             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8318         }
   8319         else {
   8320             if (cosq == BCM_COS_INVALID) {
   8321                 from_cos = to_cos = 0;
   8322             } else {
   8323                 from_cos = to_cos = cosq;
   8324             }
   8325 
   8326             BCM_IF_ERROR_RETURN
   8327                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   8328             if (local_port < 0) {
   8329                 return BCM_E_PORT;
   8330             }
   8331             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8332             for (ci = from_cos; ci <= to_cos; ci++) {
   8333                 BCM_IF_ERROR_RETURN
   8334                     (_bcm_th_cosq_index_resolve
   8335                      (unit, local_port, ci, _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8336                       NULL, &startq, NULL));
   8337             }
   8338         }
   8339         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe];
   8340         mem2 = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_MCQE_QUEUE_CONFIGm)[pipe];
   8341     } else {
   8342         return BCM_E_PARAM;
   8343     }
   8344 
   8345     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   8346     if (mem2 != INVALIDm) {
   8347         BCM_IF_ERROR_RETURN
   8348             (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   8349     }
   8350 
   8351     switch (type) {
   8352         case bcmCosqControlEgressUCQueueSharedLimitBytes:
   8353             fld_limit = Q_SHARED_LIMIT_CELLf;
   8354 
   8355             uc_qlimit_enable = 1;
   8356 
   8357             /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN
   8358              * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT
   8359              * is non-zero.
   8360              */
   8361             limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf);
   8362             if (arg == 0 && limit == 0) {
   8363                 disable_queuing = 1;
   8364             } else if (arg != 0 || limit != 0) {
   8365                 disable_queuing = 0;
   8366             }
   8367             granularity = 1;
   8368             break;
   8369         case bcmCosqControlEgressMCQueueSharedLimitBytes:
   8370             fld_limit = Q_SHARED_LIMITf;
   8371             mc_qlimit_enable = 1;
   8372             granularity = 1;
   8373             break;
   8374         case bcmCosqControlEgressUCQueueMinLimitBytes:
   8375             fld_limit = Q_MIN_LIMIT_CELLf;
   8376 
   8377             /* Set MMU_THDU_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN
   8378              * and SHARED LIMIT are 0. Set it to 0 when either MIN or
   8379              * SHARED LIMIT is non-zero
   8380              */
   8381             limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf);
   8382             if (arg == 0 && limit == 0) {
   8383                 disable_queuing = 1;
   8384             } else if (arg != 0 || limit != 0) {
   8385                 disable_queuing = 0;
   8386             }
   8387 
   8388             granularity = 1;
   8389             break;
   8390         case bcmCosqControlEgressMCQueueMinLimitBytes:
   8391             fld_limit = Q_MIN_LIMITf;
   8392             granularity = 1;
   8393             break;
   8394         default:
   8395             return BCM_E_UNAVAIL;
   8396     }
   8397 
   8398     /* Check for min/max values */
   8399     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   8400     if ((arg < 0) || ((arg/granularity) > max_val)) {
   8401         return BCM_E_PARAM;
   8402     }
   8403 
   8404     /* guarantee limits need adjust shared limits */
   8405     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   8406          (type == bcmCosqControlEgressMCQueueMinLimitBytes)) {
   8407         int xpe, xpe_map;
   8408         int delta[_TH_XPES_PER_DEV] = {0}, update;
   8409         int *egr_shd_size;
   8410 
   8411         
   8412         cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit);
   8413         sal_memcpy(egr_db_shd_size, _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, 
   8414             sizeof(egr_db_shd_size));
   8415         sal_memcpy(egr_qe_shd_size, _BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit, 
   8416             sizeof(egr_qe_shd_size));
   8417         
   8418         egr_shd_size = egr_db_shd_size;
   8419         
   8420         /* adjustment delta */
   8421         xpe_map = SOC_INFO(unit).epipe_xpe_map[pipe];
   8422         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
   8423             if (xpe_map & (1 << xpe)) {
   8424                 delta[xpe] = ((arg / granularity) - cur_val) * granularity;
   8425             }
   8426         }
   8427         
   8428         /* shared limits to be decreased */
   8429         for (xpe = 0, update = 0; xpe < NUM_XPE(unit); xpe ++) {
   8430             if ((xpe_map & (1 << xpe)) && (delta[xpe] > 0)) {
   8431                 /* no space to decrease shared limit */
   8432                 if (delta[xpe] > egr_shd_size[xpe]) {
   8433                     return BCM_E_PARAM;
   8434                 }
   8435                 egr_shd_size[xpe] -= delta[xpe];
   8436                 update = 1;
   8437             }
   8438         }
   8439         if (update) {
   8440             BCM_IF_ERROR_RETURN
   8441                 (soc_th_mmu_config_res_limits_update(unit, 2 /* egr */,
   8442                     NULL, egr_db_shd_size, egr_qe_shd_size, 1));
   8443         }
   8444         
   8445         /* set new guarantee */
   8446         /* the hw value may be changed by soc_th_mmu_config_res_limits_update
   8447          * so read the register again in order to keep consistent  */
   8448         BCM_IF_ERROR_RETURN
   8449             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   8450         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   8451         /* coverity[negative_returns] */
   8452         BCM_IF_ERROR_RETURN
   8453             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   8454         
   8455         /* shared limits to be increased */
   8456         for (xpe = 0, update = 0; xpe < NUM_XPE(unit); xpe ++) {
   8457             if ((xpe_map & (1 << xpe)) && (delta[xpe] < 0)) {
   8458                 egr_shd_size[xpe] -= delta[xpe];
   8459                 update = 1;
   8460             }
   8461         }
   8462         if (update) {
   8463             BCM_IF_ERROR_RETURN
   8464                 (soc_th_mmu_config_res_limits_update(unit, 2 /* egr */,
   8465                     NULL, egr_db_shd_size, egr_qe_shd_size, 0));
   8466         }
   8467         
   8468         sal_memcpy(_BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, egr_db_shd_size,
   8469             sizeof(egr_db_shd_size));
   8470         sal_memcpy(_BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit, egr_qe_shd_size,
   8471             sizeof(egr_qe_shd_size));
   8472     } else {
   8473         if (type == bcmCosqControlEgressMCQueueSharedLimitBytes) {
   8474             uint32 value = arg/granularity;
   8475             max_val2 = (1 << soc_mem_field_length(unit, mem2, fld_limit)) - 1;
   8476             if (value > max_val2) {
   8477                 value = max_val2;
   8478             }
   8479             soc_mem_field32_set(unit, mem2, entry2, fld_limit, value);
   8480             BCM_IF_ERROR_RETURN
   8481                 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   8482         }
   8483         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   8484         BCM_IF_ERROR_RETURN
   8485             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   8486     }
   8487 
   8488     /* limit enable */
   8489     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   8490     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   8491 
   8492     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   8493         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
   8494         soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf, disable_queuing);
   8495     }
   8496 
   8497     if (mc_qlimit_enable) {
   8498         soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1);
   8499         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
   8500     }
   8501 
   8502     if (uc_qlimit_enable) {
   8503         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
   8504     }
   8505 
   8506     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   8507     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   8508 
   8509     return BCM_E_NONE;
   8510 }
   8511 
   8512 STATIC int
   8513 _bcm_th_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   8514                             bcm_cosq_control_t type, int *arg)
   8515 {
   8516     bcm_port_t local_port;
   8517     int pipe, startq;
   8518     uint32 entry[SOC_MAX_MEM_WORDS];
   8519     soc_mem_t mem = INVALIDm;
   8520     soc_field_t fld_limit = INVALIDf;
   8521     int granularity = 1;
   8522     int from_cos, to_cos, ci;
   8523 
   8524     if (!arg) {
   8525         return BCM_E_PARAM;
   8526     }
   8527 
   8528     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   8529         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
   8530         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8531             BCM_IF_ERROR_RETURN
   8532                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   8533                                              _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8534                                              &local_port, &startq, NULL));
   8535             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8536         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8537             return BCM_E_PARAM;
   8538         }
   8539         else {
   8540             if (cosq == BCM_COS_INVALID) {
   8541                 from_cos = to_cos = 0;
   8542             } else {
   8543                 from_cos = to_cos = cosq;
   8544             }
   8545 
   8546             BCM_IF_ERROR_RETURN
   8547                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   8548             if (local_port < 0) {
   8549                 return BCM_E_PORT;
   8550             }
   8551             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8552             for (ci = from_cos; ci <= to_cos; ci++) {
   8553                 BCM_IF_ERROR_RETURN
   8554                     (_bcm_th_cosq_index_resolve
   8555                      (unit, local_port, ci, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   8556                       NULL, &startq, NULL));
   8557             }
   8558         }
   8559         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe];
   8560     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
   8561                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
   8562         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8563             return BCM_E_PARAM;
   8564         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8565             BCM_IF_ERROR_RETURN
   8566                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   8567                                              _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8568                                              &local_port, &startq, NULL));
   8569             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8570         }
   8571         else {
   8572             if (cosq == BCM_COS_INVALID) {
   8573                 from_cos = to_cos = 0;
   8574             } else {
   8575                 from_cos = to_cos = cosq;
   8576             }
   8577 
   8578             BCM_IF_ERROR_RETURN
   8579                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   8580             if (local_port < 0) {
   8581                 return BCM_E_PORT;
   8582             }
   8583             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8584             for (ci = from_cos; ci <= to_cos; ci++) {
   8585                 BCM_IF_ERROR_RETURN
   8586                     (_bcm_th_cosq_index_resolve
   8587                      (unit, local_port, ci, _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   8588                       NULL, &startq, NULL));
   8589             }
   8590         }
   8591         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe];
   8592     } else {
   8593         return BCM_E_PARAM;
   8594     }
   8595 
   8596     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   8597                              startq, entry));
   8598 
   8599     switch (type) {
   8600         case bcmCosqControlEgressUCQueueSharedLimitBytes:
   8601             fld_limit = Q_SHARED_LIMIT_CELLf;
   8602             granularity = 1;
   8603             break;
   8604         case bcmCosqControlEgressMCQueueSharedLimitBytes:
   8605             fld_limit = Q_SHARED_LIMITf;
   8606             granularity = 1;
   8607             break;
   8608         case bcmCosqControlEgressUCQueueMinLimitBytes:
   8609             fld_limit = Q_MIN_LIMIT_CELLf;
   8610             granularity = 1;
   8611             break;
   8612         case bcmCosqControlEgressMCQueueMinLimitBytes:
   8613             fld_limit = Q_MIN_LIMITf;
   8614             granularity = 1;
   8615             break;
   8616         default:
   8617             return BCM_E_UNAVAIL;
   8618     }
   8619     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
   8620     *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL;
   8621     return BCM_E_NONE;
   8622 }
   8623 
   8624 /*
   8625  * This function is used to get ingress pipe, shared pool id
   8626  * priority group and headroom pool id for a given [Port, Prio]
   8627  */
   8628 STATIC int
   8629 _bcm_th_cosq_ing_pool_pg_pipe_get(int unit, bcm_gport_t gport,
   8630                                   bcm_cos_t prio, int *pipe,
   8631                                   int *sp, int *pg, int *hdrm_pool)
   8632 {
   8633     bcm_port_t local_port;
   8634 
   8635     if (pipe) {
   8636         BCM_IF_ERROR_RETURN
   8637             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   8638         if (local_port < 0) {
   8639             return BCM_E_PORT;
   8640         }
   8641         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, pipe));
   8642     }
   8643 
   8644     if (pg) {
   8645         BCM_IF_ERROR_RETURN
   8646             (_bcm_th_cosq_ingress_pg_get(unit, gport, prio, pg,
   8647                                          NULL ));
   8648 
   8649         if ((*pg < 0) || (*pg >= _TH_MMU_NUM_PG)) {
   8650             return BCM_E_PARAM;
   8651         }
   8652     }
   8653 
   8654     if (sp) {
   8655         BCM_IF_ERROR_RETURN(
   8656             _bcm_th_cosq_ingress_sp_get(unit, gport, prio, sp,
   8657                                         NULL));
   8658 
   8659         if ((*sp < 0) || (*sp >= _TH_MMU_NUM_POOL)) {
   8660             return BCM_E_PARAM;
   8661         }
   8662     }
   8663 
   8664     if (hdrm_pool) {
   8665         BCM_IF_ERROR_RETURN(
   8666             _bcm_th_cosq_ingress_hdrm_pool_get(unit, gport,
   8667                                                prio, hdrm_pool,
   8668                                                NULL));
   8669 
   8670         if ((*hdrm_pool < 0) || (*hdrm_pool >= _TH_MMU_NUM_POOL)) {
   8671             return BCM_E_PARAM;
   8672         }
   8673     }
   8674 
   8675     return BCM_E_NONE;
   8676 }
   8677 
   8678 
   8679 /*
   8680  * This function is used to get the
   8681  * Min and Max value of ingress PG or SP
   8682  */
   8683 STATIC int
   8684 _bcm_th_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   8685                           bcm_cosq_control_t type, int *arg)
   8686 {
   8687     bcm_port_t local_port;
   8688     int midx;
   8689     uint32 entry[SOC_MAX_MEM_WORDS];
   8690     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   8691     soc_field_t fld_limit = INVALIDf;
   8692     int pipe, port_pg;
   8693     int pool, granularity = 1;
   8694 
   8695     if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) {
   8696         /* Error. Input pri > Max Pri_Grp */
   8697         return BCM_E_PARAM;
   8698     }
   8699 
   8700     if (arg == NULL) {
   8701         return BCM_E_PARAM;
   8702     }
   8703 
   8704     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   8705         BCM_GPORT_IS_SCHEDULER(gport) ||
   8706         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8707         return BCM_E_PARAM;
   8708     }
   8709 
   8710     BCM_IF_ERROR_RETURN
   8711         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   8712     if (!SOC_PORT_VALID(unit, local_port)) {
   8713         return BCM_E_PORT;
   8714     }
   8715 
   8716     BCM_IF_ERROR_RETURN
   8717         (_bcm_th_cosq_ing_pool_pg_pipe_get(unit, gport, cosq,
   8718                                            &pipe, &pool, &port_pg,
   8719                                            NULL));
   8720 
   8721     if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) ||
   8722         (type == bcmCosqControlIngressPortPGMinLimitBytes) ||
   8723         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)||
   8724         (type == bcmCosqControlIngressPortPGResetFloorBytes) ||
   8725         (type == bcmCosqControlIngressPortPGResetOffsetBytes)) {
   8726         base_mem = THDI_PORT_PG_CONFIGm;
   8727         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   8728         /* get index for Port-PG */
   8729         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   8730     } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) ||
   8731                (type == bcmCosqControlIngressPortPoolMinLimitBytes) ||
   8732                (type == bcmCosqControlIngressPortPoolResumeLimitBytes)) {
   8733         base_mem = THDI_PORT_SP_CONFIGm;
   8734         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   8735         /* get index for Port-SP */
   8736         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   8737     } else {
   8738         return BCM_E_UNAVAIL;
   8739     }
   8740 
   8741     if (midx < 0) {
   8742         return BCM_E_PARAM;
   8743     }
   8744 
   8745     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   8746 
   8747     switch (type) {
   8748         case bcmCosqControlIngressPortPGSharedLimitBytes:
   8749             fld_limit = PG_SHARED_LIMITf;
   8750             granularity = 1;
   8751             break;
   8752         case bcmCosqControlIngressPortPoolMaxLimitBytes:
   8753             fld_limit = PORT_SP_MAX_LIMITf;
   8754             granularity = 1;
   8755             break;
   8756         case bcmCosqControlIngressPortPGMinLimitBytes:
   8757             fld_limit = PG_MIN_LIMITf;
   8758             granularity = 1;
   8759             break;
   8760         case bcmCosqControlIngressPortPoolMinLimitBytes:
   8761             fld_limit = PORT_SP_MIN_LIMITf;
   8762             granularity = 1;
   8763             break;
   8764         case bcmCosqControlIngressPortPGHeadroomLimitBytes:
   8765             fld_limit = PG_HDRM_LIMITf;
   8766             granularity = 1;
   8767             break;
   8768         case bcmCosqControlIngressPortPGResetFloorBytes:
   8769             fld_limit = PG_RESET_FLOORf;
   8770             granularity = 1;
   8771             break;
   8772         case bcmCosqControlIngressPortPGResetOffsetBytes:
   8773             fld_limit = PG_RESET_OFFSETf;
   8774             granularity = 1;
   8775             break;
   8776         case bcmCosqControlIngressPortPoolResumeLimitBytes:
   8777             fld_limit = PORT_SP_RESUME_LIMITf;
   8778             granularity = 1;
   8779             break;
   8780         /* coverity[dead_error_begin] */
   8781         default:
   8782             return BCM_E_UNAVAIL;
   8783     }
   8784 
   8785     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
   8786     *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL;
   8787 
   8788     return BCM_E_NONE;
   8789 }
   8790 
   8791 
   8792 STATIC int
   8793 _bcm_th_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
   8794                           bcm_cosq_control_t type, int arg)
   8795 {
   8796     bcm_port_t local_port;
   8797     int midx;
   8798     uint32 max_val, regval = 0;
   8799     uint32 entry[SOC_MAX_MEM_WORDS];
   8800     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   8801     soc_field_t fld_limit = INVALIDf;
   8802     int pipe, port_pg;
   8803     int pool, granularity = 1;
   8804     int  ing_shd_size[_TH_XPES_PER_DEV], cur_val;
   8805     int cur_hdrm;
   8806     soc_reg_t reg;
   8807 
   8808     if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) {
   8809         /* Error. Input pri > Max Pri_Grp */
   8810         return BCM_E_PARAM;
   8811     }
   8812 
   8813     if (arg < 0) {
   8814         return BCM_E_PARAM;
   8815     }
   8816 
   8817     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   8818         BCM_GPORT_IS_SCHEDULER(gport) ||
   8819         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8820         return BCM_E_PARAM;
   8821     }
   8822 
   8823     arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL;
   8824     BCM_IF_ERROR_RETURN
   8825         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   8826     if (!SOC_PORT_VALID(unit, local_port)) {
   8827         return BCM_E_PORT;
   8828     }
   8829 
   8830     BCM_IF_ERROR_RETURN
   8831         (_bcm_th_cosq_ing_pool_pg_pipe_get(unit, gport, cosq,
   8832                                            &pipe, &pool, &port_pg,
   8833                                            NULL));
   8834 
   8835     if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) ||
   8836         (type == bcmCosqControlIngressPortPGMinLimitBytes) ||
   8837         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)||
   8838         (type == bcmCosqControlIngressPortPGResetFloorBytes) ||
   8839         (type == bcmCosqControlIngressPortPGResetOffsetBytes)) {
   8840         base_mem = THDI_PORT_PG_CONFIGm;
   8841         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   8842         /* get index for Port-PG */
   8843         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   8844     } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) ||
   8845                (type == bcmCosqControlIngressPortPoolMinLimitBytes) ||
   8846                (type == bcmCosqControlIngressPortPoolResumeLimitBytes)) {
   8847         base_mem = THDI_PORT_SP_CONFIGm;
   8848         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   8849         /* get index for Port-SP */
   8850         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   8851     } else {
   8852         return BCM_E_UNAVAIL;
   8853     }
   8854 
   8855     if (midx < 0) {
   8856         return BCM_E_PARAM;
   8857     }
   8858 
   8859     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   8860 
   8861     switch (type) {
   8862         case bcmCosqControlIngressPortPGSharedLimitBytes:
   8863             fld_limit = PG_SHARED_LIMITf;
   8864             granularity = 1;
   8865             break;
   8866         case bcmCosqControlIngressPortPoolMaxLimitBytes:
   8867             fld_limit = PORT_SP_MAX_LIMITf;
   8868             granularity = 1;
   8869             break;
   8870         case bcmCosqControlIngressPortPGMinLimitBytes:
   8871             fld_limit = PG_MIN_LIMITf;
   8872             granularity = 1;
   8873             break;
   8874         case bcmCosqControlIngressPortPoolMinLimitBytes:
   8875             fld_limit = PORT_SP_MIN_LIMITf;
   8876             granularity = 1;
   8877             break;
   8878         case bcmCosqControlIngressPortPGHeadroomLimitBytes:
   8879             fld_limit = PG_HDRM_LIMITf;
   8880             granularity = 1;
   8881             break;
   8882         case bcmCosqControlIngressPortPGResetFloorBytes:
   8883             fld_limit = PG_RESET_FLOORf;
   8884             granularity = 1;
   8885             break;
   8886         case bcmCosqControlIngressPortPGResetOffsetBytes:
   8887             fld_limit = PG_RESET_OFFSETf;
   8888             granularity = 1;
   8889             break;
   8890         case bcmCosqControlIngressPortPoolResumeLimitBytes:
   8891             fld_limit = PORT_SP_RESUME_LIMITf;
   8892             granularity = 1;
   8893             break;
   8894         /* coverity[dead_error_begin] */
   8895         default:
   8896             return BCM_E_UNAVAIL;
   8897     }
   8898 
   8899     /* Check for min/max values */
   8900     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   8901     if ((arg < 0) || ((arg/granularity) > max_val)) {
   8902         return BCM_E_PARAM;
   8903     }
   8904 
   8905     /* guarantee limits need adjust shared limits */
   8906     if ((type == bcmCosqControlIngressPortPGMinLimitBytes) ||
   8907         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)) {
   8908         int xpe, xpe_map;
   8909         int delta[_TH_XPES_PER_DEV] = {0}, update;
   8910         
   8911         cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit);
   8912         sal_memcpy(ing_shd_size, _BCM_TH_MMU_INFO(unit)->ing_shared_limit, 
   8913             sizeof(ing_shd_size));
   8914         
   8915         /* adjustment delta */
   8916         xpe_map = SOC_INFO(unit).ipipe_xpe_map[pipe];
   8917         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
   8918             if (xpe_map & (1 << xpe)) {
   8919                 delta[xpe] = ((arg / granularity) - cur_val) * granularity;
   8920             }
   8921         }
   8922         
   8923         /* shared limits to be decreased */
   8924         for (xpe = 0, update = 0; xpe < NUM_XPE(unit); xpe ++) {
   8925             if ((xpe_map & (1 << xpe)) && (delta[xpe] > 0)) {
   8926                 /* no space to decrease shared limit */
   8927                 if (delta[xpe] > ing_shd_size[xpe]) {
   8928                     return BCM_E_PARAM;
   8929                 }
   8930                 ing_shd_size[xpe] -= delta[xpe];
   8931                 update = 1;
   8932             }
   8933         }
   8934         if (update) {
   8935             BCM_IF_ERROR_RETURN
   8936                 (soc_th_mmu_config_res_limits_update(unit, 1 /* ing */,
   8937                     ing_shd_size, NULL, NULL, 1));
   8938         }
   8939 
   8940         /* set new guarantee */
   8941         /* the hw value may be changed by soc_th_mmu_config_res_limits_update
   8942          * so read the register again in order to keep consistent  */
   8943         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   8944         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   8945         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   8946 
   8947         /* shared limits to be increased */
   8948         for (xpe = 0, update = 0; xpe < NUM_XPE(unit); xpe ++) {
   8949             if ((xpe_map & (1 << xpe)) && (delta[xpe] < 0)) {
   8950                 ing_shd_size[xpe] -= delta[xpe];
   8951                 update = 1;
   8952             }
   8953         }
   8954         if (update) {
   8955             BCM_IF_ERROR_RETURN
   8956                 (soc_th_mmu_config_res_limits_update(unit, 1 /* ing */,
   8957                     ing_shd_size, NULL, NULL, 0));
   8958         }
   8959 
   8960         sal_memcpy(_BCM_TH_MMU_INFO(unit)->ing_shared_limit, ing_shd_size, 
   8961             sizeof(ing_shd_size));
   8962 
   8963         if (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) {
   8964             reg  = THDI_HDRM_BUFFER_CELL_LIMIT_HPr;
   8965             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   8966                 if (xpe_map & ( 1 << xpe)) {
   8967                     BCM_IF_ERROR_RETURN(
   8968                         soc_tomahawk_xpe_reg32_get(unit, reg, xpe, -1, pool, &regval));
   8969                     cur_hdrm = soc_reg_field_get(unit, reg, regval, LIMITf);
   8970                     cur_hdrm += delta[xpe];
   8971                     if (cur_hdrm < 0 ){
   8972                         return BCM_E_PARAM;
   8973                     }
   8974                     regval = 0;
   8975                     soc_reg_field_set(unit, reg, &regval, LIMITf, cur_hdrm);
   8976                     BCM_IF_ERROR_RETURN(
   8977                         soc_tomahawk_xpe_reg32_set(unit, reg, xpe, -1, pool, regval));
   8978                 }
   8979             }
   8980         }
   8981     } else {
   8982         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   8983         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   8984     }
   8985 
   8986     return BCM_E_NONE;
   8987 }
   8988 
   8989 /*
   8990  * This function is used to get the
   8991  * enable status of ingress PG or SP
   8992  */
   8993 STATIC int
   8994 _bcm_th_cosq_ing_res_enable_get(int unit, bcm_gport_t gport,
   8995                           bcm_cos_queue_t cosq, bcm_cosq_control_t type,
   8996                           int *arg)
   8997 {
   8998     bcm_port_t local_port;
   8999     int midx;
   9000     uint32 entry[SOC_MAX_MEM_WORDS];
   9001     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   9002     soc_field_t fld_en = INVALIDf;
   9003     int pipe, port_pg;
   9004 
   9005     if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) {
   9006         /* Error. Input pri > Max Pri_Grp */
   9007         return BCM_E_PARAM;
   9008     }
   9009 
   9010     if (arg == NULL) {
   9011         return BCM_E_PARAM;
   9012     }
   9013 
   9014     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   9015         BCM_GPORT_IS_SCHEDULER(gport) ||
   9016         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9017         return BCM_E_PARAM;
   9018     }
   9019 
   9020     BCM_IF_ERROR_RETURN
   9021         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   9022     if (!SOC_PORT_VALID(unit, local_port)) {
   9023         return BCM_E_PORT;
   9024     }
   9025 
   9026     BCM_IF_ERROR_RETURN
   9027         (_bcm_th_cosq_ing_pool_pg_pipe_get(unit, gport, cosq,
   9028                                            &pipe, NULL, &port_pg,
   9029                                            NULL));
   9030 
   9031     if (type == bcmCosqControlIngressPortPGGlobalHeadroomEnable) {
   9032         base_mem = THDI_PORT_PG_CONFIGm;
   9033         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9034         /* get index for Port-PG */
   9035         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   9036     } else {
   9037         return BCM_E_UNAVAIL;
   9038     }
   9039 
   9040     if (midx < 0) {
   9041         return BCM_E_PARAM;
   9042     }
   9043 
   9044     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   9045 
   9046     switch (type) {
   9047         case bcmCosqControlIngressPortPGGlobalHeadroomEnable:
   9048             fld_en = PG_GBL_HDRM_ENf;
   9049             break;
   9050         /* coverity[dead_error_begin] */
   9051         default:
   9052             return BCM_E_UNAVAIL;
   9053     }
   9054 
   9055     *arg = soc_mem_field32_get(unit, mem, entry, fld_en);
   9056 
   9057     return BCM_E_NONE;
   9058 }
   9059 
   9060 STATIC int
   9061 _bcm_th_cosq_ing_res_enable_set(int unit, bcm_gport_t gport,
   9062                           bcm_cos_queue_t cosq, bcm_cosq_control_t type,
   9063                           int arg)
   9064 {
   9065     bcm_port_t local_port;
   9066     int midx;
   9067     uint32 max_val;
   9068     uint32 entry[SOC_MAX_MEM_WORDS];
   9069     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   9070     soc_field_t fld_en = INVALIDf;
   9071     int pipe, port_pg;
   9072 
   9073     if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) {
   9074         /* Error. Input pri > Max Pri_Grp */
   9075         return BCM_E_PARAM;
   9076     }
   9077 
   9078     if (arg < 0) {
   9079         return BCM_E_PARAM;
   9080     }
   9081 
   9082     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   9083         BCM_GPORT_IS_SCHEDULER(gport) ||
   9084         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9085         return BCM_E_PARAM;
   9086     }
   9087 
   9088     BCM_IF_ERROR_RETURN
   9089         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   9090     if (!SOC_PORT_VALID(unit, local_port)) {
   9091         return BCM_E_PORT;
   9092     }
   9093 
   9094     BCM_IF_ERROR_RETURN
   9095         (_bcm_th_cosq_ing_pool_pg_pipe_get(unit, gport, cosq,
   9096                                            &pipe, NULL, &port_pg,
   9097                                            NULL));
   9098 
   9099     if (type == bcmCosqControlIngressPortPGGlobalHeadroomEnable) {
   9100         base_mem = THDI_PORT_PG_CONFIGm;
   9101         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9102         /* get index for Port-PG */
   9103         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   9104     } else {
   9105         return BCM_E_UNAVAIL;
   9106     }
   9107 
   9108     if (midx < 0) {
   9109         return BCM_E_PARAM;
   9110     }
   9111 
   9112     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   9113 
   9114     switch (type) {
   9115         case bcmCosqControlIngressPortPGGlobalHeadroomEnable:
   9116             fld_en = PG_GBL_HDRM_ENf;
   9117             break;
   9118         /* coverity[dead_error_begin] */
   9119         default:
   9120             return BCM_E_UNAVAIL;
   9121     }
   9122 
   9123     /* Check for min/max values */
   9124     max_val = (1 << soc_mem_field_length(unit, mem, fld_en)) - 1;
   9125     if ((arg < 0) || (arg > max_val)) {
   9126         return BCM_E_PARAM;
   9127     }
   9128 
   9129     if (type == bcmCosqControlIngressPortPGGlobalHeadroomEnable) {
   9130         soc_mem_field32_set(unit, mem, entry, fld_en, arg ? 1 : 0);
   9131         /* coverity[negative_returns] */
   9132         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   9133     }
   9134 
   9135     return BCM_E_NONE;
   9136 }
   9137 
   9138 /*
   9139  * This function is used to set headroom pool
   9140  * or shared pool for given Ingress [Port, Priority]
   9141  */
   9142 STATIC int
   9143 _bcm_th_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_t pri,
   9144                           bcm_cosq_control_t type, int arg)
   9145 {
   9146     int local_port;
   9147     uint32 rval;
   9148     int pri_grp;
   9149     static const soc_field_t prigroup_spid_field[] = {
   9150         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   9151         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   9152     };
   9153     static const soc_field_t prigroup_hpid_field[] = {
   9154         PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf,
   9155         PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf
   9156     };
   9157 
   9158     if((arg < 0) || (arg >= _TH_MMU_NUM_POOL)) {
   9159             return BCM_E_PARAM;
   9160     }
   9161 
   9162     if ((pri < 0) || (pri >= _TH_MMU_NUM_INT_PRI)) {
   9163         /* Error. Input pri > Max Pri_Grp */
   9164         return BCM_E_PARAM;
   9165     }
   9166 
   9167     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   9168         BCM_GPORT_IS_SCHEDULER(gport) ||
   9169         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9170         return BCM_E_PARAM;
   9171     }
   9172 
   9173     BCM_IF_ERROR_RETURN
   9174             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   9175 
   9176     if (!SOC_PORT_VALID(unit, local_port)) {
   9177         return BCM_E_PORT;
   9178     }
   9179 
   9180     BCM_IF_ERROR_RETURN
   9181         (_bcm_th_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp));
   9182 
   9183     /* coverity fix : pri_grp can take value from 0 to 7 */
   9184     if ((pri_grp < 0) || (pri_grp >= _TH_MMU_NUM_PG)) {
   9185         return BCM_E_PARAM;
   9186     }
   9187 
   9188     if (type == bcmCosqControlIngressPool) {
   9189         SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval));
   9190         soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval,
   9191                           prigroup_spid_field[pri_grp],arg);
   9192         BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, local_port, rval));
   9193     } else if (type == bcmCosqControlIngressHeadroomPool) {
   9194         SOC_IF_ERROR_RETURN(READ_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, &rval));
   9195         soc_reg_field_set(unit, THDI_HDRM_PORT_PG_HPIDr, &rval,
   9196                           prigroup_hpid_field[pri_grp], arg);
   9197         BCM_IF_ERROR_RETURN(WRITE_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, rval));
   9198     } else {
   9199         return BCM_E_PARAM;
   9200     }
   9201     return BCM_E_NONE;
   9202 }
   9203 
   9204 STATIC int
   9205 _bcm_th_cosq_ing_pool_get(int unit, bcm_gport_t gport,
   9206                           bcm_cos_t pri,
   9207                           bcm_cosq_control_t type, int *arg)
   9208 {
   9209     int pool_start_idx = 0, pool_end_idx = 0;
   9210 
   9211     if (arg == NULL) {
   9212         return BCM_E_PARAM;
   9213     }
   9214 
   9215     if ((pri < 0) || (pri >= _TH_MMU_NUM_INT_PRI)) {
   9216         /* Error. Input pri > Max Pri_Grp */
   9217         return BCM_E_PARAM;
   9218     }
   9219 
   9220     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   9221         BCM_GPORT_IS_SCHEDULER(gport) ||
   9222         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9223         return BCM_E_PARAM;
   9224     }
   9225 
   9226     if (type == bcmCosqControlIngressPool) {
   9227         BCM_IF_ERROR_RETURN(
   9228             _bcm_th_cosq_ingress_sp_get(unit, gport, pri,
   9229                                         &pool_start_idx,
   9230                                         &pool_end_idx));
   9231     } else if (type == bcmCosqControlIngressHeadroomPool) {
   9232         BCM_IF_ERROR_RETURN(
   9233             _bcm_th_cosq_ingress_hdrm_pool_get(unit, gport, pri,
   9234                                                &pool_start_idx,
   9235                                                &pool_end_idx));
   9236     } else {
   9237         return BCM_E_PARAM;
   9238     }
   9239     *arg = pool_start_idx;
   9240     return BCM_E_NONE;
   9241 }
   9242 
   9243 STATIC int
   9244 _bcm_th_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   9245                           bcm_cosq_buffer_id_t buffer, 
   9246                           bcm_cosq_control_t type, int arg)
   9247 {
   9248     bcm_port_t local_port;
   9249     int startq, pool, midx;
   9250     uint32 max_val;
   9251     uint32 entry[SOC_MAX_MEM_WORDS];
   9252     uint32 entry2[SOC_MAX_MEM_WORDS];
   9253     soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm;
   9254     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
   9255     soc_field_t fld_limit = INVALIDf;
   9256     int granularity = 1, pipe;
   9257 
   9258     if (arg < 0) {
   9259         return BCM_E_PARAM;
   9260     }
   9261 
   9262     BCM_IF_ERROR_RETURN
   9263         (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9264                                     _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL,
   9265                                     &local_port, &pool, NULL));
   9266 
   9267     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   9268 
   9269 	base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   9270     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9271 
   9272     if (type == bcmCosqControlEgressPoolLimitEnable) {
   9273         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   9274         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   9275                             midx, entry));
   9276 
   9277         soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, !!arg);
   9278 
   9279         return soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry);
   9280     }
   9281     if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool ||
   9282         type == bcmCosqControlMCEgressPool) {
   9283         if((arg < 0) || (arg >= _TH_MMU_NUM_POOL)) {
   9284             return BCM_E_PARAM;
   9285         }
   9286         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9287             if (type != bcmCosqControlEgressPool) {
   9288                 return BCM_E_PARAM;
   9289             }
   9290             /* regular unicast queue */
   9291             BCM_IF_ERROR_RETURN
   9292                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9293                                      _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9294                                      &local_port, &startq, NULL));
   9295             base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   9296             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9297         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9298             if (type != bcmCosqControlEgressPool) {
   9299                 return BCM_E_PARAM;
   9300             }
   9301             BCM_IF_ERROR_RETURN
   9302                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9303                                      _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9304                                      &local_port, &startq, NULL));
   9305             base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   9306             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9307             base_mem2 = MMU_THDM_DB_QUEUE_CONFIGm;
   9308             mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
   9309         } else  { /* local port */
   9310             if (type == bcmCosqControlUCEgressPool) {
   9311                 BCM_IF_ERROR_RETURN
   9312                     (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9313                                          _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9314                                          &local_port, &startq, NULL));
   9315                 base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   9316                 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9317             } else {
   9318                 BCM_IF_ERROR_RETURN
   9319                     (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9320                                              _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9321                                              &local_port, &startq, NULL));
   9322                 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   9323                 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9324                 base_mem2 = MMU_THDM_DB_QUEUE_CONFIGm;
   9325                 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
   9326             }
   9327         }
   9328 
   9329         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   9330         soc_mem_field32_set(unit, mem, entry, Q_SPIDf, arg);
   9331 
   9332         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   9333         if (mem2 != INVALIDm) {
   9334             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   9335             soc_mem_field32_set(unit, mem2, entry2, Q_SPIDf, arg);
   9336             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   9337         }
   9338         return BCM_E_NONE;
   9339     }
   9340 
   9341     arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL;
   9342 
   9343     /* per service pool settings */
   9344     if (type == bcmCosqControlEgressPoolSharedLimitBytes ||
   9345         type == bcmCosqControlEgressPoolResumeLimitBytes ||
   9346         type == bcmCosqControlEgressPoolYellowSharedLimitBytes ||
   9347         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
   9348         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
   9349         type == bcmCosqControlEgressPoolRedResumeLimitBytes ||
   9350         type == bcmCosqControlEgressPoolHighCongestionLimitBytes ||
   9351         type == bcmCosqControlEgressPoolLowCongestionLimitBytes) {
   9352         int xpe, xpe_map;
   9353         uint32 rval;
   9354         soc_reg_t reg;
   9355         soc_reg_t wred_cng_lmt[4] = {
   9356             WRED_POOL_INST_CONG_LIMIT_0r,
   9357             WRED_POOL_INST_CONG_LIMIT_1r,
   9358             WRED_POOL_INST_CONG_LIMIT_2r,
   9359             WRED_POOL_INST_CONG_LIMIT_3r,
   9360         };
   9361 
   9362         switch (type) {
   9363         case bcmCosqControlEgressPoolSharedLimitBytes:
   9364             reg = MMU_THDM_DB_POOL_SHARED_LIMITr;
   9365             fld_limit = SHARED_LIMITf;
   9366             granularity = 1;
   9367             break;
   9368         case bcmCosqControlEgressPoolResumeLimitBytes:
   9369             reg = MMU_THDM_DB_POOL_RESUME_LIMITr;
   9370             fld_limit = RESUME_LIMITf;
   9371             granularity = 8;
   9372             break;
   9373         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
   9374             reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;
   9375             fld_limit = YELLOW_SHARED_LIMITf;
   9376             granularity = 8;
   9377             break;
   9378         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
   9379             reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr;
   9380             fld_limit = YELLOW_RESUME_LIMITf;
   9381             granularity = 8;
   9382             break;
   9383         case bcmCosqControlEgressPoolRedSharedLimitBytes:
   9384             reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;
   9385             fld_limit = RED_SHARED_LIMITf;
   9386             granularity = 8;
   9387             break;
   9388         case bcmCosqControlEgressPoolRedResumeLimitBytes:
   9389             reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr;
   9390             fld_limit = RED_RESUME_LIMITf;
   9391             granularity = 8;
   9392             break;
   9393         case bcmCosqControlEgressPoolHighCongestionLimitBytes:
   9394             reg = wred_cng_lmt[pool];
   9395             fld_limit = POOL_HI_CONG_LIMITf;
   9396             pool = -1;
   9397             granularity = 1;
   9398             break;
   9399         case bcmCosqControlEgressPoolLowCongestionLimitBytes:
   9400             reg = wred_cng_lmt[pool];
   9401             fld_limit = POOL_LOW_CONG_LIMITf;
   9402             pool = -1;
   9403             granularity = 1;
   9404             break;
   9405         /* coverity[dead_error_begin] */
   9406         default:
   9407             return BCM_E_UNAVAIL;
   9408         }
   9409 
   9410         /* These regs are chip unique, buffer = -1 writes on all 4 xpes. 
   9411            No need to do pipe-xpe checking */
   9412         xpe_map = SOC_INFO(unit).ipipe_xpe_map[0] | 
   9413                   SOC_INFO(unit).ipipe_xpe_map[1];
   9414         if (buffer == BCM_COSQ_BUFFER_ID_INVALID) {
   9415             xpe = -1;
   9416         } else if (xpe_map & (1 << buffer)) {
   9417             xpe = buffer;
   9418         } else {
   9419             return BCM_E_PARAM;
   9420         }
   9421         
   9422         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get
   9423             (unit, reg, xpe, -1, pool, &rval));
   9424 
   9425         /* Check for min/max values */
   9426         max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1;
   9427         if ((arg < 0) || ((arg/granularity) > max_val)) {
   9428             return BCM_E_PARAM;
   9429         } else {
   9430             soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity));
   9431         }
   9432 
   9433         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set
   9434             (unit, reg, xpe, -1, pool, rval));
   9435 
   9436         return BCM_E_NONE;
   9437     }
   9438 
   9439     /* per port settings */
   9440     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9441         BCM_IF_ERROR_RETURN
   9442             (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9443                                          _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9444                                          &local_port, &startq, NULL));
   9445         base_mem = MMU_THDU_CONFIG_QUEUEm;
   9446         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9447         base_mem2 = MMU_THDU_Q_TO_QGRP_MAPm;
   9448         mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
   9449     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9450         BCM_IF_ERROR_RETURN
   9451             (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9452                                          _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9453                                          &local_port, &startq, NULL));
   9454         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
   9455         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9456     } else {
   9457         if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) {
   9458             /* Need to have the UC_MC_Combine config enabled */
   9459             return BCM_E_PARAM;
   9460         }
   9461         base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   9462         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9463         startq = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   9464     }
   9465 
   9466     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   9467 
   9468     if (mem2 != INVALIDm) {
   9469         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   9470     }
   9471 
   9472     switch (type) {
   9473         case bcmCosqControlEgressPoolLimitBytes:
   9474             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9475                 fld_limit = Q_SHARED_LIMIT_CELLf;
   9476 
   9477                 if (mem2 != INVALIDm) {
   9478                     soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
   9479                 }
   9480             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9481                 fld_limit = Q_SHARED_LIMITf;
   9482                 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1);
   9483             } else {
   9484                 fld_limit = SHARED_LIMITf;
   9485                 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, 1);
   9486             }
   9487             granularity = 1;
   9488             break;
   9489         case bcmCosqControlEgressPoolYellowLimitBytes:
   9490             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9491                 fld_limit = LIMIT_YELLOW_CELLf;
   9492             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9493                 fld_limit = YELLOW_SHARED_LIMITf;
   9494             } else {
   9495                 fld_limit = YELLOW_SHARED_LIMITf;
   9496             }
   9497             granularity = 8;
   9498             break;
   9499         case bcmCosqControlEgressPoolRedLimitBytes:
   9500             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9501                 fld_limit = LIMIT_RED_CELLf;
   9502             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9503                 fld_limit = RED_SHARED_LIMITf;
   9504             } else {
   9505                 fld_limit = RED_SHARED_LIMITf;
   9506             }
   9507             granularity = 8;
   9508             break;
   9509         default:
   9510             return BCM_E_UNAVAIL;
   9511     }
   9512 
   9513     /* Check for min/max values */
   9514     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   9515     if ((arg < 0) || ((arg/granularity) > max_val)) {
   9516         return BCM_E_PARAM;
   9517     } else {
   9518         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   9519     }
   9520     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   9521 
   9522     if (mem2 != INVALIDm) {
   9523         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   9524     }
   9525     return BCM_E_NONE;
   9526 }
   9527 
   9528 STATIC int
   9529 _bcm_th_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   9530                           bcm_cosq_buffer_id_t buffer, 
   9531                           bcm_cosq_control_t type, int *arg)
   9532 {
   9533     bcm_port_t local_port;
   9534     int startq, pool, midx, pipe;
   9535     uint32 entry[SOC_MAX_MEM_WORDS];
   9536     soc_mem_t mem, base_mem;
   9537     int granularity = 1;
   9538 
   9539     if (!arg) {
   9540         return BCM_E_PARAM;
   9541     }
   9542 
   9543     BCM_IF_ERROR_RETURN
   9544         (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9545                                     _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL,
   9546                                     &local_port, &pool, NULL));
   9547 
   9548     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   9549 
   9550     if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool ||
   9551         type == bcmCosqControlMCEgressPool) {
   9552         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9553             if (type != bcmCosqControlEgressPool) {
   9554                 return BCM_E_PARAM;
   9555             }
   9556             /* regular unicast queue */
   9557             BCM_IF_ERROR_RETURN
   9558                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9559                                      _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9560                                      &local_port, &startq, NULL));
   9561             base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   9562             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9563         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9564             if (type != bcmCosqControlEgressPool) {
   9565                 return BCM_E_PARAM;
   9566             }
   9567             BCM_IF_ERROR_RETURN
   9568                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9569                                      _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9570                                      &local_port, &startq, NULL));
   9571             base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   9572             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9573         } else  { /* local port */
   9574             if (type == bcmCosqControlUCEgressPool) {
   9575                 BCM_IF_ERROR_RETURN
   9576                     (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9577                                          _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9578                                          &local_port, &startq, NULL));
   9579                 base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   9580                 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9581             } else {
   9582                 BCM_IF_ERROR_RETURN
   9583                     (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9584                                              _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9585                                              &local_port, &startq, NULL));
   9586                 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   9587                 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9588             }
   9589         }
   9590 
   9591         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   9592         *arg = soc_mem_field32_get(unit, mem, entry, Q_SPIDf);
   9593         return BCM_E_NONE;
   9594     }
   9595 
   9596     /* per service pool settings */
   9597     if (type == bcmCosqControlEgressPoolSharedLimitBytes ||
   9598         type == bcmCosqControlEgressPoolResumeLimitBytes ||
   9599         type == bcmCosqControlEgressPoolYellowSharedLimitBytes ||
   9600         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
   9601         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
   9602         type == bcmCosqControlEgressPoolRedResumeLimitBytes ||
   9603         type == bcmCosqControlEgressPoolHighCongestionLimitBytes ||
   9604         type == bcmCosqControlEgressPoolLowCongestionLimitBytes) {
   9605         int xpe, xpe_map;
   9606         uint32 rval;
   9607         soc_reg_t reg;
   9608         soc_reg_t wred_cng_lmt[4] = {
   9609             WRED_POOL_INST_CONG_LIMIT_0r,
   9610             WRED_POOL_INST_CONG_LIMIT_1r,
   9611             WRED_POOL_INST_CONG_LIMIT_2r,
   9612             WRED_POOL_INST_CONG_LIMIT_3r,
   9613         };
   9614         soc_field_t fld_limit = INVALIDf;
   9615 
   9616         switch (type) {
   9617         case bcmCosqControlEgressPoolSharedLimitBytes:
   9618             reg = MMU_THDM_DB_POOL_SHARED_LIMITr;
   9619             fld_limit = SHARED_LIMITf;
   9620             granularity = 1;
   9621             break;
   9622         case bcmCosqControlEgressPoolResumeLimitBytes:
   9623             reg = MMU_THDM_DB_POOL_RESUME_LIMITr;
   9624             fld_limit = RESUME_LIMITf;
   9625             granularity = 8;
   9626             break;
   9627         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
   9628             reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;
   9629             fld_limit = YELLOW_SHARED_LIMITf;
   9630             granularity = 8;
   9631             break;
   9632         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
   9633             reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr;
   9634             fld_limit = YELLOW_RESUME_LIMITf;
   9635             granularity = 8;
   9636             break;
   9637         case bcmCosqControlEgressPoolRedSharedLimitBytes:
   9638             reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;
   9639             fld_limit = RED_SHARED_LIMITf;
   9640             granularity = 8;
   9641             break;
   9642         case bcmCosqControlEgressPoolRedResumeLimitBytes:
   9643             reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr;
   9644             fld_limit = RED_RESUME_LIMITf;
   9645             granularity = 8;
   9646             break;
   9647         case bcmCosqControlEgressPoolHighCongestionLimitBytes:
   9648             reg = wred_cng_lmt[pool];
   9649             fld_limit = POOL_HI_CONG_LIMITf;
   9650             pool = -1;
   9651             granularity = 1;
   9652             break;
   9653         case bcmCosqControlEgressPoolLowCongestionLimitBytes:
   9654             reg = wred_cng_lmt[pool];
   9655             fld_limit = POOL_LOW_CONG_LIMITf;
   9656             pool = -1;
   9657             granularity = 1;
   9658             break;
   9659         /* coverity[dead_error_begin] */
   9660         default:
   9661             return BCM_E_UNAVAIL;
   9662         }
   9663 
   9664         /* These regs are chip unique, buffer = -1 writes on all 4 xpes. 
   9665            No need to do pipe-xpe checking */
   9666         xpe_map = SOC_INFO(unit).ipipe_xpe_map[0] | 
   9667                   SOC_INFO(unit).ipipe_xpe_map[1];
   9668         if (buffer == BCM_COSQ_BUFFER_ID_INVALID) {
   9669             xpe_map = SOC_INFO(unit).epipe_xpe_map[pipe];
   9670             /*find the first valid xpe*/
   9671             for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
   9672                 if ((xpe_map & (1 << xpe))) {
   9673                     break;
   9674                 }
   9675             }
   9676             if(xpe == NUM_XPE(unit)) {
   9677                 return BCM_E_INTERNAL;
   9678             }
   9679         } else if (xpe_map & (1 << buffer)) {
   9680             xpe = buffer;
   9681         } else {
   9682             return BCM_E_PARAM;
   9683         }
   9684         
   9685         SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get
   9686             (unit, reg, xpe, -1, pool, &rval));
   9687 
   9688         *arg = soc_reg_field_get(unit, reg, rval, fld_limit);
   9689         *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL;
   9690 
   9691         return BCM_E_NONE;
   9692     }
   9693 
   9694     base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   9695     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9696 
   9697     if (type == bcmCosqControlEgressPoolLimitEnable) {
   9698         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   9699         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   9700                                  midx, entry));
   9701 
   9702         *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMIT_ENABLEf);
   9703         return BCM_E_NONE;
   9704     }
   9705 
   9706     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9707         BCM_IF_ERROR_RETURN
   9708             (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9709                                         _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
   9710                                         &local_port, &startq, NULL));
   9711         base_mem = MMU_THDU_CONFIG_QUEUEm;
   9712         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9713     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9714         BCM_IF_ERROR_RETURN
   9715             (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9716                                         _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
   9717                                         &local_port, &startq, NULL));
   9718 
   9719         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
   9720         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9721     } else {
   9722         if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) {
   9723             /* Need to have the UC_MC_Combine config enabled */
   9724             return BCM_E_PARAM;
   9725         }
   9726         base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   9727         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9728         startq = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   9729     }
   9730     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   9731                              startq, entry));
   9732 
   9733     switch (type) {
   9734         case bcmCosqControlEgressPoolLimitBytes:
   9735             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9736                 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf);
   9737             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9738                 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMITf);
   9739             } else {
   9740                 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf);
   9741             }
   9742             granularity = 1;
   9743             break;
   9744         case bcmCosqControlEgressPoolYellowLimitBytes:
   9745             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9746                 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_YELLOW_CELLf);
   9747             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9748                 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf);
   9749             } else {
   9750                 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf);
   9751             }
   9752             granularity = 8;
   9753             break;
   9754         case bcmCosqControlEgressPoolRedLimitBytes:
   9755             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   9756                 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_RED_CELLf);
   9757             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9758                 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf);
   9759             } else {
   9760                 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf);
   9761             }
   9762             granularity = 8;
   9763             break;
   9764         default:
   9765             return BCM_E_UNAVAIL;
   9766     }
   9767     *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL;
   9768     return BCM_E_NONE;
   9769 }
   9770 
   9771 STATIC int
   9772 _bcm_th_cosq_egr_port_pool_set(int unit, bcm_gport_t gport,
   9773                                bcm_cos_queue_t cosq,
   9774                                bcm_cosq_control_t type, int arg)
   9775 {
   9776     bcm_port_t local_port;
   9777     uint32 max_val;
   9778     uint32 entry[SOC_MAX_MEM_WORDS];
   9779     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   9780     soc_field_t fld_limit = INVALIDf;
   9781     int granularity = 1;
   9782     int pool, midx, pipe;
   9783 
   9784     if (arg < 0) {
   9785         return BCM_E_PARAM;
   9786     }
   9787 
   9788     BCM_IF_ERROR_RETURN
   9789         (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9790                                     _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL,
   9791                                     &local_port, &pool, NULL));
   9792     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   9793 
   9794     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9795         base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   9796     } else {
   9797         if ((type == bcmCosqControlEgressPortPoolRedResumeBytes) ||
   9798             (type == bcmCosqControlEgressPortPoolYellowResumeBytes) ||
   9799             (type == bcmCosqControlEgressPortPoolSharedResumeBytes)) {
   9800             base_mem = MMU_THDU_RESUME_PORTm;
   9801         } else {
   9802             base_mem = MMU_THDU_CONFIG_PORTm;
   9803         }
   9804     }
   9805     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9806     midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   9807     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   9808 
   9809     switch (type) {
   9810         case bcmCosqControlEgressPortPoolYellowLimitBytes:
   9811             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9812                 fld_limit = YELLOW_SHARED_LIMITf;
   9813             } else {
   9814                 fld_limit = YELLOW_LIMITf;
   9815             }
   9816             granularity = 8;
   9817             break;
   9818         case bcmCosqControlEgressPortPoolRedLimitBytes:
   9819             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9820                 fld_limit = RED_SHARED_LIMITf;
   9821             } else {
   9822                 fld_limit = RED_LIMITf;
   9823             }
   9824             granularity = 8;
   9825             break;
   9826         case bcmCosqControlEgressPortPoolSharedLimitBytes:
   9827             fld_limit = SHARED_LIMITf;
   9828             granularity = 8;
   9829             break;
   9830         case bcmCosqControlEgressPortPoolRedResumeBytes:
   9831             fld_limit = RED_RESUMEf;
   9832             granularity = 8;
   9833             break;
   9834         case bcmCosqControlEgressPortPoolYellowResumeBytes:
   9835             fld_limit = YELLOW_RESUMEf;
   9836             granularity = 8;
   9837             break;
   9838         case bcmCosqControlEgressPortPoolSharedResumeBytes:
   9839             fld_limit = SHARED_RESUMEf;
   9840             granularity = 8;
   9841             break;
   9842         default:
   9843             return BCM_E_UNAVAIL;
   9844     }
   9845 
   9846     arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL;
   9847 
   9848     /* Check for min/max values */
   9849     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   9850     if ((arg < 0) || ((arg/granularity) > max_val)) {
   9851         return BCM_E_PARAM;
   9852     } else {
   9853         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   9854     }
   9855     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   9856 
   9857     return BCM_E_NONE;
   9858 }
   9859 
   9860 STATIC int
   9861 _bcm_th_cosq_egr_port_pool_get(int unit, bcm_gport_t gport,
   9862                                bcm_cos_queue_t cosq,
   9863                                bcm_cosq_control_t type, int *arg)
   9864 {
   9865     bcm_port_t local_port;
   9866     uint32 entry[SOC_MAX_MEM_WORDS];
   9867     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   9868     int granularity = 1;
   9869     int pool, midx, pipe;
   9870 
   9871     if (!arg) {
   9872         return BCM_E_PARAM;
   9873     }
   9874 
   9875     BCM_IF_ERROR_RETURN
   9876         (_bcm_th_cosq_index_resolve(unit, gport, cosq,
   9877                                     _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL,
   9878                                     &local_port, &pool, NULL));
   9879     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   9880 
   9881     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9882         base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   9883     } else {
   9884         if ((type == bcmCosqControlEgressPortPoolRedResumeBytes) ||
   9885             (type == bcmCosqControlEgressPortPoolYellowResumeBytes) ||
   9886             (type == bcmCosqControlEgressPortPoolSharedResumeBytes)) {
   9887             base_mem = MMU_THDU_RESUME_PORTm;
   9888         } else {
   9889             base_mem = MMU_THDU_CONFIG_PORTm;
   9890         }
   9891     }
   9892     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9893     midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   9894     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   9895 
   9896     switch (type) {
   9897         case bcmCosqControlEgressPortPoolYellowLimitBytes:
   9898             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9899                 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf);
   9900             } else {
   9901                 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_LIMITf);
   9902             }
   9903             granularity = 8;
   9904             break;
   9905         case bcmCosqControlEgressPortPoolRedLimitBytes:
   9906             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9907                 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf);
   9908             } else {
   9909                 *arg = soc_mem_field32_get(unit, mem, entry, RED_LIMITf);
   9910             }
   9911             granularity = 8;
   9912             break;
   9913         case bcmCosqControlEgressPortPoolSharedLimitBytes:
   9914              *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf);
   9915              granularity = 8;
   9916              break;
   9917         case bcmCosqControlEgressPortPoolRedResumeBytes:
   9918              *arg = soc_mem_field32_get(unit, mem, entry, RED_RESUMEf);
   9919              granularity = 8;
   9920              break;
   9921         case bcmCosqControlEgressPortPoolYellowResumeBytes:
   9922              *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_RESUMEf);
   9923              granularity = 8;
   9924              break;
   9925         case bcmCosqControlEgressPortPoolSharedResumeBytes:
   9926              *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_RESUMEf);
   9927              granularity = 8;
   9928              break;
   9929         default:
   9930             return BCM_E_UNAVAIL;
   9931     }
   9932 
   9933     *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL;
   9934     return BCM_E_NONE;
   9935 }
   9936 
   9937 STATIC int
   9938 _bcm_th_cosq_dynamic_thresh_enable_get(int unit,
   9939                         bcm_gport_t gport, bcm_cos_queue_t cosq,
   9940                         bcm_cosq_control_t type, int *arg)
   9941 {
   9942     bcm_port_t local_port;
   9943     int startq, pipe, from_cos, to_cos, ci, midx, port_pg;
   9944     uint32 rval;
   9945     uint32 entry[SOC_MAX_MEM_WORDS];
   9946     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   9947     soc_reg_t reg = INVALIDr;
   9948     static const soc_reg_t prigroup_reg[] = {
   9949         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   9950     };
   9951     static const soc_field_t prigroup_field[] = {
   9952         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   9953         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   9954         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   9955         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   9956     };
   9957 
   9958     if (!arg) {
   9959         return BCM_E_PARAM;
   9960     }
   9961 
   9962     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
   9963         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   9964             BCM_GPORT_IS_SCHEDULER(gport) ||
   9965             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9966             return BCM_E_PARAM;
   9967         }
   9968         BCM_IF_ERROR_RETURN
   9969             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
   9970         if (local_port < 0) {
   9971             return BCM_E_PORT;
   9972         }
   9973         if ((cosq < 0) || (cosq >= 16)) {
   9974             return BCM_E_PARAM;
   9975         }
   9976         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   9977 
   9978         if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) {
   9979             /* Error. Input pri > Max Pri_Grp */
   9980             /* coverity[dead_error_line] */
   9981             return BCM_E_PARAM;
   9982         }
   9983 
   9984         /* get PG for port using Port+Cos */
   9985         if (cosq < _TH_MMU_NUM_PG) {
   9986             reg = prigroup_reg[0];
   9987         } else {
   9988             reg = prigroup_reg[1];
   9989         }
   9990 
   9991         SOC_IF_ERROR_RETURN
   9992             (soc_reg32_get(unit, reg, local_port, 0, &rval));
   9993         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
   9994         base_mem = THDI_PORT_PG_CONFIGm;
   9995         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9996         /* get index for Port-PG */
   9997         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   9998 
   9999         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  10000                                  midx, entry));
  10001         *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf);
  10002 
  10003     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
  10004         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10005             BCM_IF_ERROR_RETURN
  10006                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10007                                          _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10008                                          &local_port, &startq, NULL));
  10009         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10010             return BCM_E_PARAM;
  10011         } else {
  10012             if (cosq == BCM_COS_INVALID) {
  10013                 from_cos = to_cos = 0;
  10014             } else {
  10015                 from_cos = to_cos = cosq;
  10016             }
  10017 
  10018             BCM_IF_ERROR_RETURN
  10019                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10020             if (local_port < 0) {
  10021                 return BCM_E_PORT;
  10022             }
  10023             for (ci = from_cos; ci <= to_cos; ci++) {
  10024                 BCM_IF_ERROR_RETURN
  10025                     (_bcm_th_cosq_index_resolve(unit, local_port, ci,
  10026                           _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10027                           NULL, &startq, NULL));
  10028             }
  10029         }
  10030         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10031         base_mem = MMU_THDU_CONFIG_QUEUEm;
  10032         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10033 
  10034         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  10035                                  startq, entry));
  10036         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf);
  10037     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
  10038         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10039             return BCM_E_PARAM;
  10040         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10041             BCM_IF_ERROR_RETURN
  10042                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10043                                          _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10044                                          &local_port, &startq, NULL));
  10045         }
  10046         else {
  10047             if (cosq == BCM_COS_INVALID) {
  10048                 from_cos = to_cos = 0;
  10049             } else {
  10050                 from_cos = to_cos = cosq;
  10051             }
  10052 
  10053             BCM_IF_ERROR_RETURN
  10054                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10055             if (local_port < 0) {
  10056                 return BCM_E_PORT;
  10057             }
  10058             for (ci = from_cos; ci <= to_cos; ci++) {
  10059                 BCM_IF_ERROR_RETURN
  10060                     (_bcm_th_cosq_index_resolve(unit, local_port, ci,
  10061                                          _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10062                                          NULL, &startq, NULL));
  10063             }
  10064         }
  10065         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10066         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
  10067         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10068 
  10069         BCM_IF_ERROR_RETURN
  10070             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10071         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMICf);
  10072     } else {
  10073         return BCM_E_PARAM;
  10074     }
  10075 
  10076     return BCM_E_NONE;
  10077 }
  10078 
  10079 STATIC int
  10080 _bcm_th_cosq_alpha_set(int unit,
  10081                        bcm_gport_t gport, bcm_cos_queue_t cosq,
  10082                        bcm_cosq_control_drop_limit_alpha_value_t arg)
  10083 {
  10084     bcm_port_t local_port;
  10085     int startq, midx, pipe;
  10086     uint32 rval;
  10087     uint32 entry[SOC_MAX_MEM_WORDS];
  10088     uint32 entry2[SOC_MAX_MEM_WORDS];
  10089     soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm;
  10090     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  10091     int alpha, dynamic_thresh_mode, port_pg;
  10092     soc_reg_t reg = INVALIDr;
  10093     static const soc_reg_t prigroup_reg[] = {
  10094         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  10095     };
  10096     static const soc_field_t prigroup_field[] = {
  10097         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  10098         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  10099         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  10100         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  10101     };
  10102     int phy_port, mmu_port, local_mmu_port;
  10103 
  10104     soc_info_t *si;
  10105     si = &SOC_INFO(unit);
  10106 
  10107     switch(arg) {
  10108     case bcmCosqControlDropLimitAlpha_1_128:
  10109         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128;
  10110         break;
  10111     case bcmCosqControlDropLimitAlpha_1_64:
  10112         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_64;
  10113         break;
  10114     case bcmCosqControlDropLimitAlpha_1_32:
  10115         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_32;
  10116         break;
  10117     case bcmCosqControlDropLimitAlpha_1_16:
  10118         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_16;
  10119         break;
  10120     case bcmCosqControlDropLimitAlpha_1_8:
  10121         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_8;
  10122         break;
  10123     case bcmCosqControlDropLimitAlpha_1_4:
  10124         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_4;
  10125         break;
  10126     case bcmCosqControlDropLimitAlpha_1_2:
  10127         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_2;
  10128         break;
  10129     case bcmCosqControlDropLimitAlpha_1:
  10130         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_1;
  10131         break;
  10132     case bcmCosqControlDropLimitAlpha_2:
  10133         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_2;
  10134         break;
  10135     case bcmCosqControlDropLimitAlpha_4:
  10136         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_4;
  10137         break;
  10138     case bcmCosqControlDropLimitAlpha_8:
  10139         alpha = SOC_TH_COSQ_DROP_LIMIT_ALPHA_8;
  10140         break;
  10141     default:
  10142         return BCM_E_PARAM;
  10143     }
  10144 
  10145     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10146         BCM_IF_ERROR_RETURN
  10147                 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  10148                                    bcmCosqControlEgressUCSharedDynamicEnable,
  10149                                    &dynamic_thresh_mode));
  10150         if (!dynamic_thresh_mode){
  10151             return BCM_E_CONFIG;
  10152         }
  10153 
  10154         BCM_IF_ERROR_RETURN
  10155             (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10156                                      _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10157                                      &local_port, &startq, NULL));
  10158         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10159 
  10160         base_mem = MMU_THDU_CONFIG_QUEUEm;
  10161         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10162 
  10163         BCM_IF_ERROR_RETURN
  10164             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10165         soc_mem_field32_set(unit, mem, entry,
  10166                             Q_SHARED_ALPHA_CELLf, alpha);
  10167         SOC_IF_ERROR_RETURN
  10168             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10169     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10170         BCM_IF_ERROR_RETURN
  10171                 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  10172                                    bcmCosqControlEgressMCSharedDynamicEnable,
  10173                                    &dynamic_thresh_mode));
  10174         if (!dynamic_thresh_mode){
  10175             return BCM_E_CONFIG;
  10176         }
  10177 
  10178         BCM_IF_ERROR_RETURN
  10179             (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10180                                      _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10181                                      &local_port, &startq, NULL));
  10182         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10183 
  10184         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
  10185         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10186 
  10187         base_mem2 = MMU_THDM_MCQE_QUEUE_CONFIGm;
  10188         mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
  10189 
  10190         BCM_IF_ERROR_RETURN
  10191             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10192         soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, alpha);
  10193         SOC_IF_ERROR_RETURN
  10194             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10195 
  10196         BCM_IF_ERROR_RETURN
  10197             (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  10198         soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, alpha);
  10199         SOC_IF_ERROR_RETURN
  10200             (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  10201     } else if (BCM_GPORT_IS_LOCAL(gport)) {
  10202         /*Set the alpha for Qgroup associated with the gport*/
  10203             BCM_IF_ERROR_RETURN
  10204                 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  10205                                    bcmCosqControlEgressUCQueueGroupSharedDynamicEnable,
  10206                                    &dynamic_thresh_mode));
  10207         if (!dynamic_thresh_mode){
  10208             return BCM_E_CONFIG;
  10209         }
  10210 
  10211         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10212 
  10213         phy_port = si->port_l2p_mapping[local_port];
  10214         mmu_port = si->port_p2m_mapping[phy_port];
  10215         local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1);
  10216 
  10217         base_mem =  MMU_THDU_CONFIG_QGROUPm;
  10218         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10219 
  10220         BCM_IF_ERROR_RETURN
  10221             (soc_mem_read(unit, mem, MEM_BLOCK_ALL,local_mmu_port , entry));
  10222         soc_mem_field32_set(unit, mem, entry,
  10223                             Q_SHARED_ALPHA_CELLf, alpha);
  10224         SOC_IF_ERROR_RETURN
  10225             (soc_mem_write(unit, mem, MEM_BLOCK_ALL,local_mmu_port , entry));
  10226     } else {
  10227         BCM_IF_ERROR_RETURN
  10228                 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  10229                                    bcmCosqControlIngressPortPGSharedDynamicEnable,
  10230                                    &dynamic_thresh_mode));
  10231         if (!dynamic_thresh_mode){
  10232             return BCM_E_CONFIG;
  10233         }
  10234 
  10235         BCM_IF_ERROR_RETURN
  10236             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10237         if (local_port < 0) {
  10238             return BCM_E_PORT;
  10239         }
  10240         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10241 
  10242         if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) {
  10243             /* Error. Input pri > Max Pri_Grp */
  10244             return BCM_E_PARAM;
  10245         }
  10246 
  10247         /* get PG for port using Port+Cos */
  10248         if (cosq < _TH_MMU_NUM_PG) {
  10249             reg = prigroup_reg[0];
  10250         } else {
  10251             reg = prigroup_reg[1];
  10252         }
  10253 
  10254         SOC_IF_ERROR_RETURN
  10255             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  10256         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  10257         base_mem = THDI_PORT_PG_CONFIGm;
  10258         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10259         /* get index for Port-PG */
  10260         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
  10261         BCM_IF_ERROR_RETURN
  10262             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  10263         soc_mem_field32_set(unit, mem, entry, PG_SHARED_LIMITf, alpha);
  10264         SOC_IF_ERROR_RETURN
  10265             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
  10266     }
  10267 
  10268     return BCM_E_NONE;
  10269 }
  10270 
  10271 
  10272 STATIC int
  10273 _bcm_th_cosq_alpha_get(int unit,
  10274                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  10275                         bcm_cosq_control_drop_limit_alpha_value_t *arg)
  10276 {
  10277     bcm_port_t local_port;
  10278     int startq, midx, pipe;
  10279     uint32 rval;
  10280     uint32 entry[SOC_MAX_MEM_WORDS];
  10281     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
  10282     int alpha, dynamic_thresh_mode, port_pg;
  10283     soc_reg_t reg = INVALIDr;
  10284     static const soc_reg_t prigroup_reg[] = {
  10285         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  10286     };
  10287     static const soc_field_t prigroup_field[] = {
  10288         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  10289         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  10290         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  10291         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  10292     };
  10293 
  10294     if (!arg) {
  10295         return BCM_E_PARAM;
  10296     }
  10297 
  10298     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10299         BCM_IF_ERROR_RETURN
  10300                 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  10301                                    bcmCosqControlEgressUCSharedDynamicEnable,
  10302                                    &dynamic_thresh_mode));
  10303         if (!dynamic_thresh_mode){
  10304             return BCM_E_CONFIG;
  10305         }
  10306 
  10307         BCM_IF_ERROR_RETURN
  10308             (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10309                                      _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10310                                      &local_port, &startq, NULL));
  10311         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10312 
  10313         base_mem = MMU_THDU_CONFIG_QUEUEm;
  10314         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10315 
  10316         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  10317                                  startq, entry));
  10318         alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf);
  10319 
  10320     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10321         BCM_IF_ERROR_RETURN
  10322                 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  10323                                    bcmCosqControlEgressMCSharedDynamicEnable,
  10324                                    &dynamic_thresh_mode));
  10325         if (!dynamic_thresh_mode){
  10326             return BCM_E_CONFIG;
  10327         }
  10328 
  10329         BCM_IF_ERROR_RETURN
  10330             (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10331                                      _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10332                                      &local_port, &startq, NULL));
  10333         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10334 
  10335         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
  10336         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10337         BCM_IF_ERROR_RETURN
  10338             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10339         alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHAf);
  10340 
  10341     } else {
  10342         BCM_IF_ERROR_RETURN
  10343                 (_bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  10344                                    bcmCosqControlIngressPortPGSharedDynamicEnable,
  10345                                    &dynamic_thresh_mode));
  10346         if (!dynamic_thresh_mode){
  10347             return BCM_E_CONFIG;
  10348         }
  10349 
  10350         BCM_IF_ERROR_RETURN
  10351             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10352         if (local_port < 0) {
  10353             return BCM_E_PORT;
  10354         }
  10355 
  10356         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10357 
  10358         if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) {
  10359             /* Error. Input pri > Max Pri_Grp */
  10360             return BCM_E_PARAM;
  10361         }
  10362 
  10363         /* get PG for port using Port+Cos */
  10364         if (cosq < _TH_MMU_NUM_PG) {
  10365             reg = prigroup_reg[0];
  10366         } else {
  10367             reg = prigroup_reg[1];
  10368         }
  10369 
  10370         SOC_IF_ERROR_RETURN
  10371             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  10372         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  10373 
  10374         base_mem = THDI_PORT_PG_CONFIGm;
  10375         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10376         /* get index for Port-PG */
  10377         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
  10378 
  10379         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  10380                                  midx, entry));
  10381         alpha = soc_mem_field32_get(unit, mem, entry, PG_SHARED_LIMITf);
  10382 
  10383     }
  10384 
  10385     switch(alpha) {
  10386     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128:
  10387         *arg = bcmCosqControlDropLimitAlpha_1_128;
  10388         break;
  10389     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_64:
  10390         *arg = bcmCosqControlDropLimitAlpha_1_64;
  10391         break;
  10392     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_32:
  10393         *arg = bcmCosqControlDropLimitAlpha_1_32;
  10394         break;
  10395     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_16:
  10396         *arg = bcmCosqControlDropLimitAlpha_1_16;
  10397         break;
  10398     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_8:
  10399         *arg = bcmCosqControlDropLimitAlpha_1_8;
  10400         break;
  10401     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_4:
  10402         *arg = bcmCosqControlDropLimitAlpha_1_4;
  10403         break;
  10404     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_2:
  10405         *arg = bcmCosqControlDropLimitAlpha_1_2;
  10406         break;
  10407     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_1:
  10408         *arg = bcmCosqControlDropLimitAlpha_1;
  10409         break;
  10410     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_2:
  10411         *arg = bcmCosqControlDropLimitAlpha_2;
  10412         break;
  10413     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_4:
  10414         *arg = bcmCosqControlDropLimitAlpha_4;
  10415         break;
  10416     case SOC_TH_COSQ_DROP_LIMIT_ALPHA_8:
  10417         *arg = bcmCosqControlDropLimitAlpha_8;
  10418         break;
  10419     default:
  10420         return BCM_E_PARAM;
  10421     }
  10422 
  10423     return BCM_E_NONE;
  10424 }
  10425 
  10426 STATIC int
  10427 _bcm_th_cosq_dynamic_thresh_enable_set(int unit,
  10428                         bcm_gport_t gport, bcm_cos_queue_t cosq,
  10429                         bcm_cosq_control_t type, int arg)
  10430 {
  10431     bcm_port_t local_port;
  10432     int startq, pipe;
  10433     int from_cos, to_cos, ci;
  10434     int midx;
  10435     uint32 rval;
  10436     uint32 entry[SOC_MAX_MEM_WORDS];
  10437     uint32 entry2[SOC_MAX_MEM_WORDS];
  10438     soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm;
  10439     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
  10440     soc_reg_t reg = INVALIDr;
  10441     int port_pg;
  10442     static const soc_reg_t prigroup_reg[] = {
  10443         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
  10444     };
  10445     static const soc_field_t prigroup_field[] = {
  10446         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
  10447         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
  10448         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
  10449         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
  10450     };
  10451 
  10452     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
  10453         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  10454             BCM_GPORT_IS_SCHEDULER(gport) ||
  10455             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10456             return BCM_E_PARAM;
  10457         }
  10458         BCM_IF_ERROR_RETURN
  10459             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10460         if (local_port < 0) {
  10461             return BCM_E_PORT;
  10462         }
  10463         if ((cosq < 0) || (cosq >= 16)) {
  10464             return BCM_E_PARAM;
  10465         }
  10466         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10467 
  10468         if ((cosq < 0) || (cosq >= _TH_MMU_NUM_INT_PRI)) {
  10469             /* Error. Input pri > Max Pri_Grp */
  10470             /* coverity[dead_error_line] */
  10471             return BCM_E_PARAM;
  10472         }
  10473 
  10474         /* get PG for port using Port+Cos */
  10475         if (cosq < _TH_MMU_NUM_PG) {
  10476             reg = prigroup_reg[0];
  10477         } else {
  10478             reg = prigroup_reg[1];
  10479         }
  10480 
  10481         SOC_IF_ERROR_RETURN
  10482             (soc_reg32_get(unit, reg, local_port, 0, &rval));
  10483         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
  10484         base_mem = THDI_PORT_PG_CONFIGm;
  10485         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10486         /* get index for Port-PG */
  10487         midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
  10488         BCM_IF_ERROR_RETURN
  10489             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
  10490         soc_mem_field32_set(unit, mem, entry,
  10491                             PG_SHARED_DYNAMICf, arg ? 1 : 0);
  10492         if(arg) {
  10493             /* Set default alpha value*/
  10494             soc_mem_field32_set(unit, mem, entry, PG_SHARED_LIMITf,
  10495                                 SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128);
  10496         }
  10497         SOC_IF_ERROR_RETURN
  10498             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
  10499     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
  10500         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10501             BCM_IF_ERROR_RETURN
  10502                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10503                                             _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10504                                             &local_port, &startq, NULL));
  10505         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10506             return BCM_E_PARAM;
  10507         } else {
  10508             if (cosq == BCM_COS_INVALID) {
  10509                 from_cos = to_cos = 0;
  10510             } else {
  10511                 from_cos = to_cos = cosq;
  10512             }
  10513 
  10514             BCM_IF_ERROR_RETURN
  10515                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10516             if (local_port < 0) {
  10517                 return BCM_E_PORT;
  10518             }
  10519             for (ci = from_cos; ci <= to_cos; ci++) {
  10520                 BCM_IF_ERROR_RETURN
  10521                     (_bcm_th_cosq_index_resolve(unit, local_port, ci,
  10522                                          _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10523                                          NULL, &startq, NULL));
  10524 
  10525             }
  10526         }
  10527         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10528         base_mem = MMU_THDU_CONFIG_QUEUEm;
  10529         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10530 
  10531         BCM_IF_ERROR_RETURN
  10532             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10533         soc_mem_field32_set(unit, mem, entry,
  10534                             Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0);
  10535         if(arg) {
  10536             /* Set default alpha value*/
  10537             soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHA_CELLf,
  10538                                 SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128);
  10539         }
  10540         SOC_IF_ERROR_RETURN
  10541             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10542     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
  10543         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10544             return BCM_E_PARAM;
  10545         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10546             BCM_IF_ERROR_RETURN
  10547                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10548                                       _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10549                                       &local_port, &startq, NULL));
  10550         }
  10551         else {
  10552             if (cosq == BCM_COS_INVALID) {
  10553                 from_cos = to_cos = 0;
  10554             } else {
  10555                 from_cos = to_cos = cosq;
  10556             }
  10557 
  10558             BCM_IF_ERROR_RETURN
  10559                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10560             if (local_port < 0) {
  10561                 return BCM_E_PORT;
  10562             }
  10563             for (ci = from_cos; ci <= to_cos; ci++) {
  10564                 BCM_IF_ERROR_RETURN
  10565                     (_bcm_th_cosq_index_resolve(unit, local_port, ci,
  10566                                          _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10567                                          NULL, &startq, NULL));
  10568 
  10569             }
  10570         }
  10571 
  10572         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10573         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
  10574         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  10575 
  10576         base_mem2 = MMU_THDM_MCQE_QUEUE_CONFIGm;
  10577         mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
  10578 
  10579         BCM_IF_ERROR_RETURN
  10580             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10581         soc_mem_field32_set(unit, mem, entry, Q_LIMIT_DYNAMICf, arg ? 1 : 0);
  10582         if(arg) {
  10583             /* Set default alpha value*/
  10584             soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf,
  10585                                 SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128);
  10586         }
  10587         SOC_IF_ERROR_RETURN
  10588             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10589 
  10590         BCM_IF_ERROR_RETURN
  10591             (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  10592         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_DYNAMICf, arg ? 1 : 0);
  10593         if(arg) {
  10594             /* Set default alpha value*/
  10595             soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf,
  10596                                 SOC_TH_COSQ_DROP_LIMIT_ALPHA_1_128);
  10597         }
  10598         SOC_IF_ERROR_RETURN
  10599             (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
  10600 
  10601     } else {
  10602         return BCM_E_PARAM;
  10603     }
  10604 
  10605     return BCM_E_NONE;
  10606 }
  10607 /*
  10608  * Function: _bcm_th_cosq_egr_queue_color_limit_set
  10609  * Purpose: Set Red and Yellow color limit per queue
  10610  *          IF color mode dynamic: limit should be between 0-7
  10611  *                                 0: 100% of green threshold
  10612  *                                 1: 12.5% of green threshold
  10613  *                                 2: 25% of green threshold
  10614  *                                 3: 37.5% of green threshold
  10615  *                                 4: 50% of green threshold
  10616  *                                 5: 67.5% of green threshold
  10617  *                                 6: 75% of green threshold
  10618  *                                 7: 87.5% of green threshold
  10619  *          If color mode static: Limit is number of bytes
  10620 */
  10621 
  10622 STATIC int
  10623 _bcm_th_cosq_egr_queue_color_limit_set(int unit, bcm_gport_t gport,
  10624                                         bcm_cos_queue_t cosq,
  10625                                         bcm_cosq_control_t type,
  10626                                         int arg)
  10627 {
  10628     bcm_port_t local_port;
  10629     int startq, pipe;
  10630     uint32 entry[SOC_MAX_MEM_WORDS];
  10631     soc_mem_t mem = INVALIDm;
  10632     soc_field_t fld_limit = INVALIDf;
  10633     int color_mode, granularity, max_val;
  10634 
  10635     if (arg < 0) {
  10636         return BCM_E_PARAM;
  10637     }
  10638     granularity = 8;
  10639 
  10640     if ((type == bcmCosqControlEgressUCQueueRedLimit) ||
  10641         (type == bcmCosqControlEgressUCQueueYellowLimit)) {
  10642         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10643             BCM_IF_ERROR_RETURN
  10644                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10645                                             _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10646                                             &local_port, &startq, NULL));
  10647         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10648             return BCM_E_PARAM;
  10649         } else {
  10650             if (cosq < 0) {
  10651                 return BCM_E_PARAM;
  10652             }
  10653             BCM_IF_ERROR_RETURN
  10654                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10655             if (local_port < 0) {
  10656                 return BCM_E_PORT;
  10657             }
  10658             BCM_IF_ERROR_RETURN
  10659                 (_bcm_th_cosq_index_resolve
  10660                  (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10661                   NULL, &startq, NULL));
  10662         }
  10663         if (type == bcmCosqControlEgressUCQueueRedLimit) {
  10664             fld_limit = LIMIT_RED_CELLf;
  10665         } else {
  10666             fld_limit = LIMIT_YELLOW_CELLf;
  10667         }
  10668         BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10669         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe];
  10670         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10671         color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf);
  10672 
  10673         if (color_mode == 1) { /* Dynamic color limit */
  10674             if (arg > 7) { /* Legal values are 0 - 7 */
  10675                 return BCM_E_PARAM;
  10676             } else {
  10677                 soc_mem_field32_set(unit, mem, entry, fld_limit, arg);
  10678             }
  10679         } else { /* Static color limit */
  10680             arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL;
  10681 
  10682             /* Check for min/max values */
  10683             max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  10684             if ((arg < 0) || ((arg/granularity) > max_val)) {
  10685                 return BCM_E_PARAM;
  10686             } else {
  10687                 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  10688             }
  10689         }
  10690         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10691     } else if ((type == bcmCosqControlEgressMCQueueRedLimit) ||
  10692                (type == bcmCosqControlEgressMCQueueYellowLimit)) {
  10693         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10694             return BCM_E_PARAM;
  10695         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10696             BCM_IF_ERROR_RETURN
  10697                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10698                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10699                                             &local_port, &startq, NULL));
  10700         } else {
  10701             if (cosq < 0) {
  10702                 return BCM_E_PARAM;
  10703             }
  10704             BCM_IF_ERROR_RETURN
  10705                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10706             if (local_port < 0) {
  10707                 return BCM_E_PORT;
  10708             }
  10709             BCM_IF_ERROR_RETURN
  10710                 (_bcm_th_cosq_index_resolve(unit, local_port, cosq,
  10711                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10712                                             NULL, &startq, NULL));
  10713         }
  10714 
  10715         if (type == bcmCosqControlEgressMCQueueRedLimit) {
  10716             fld_limit = RED_SHARED_LIMITf;
  10717         } else {
  10718             fld_limit = YELLOW_SHARED_LIMITf;
  10719         }
  10720         BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10721         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe];
  10722         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10723         color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf);
  10724 
  10725         if (color_mode == 1) { /* Dynamic color limit */
  10726             if (arg > 7) { /* Legal values are 0 - 7 */
  10727                 return BCM_E_PARAM;
  10728             } else {
  10729                 soc_mem_field32_set(unit, mem, entry, fld_limit, arg);
  10730             }
  10731         } else { /* Static color limit */
  10732             arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL;
  10733 
  10734             /* Check for min/max values */
  10735             max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
  10736             if ((arg < 0) || ((arg/granularity) > max_val)) {
  10737                 return BCM_E_PARAM;
  10738             } else {
  10739                 soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
  10740             }
  10741         }
  10742         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10743 
  10744     } else {
  10745         return BCM_E_PARAM;
  10746     }
  10747 
  10748     return BCM_E_NONE;
  10749 }
  10750 
  10751 /*
  10752  * Function: _bcm_th_cosq_egr_queue_color_limit_get
  10753  * Purpose: Get Red and Yellow color limit per queue
  10754  * Return value: IF color mode dynamic: limit should be between 0-7
  10755  *                                 0: 100% of green threshold
  10756  *                                 1: 12.5% of green threshold
  10757  *                                 2: 25% of green threshold
  10758  *                                 3: 37.5% of green threshold
  10759  *                                 4: 50% of green threshold
  10760  *                                 5: 67.5% of green threshold
  10761  *                                 6: 75% of green threshold
  10762  *                                 7: 87.5% of green threshold
  10763  *          If color mode static: Limit is number of bytes
  10764 */
  10765 
  10766 STATIC int
  10767 _bcm_th_cosq_egr_queue_color_limit_get(int unit, bcm_gport_t gport,
  10768                                         bcm_cos_queue_t cosq,
  10769                                         bcm_cosq_control_t type,
  10770                                         int* arg)
  10771 {
  10772     bcm_port_t local_port;
  10773     int startq, pipe;
  10774     uint32 entry[SOC_MAX_MEM_WORDS];
  10775     soc_mem_t mem = INVALIDm;
  10776     soc_field_t fld_limit = INVALIDf;
  10777     int color_mode, granularity;
  10778 
  10779     if (arg == NULL) {
  10780         return BCM_E_PARAM;
  10781     }
  10782 
  10783     granularity = 8;
  10784 
  10785     if ((type == bcmCosqControlEgressUCQueueRedLimit) ||
  10786         (type == bcmCosqControlEgressUCQueueYellowLimit)) {
  10787         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10788             BCM_IF_ERROR_RETURN
  10789                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10790                                             _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10791                                             &local_port, &startq, NULL));
  10792         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10793             return BCM_E_PARAM;
  10794         } else {
  10795             if (cosq < 0) {
  10796                 return BCM_E_PARAM;
  10797             }
  10798             BCM_IF_ERROR_RETURN
  10799                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10800             if (local_port < 0) {
  10801                 return BCM_E_PORT;
  10802             }
  10803             BCM_IF_ERROR_RETURN
  10804                 (_bcm_th_cosq_index_resolve
  10805                  (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10806                   NULL, &startq, NULL));
  10807         }
  10808 
  10809         if (type == bcmCosqControlEgressUCQueueRedLimit) {
  10810             fld_limit = LIMIT_RED_CELLf;
  10811         } else {
  10812             fld_limit = LIMIT_YELLOW_CELLf;
  10813         }
  10814         BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10815         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe];
  10816         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10817         color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf);
  10818 
  10819         if (color_mode == 1) { /* Dynamic color limit */
  10820             *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  10821         } else { /* Static color limit */
  10822             *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  10823             *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL;
  10824         }
  10825     } else if ((type == bcmCosqControlEgressMCQueueRedLimit) ||
  10826                (type == bcmCosqControlEgressMCQueueYellowLimit)) {
  10827         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10828             return BCM_E_PARAM;
  10829         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10830             BCM_IF_ERROR_RETURN
  10831                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10832                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10833                                             &local_port, &startq, NULL));
  10834         } else {
  10835             if (cosq < 0) {
  10836                 return BCM_E_PARAM;
  10837             }
  10838             BCM_IF_ERROR_RETURN
  10839                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10840             if (local_port < 0) {
  10841                 return BCM_E_PORT;
  10842             }
  10843             BCM_IF_ERROR_RETURN
  10844                 (_bcm_th_cosq_index_resolve(unit, local_port, cosq,
  10845                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10846                                             NULL, &startq, NULL));
  10847         }
  10848 
  10849         if (type == bcmCosqControlEgressMCQueueRedLimit) {
  10850             fld_limit = RED_SHARED_LIMITf;
  10851         } else {
  10852             fld_limit = YELLOW_SHARED_LIMITf;
  10853         }
  10854         BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10855         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe];
  10856         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10857         color_mode = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf);
  10858 
  10859         if (color_mode == 1) { /* Dynamic color limit */
  10860             *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  10861         } else { /* Static color limit */
  10862             *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
  10863             *arg = (*arg) * granularity * _TH_MMU_BYTES_PER_CELL;
  10864         }
  10865 
  10866     } else {
  10867         return BCM_E_PARAM;
  10868     }
  10869 
  10870     return BCM_E_NONE;
  10871 }
  10872 
  10873 
  10874 /*
  10875  * Function: _bcm_th_cosq_egr_queue_color_limit_mode_set
  10876  * Purpose: Set color limit mode per queue to static (0) or
  10877  *          dynamic (1)
  10878 */
  10879 
  10880 STATIC int
  10881 _bcm_th_cosq_egr_queue_color_limit_mode_set(int unit, bcm_gport_t gport,
  10882                                              bcm_cos_queue_t cosq,
  10883                                              bcm_cosq_control_t type,
  10884                                              int arg)
  10885 {
  10886     bcm_port_t local_port;
  10887     int startq, pipe;
  10888     uint32 entry[SOC_MAX_MEM_WORDS];
  10889     soc_mem_t mem = INVALIDm;
  10890     int enable;
  10891 
  10892     if (arg < 0) {
  10893         return BCM_E_PARAM;
  10894     }
  10895 
  10896     arg = arg ? 1 : 0;
  10897 
  10898     if (type == bcmCosqControlEgressUCQueueColorLimitDynamicEnable) {
  10899         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10900             BCM_IF_ERROR_RETURN
  10901                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10902                                             _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10903                                             &local_port, &startq, NULL));
  10904         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10905             return BCM_E_PARAM;
  10906         } else {
  10907             if (cosq < 0) {
  10908                 return BCM_E_PARAM;
  10909             }
  10910             BCM_IF_ERROR_RETURN
  10911                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10912             if (local_port < 0) {
  10913                 return BCM_E_PORT;
  10914             }
  10915             BCM_IF_ERROR_RETURN
  10916                 (_bcm_th_cosq_index_resolve
  10917                  (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10918                   NULL, &startq, NULL));
  10919         }
  10920         BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10921         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe];
  10922         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10923         enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf);
  10924         if (enable != arg) {
  10925             soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf, arg);
  10926             /* Reset the Red and Yellow limits when color limit mode is changed */
  10927             soc_mem_field32_set(unit, mem, entry, LIMIT_RED_CELLf, 0);
  10928             soc_mem_field32_set(unit, mem, entry, LIMIT_YELLOW_CELLf, 0);
  10929             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10930         }
  10931     } else if (type == bcmCosqControlEgressMCQueueColorLimitDynamicEnable) {
  10932         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10933             return BCM_E_PARAM;
  10934         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10935             BCM_IF_ERROR_RETURN
  10936                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10937                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10938                                             &local_port, &startq, NULL));
  10939         } else {
  10940             if (cosq < 0) {
  10941                 return BCM_E_PARAM;
  10942             }
  10943             BCM_IF_ERROR_RETURN
  10944                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  10945             if (local_port < 0) {
  10946                 return BCM_E_PORT;
  10947             }
  10948             BCM_IF_ERROR_RETURN
  10949                 (_bcm_th_cosq_index_resolve(unit, local_port, cosq,
  10950                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10951                                             NULL, &startq, NULL));
  10952         }
  10953         BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10954         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe];
  10955         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10956         enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf);
  10957         if (enable != arg) {
  10958             soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf, arg);
  10959             /* Reset the Red and Yellow limits when color limit mode is changed */
  10960             soc_mem_field32_set(unit, mem, entry, RED_SHARED_LIMITf, 0);
  10961             soc_mem_field32_set(unit, mem, entry, YELLOW_SHARED_LIMITf, 0);
  10962             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  10963         }
  10964     } else {
  10965         return BCM_E_PARAM;
  10966     }
  10967 
  10968     return BCM_E_NONE;
  10969 }
  10970 
  10971 /*
  10972  * Function: _bcm_th_cosq_egr_queue_color_limit_mode_get
  10973  * Purpose: Get color limit mode per queue.
  10974  * Returns: 0 (static) or 1 (dynamic)
  10975 */
  10976 STATIC int
  10977 _bcm_th_cosq_egr_queue_color_limit_mode_get(int unit, bcm_gport_t gport,
  10978                                              bcm_cos_queue_t cosq,
  10979                                              bcm_cosq_control_t type,
  10980                                              int* arg)
  10981 {
  10982     bcm_port_t local_port;
  10983     int startq, pipe;
  10984     uint32 entry[SOC_MAX_MEM_WORDS];
  10985     soc_mem_t mem = INVALIDm;
  10986 
  10987     if (arg == NULL) {
  10988         return BCM_E_PARAM;
  10989     }
  10990 
  10991     if (type == bcmCosqControlEgressUCQueueColorLimitDynamicEnable) {
  10992         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10993             BCM_IF_ERROR_RETURN
  10994                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  10995                                             _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10996                                             &local_port, &startq, NULL));
  10997         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10998             return BCM_E_PARAM;
  10999         } else {
  11000             if (cosq < 0) {
  11001                 return BCM_E_PARAM;
  11002             }
  11003             BCM_IF_ERROR_RETURN
  11004                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11005             if (local_port < 0) {
  11006                 return BCM_E_PORT;
  11007             }
  11008             BCM_IF_ERROR_RETURN
  11009                 (_bcm_th_cosq_index_resolve
  11010                  (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11011                   NULL, &startq, NULL));
  11012         }
  11013         BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11014         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe];
  11015         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11016         *arg = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMIC_CELLf);
  11017     } else if (type == bcmCosqControlEgressMCQueueColorLimitDynamicEnable) {
  11018         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11019             return BCM_E_PARAM;
  11020         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11021             BCM_IF_ERROR_RETURN
  11022                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  11023                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11024                                             &local_port, &startq, NULL));
  11025         } else {
  11026             if (cosq < 0) {
  11027                 return BCM_E_PARAM;
  11028             }
  11029             BCM_IF_ERROR_RETURN
  11030                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11031             if (local_port < 0) {
  11032                 return BCM_E_PORT;
  11033             }
  11034             BCM_IF_ERROR_RETURN
  11035                 (_bcm_th_cosq_index_resolve(unit, local_port, cosq,
  11036                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11037                                             NULL, &startq, NULL));
  11038         }
  11039         BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11040         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe];
  11041         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11042         *arg = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_DYNAMICf);
  11043     } else {
  11044         return BCM_E_PARAM;
  11045     }
  11046 
  11047     return BCM_E_NONE;
  11048 }
  11049 
  11050 
  11051 STATIC int
  11052 _bcm_th_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport,
  11053                                         bcm_cos_queue_t cosq,
  11054                                         bcm_cosq_control_t type,
  11055                                         int arg)
  11056 {
  11057     bcm_port_t local_port;
  11058     int startq, pipe;
  11059     uint32 entry[SOC_MAX_MEM_WORDS];
  11060     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
  11061     soc_field_t fld_name = INVALIDf;
  11062     int enable;
  11063 
  11064     if (arg < 0) {
  11065         return BCM_E_PARAM;
  11066     }
  11067 
  11068     arg = arg ? 1 : 0;
  11069 
  11070     if ((type == bcmCosqControlEgressUCQueueLimitEnable) ||
  11071         (type == bcmCosqControlEgressUCQueueColorLimitEnable)) {
  11072         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11073             BCM_IF_ERROR_RETURN
  11074                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  11075                                             _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11076                                             &local_port, &startq, NULL));
  11077         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11078             return BCM_E_PARAM;
  11079         } else {
  11080             if (cosq < 0) {
  11081                 return BCM_E_PARAM;
  11082             }
  11083             BCM_IF_ERROR_RETURN
  11084                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11085             if (local_port < 0) {
  11086                 return BCM_E_PORT;
  11087             }
  11088             BCM_IF_ERROR_RETURN
  11089                 (_bcm_th_cosq_index_resolve
  11090                  (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11091                   NULL, &startq, NULL));
  11092         }
  11093 
  11094         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11095 
  11096         base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
  11097         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11098         if (type == bcmCosqControlEgressUCQueueLimitEnable) {
  11099             fld_name = Q_LIMIT_ENABLEf;
  11100         } else if (type == bcmCosqControlEgressUCQueueColorLimitEnable) {
  11101             fld_name = Q_COLOR_ENABLE_CELLf;
  11102         }
  11103         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11104         enable = soc_mem_field32_get(unit, mem, entry, fld_name);
  11105         if (enable != arg) {
  11106             soc_mem_field32_set(unit, mem, entry, fld_name, arg);
  11107             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11108         }
  11109     } else if (type == bcmCosqControlEgressMCQueueLimitEnable) {
  11110         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11111             return BCM_E_PARAM;
  11112         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11113             BCM_IF_ERROR_RETURN
  11114                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  11115                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11116                                             &local_port, &startq, NULL));
  11117         } else {
  11118             if (cosq < 0) {
  11119                 return BCM_E_PARAM;
  11120             }
  11121             BCM_IF_ERROR_RETURN
  11122                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11123             if (local_port < 0) {
  11124                 return BCM_E_PORT;
  11125             }
  11126             BCM_IF_ERROR_RETURN
  11127                 (_bcm_th_cosq_index_resolve(unit, local_port, cosq,
  11128                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11129                                             NULL, &startq, NULL));
  11130         }
  11131 
  11132         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11133 
  11134         base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
  11135         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11136         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11137         enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
  11138         if (enable != arg) {
  11139             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg);
  11140             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11141         }
  11142 
  11143         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
  11144         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11145         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11146         enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
  11147         if (enable != arg) {
  11148             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg);
  11149             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11150         }
  11151     } else if (type == bcmCosqControlEgressMCQueueColorLimitEnable) {
  11152         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11153             return BCM_E_PARAM;
  11154         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11155             BCM_IF_ERROR_RETURN
  11156                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  11157                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11158                                             &local_port, &startq, NULL));
  11159         } else {
  11160             if (cosq < 0) {
  11161                 return BCM_E_PARAM;
  11162             }
  11163             BCM_IF_ERROR_RETURN
  11164                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11165             if (local_port < 0) {
  11166                 return BCM_E_PORT;
  11167             }
  11168             BCM_IF_ERROR_RETURN
  11169                 (_bcm_th_cosq_index_resolve(unit, local_port, cosq,
  11170                                             _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11171                                             NULL, &startq, NULL));
  11172         }
  11173 
  11174         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11175 
  11176         base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
  11177         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11178         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11179         enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf);
  11180         if (enable != arg) {
  11181             soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf, arg);
  11182             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11183         }
  11184 
  11185         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
  11186         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11187         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11188         enable = soc_mem_field32_get(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf);
  11189         if (enable != arg) {
  11190             soc_mem_field32_set(unit, mem, entry, Q_COLOR_LIMIT_ENABLEf, arg);
  11191             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11192         }
  11193     } else {
  11194         return BCM_E_PARAM;
  11195     }
  11196 
  11197     return BCM_E_NONE;
  11198 }
  11199 
  11200 STATIC int
  11201 _bcm_th_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport,
  11202                                          bcm_cos_queue_t cosq,
  11203                                          bcm_cosq_control_t type,
  11204                                          int *arg)
  11205 {
  11206     bcm_port_t local_port;
  11207     int startq, pipe;
  11208     uint32 entry[SOC_MAX_MEM_WORDS];
  11209     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
  11210     soc_field_t field_name = INVALIDf;
  11211 
  11212     if ((type == bcmCosqControlEgressUCQueueLimitEnable) ||
  11213         (type == bcmCosqControlEgressUCQueueColorLimitEnable)) {
  11214         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11215             BCM_IF_ERROR_RETURN
  11216                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  11217                                           _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11218                                           &local_port, &startq, NULL));
  11219         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11220             return BCM_E_PARAM;
  11221         } else {
  11222             if (cosq < 0) {
  11223                 return BCM_E_PARAM;
  11224             }
  11225             BCM_IF_ERROR_RETURN
  11226                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11227             if (local_port < 0) {
  11228                 return BCM_E_PORT;
  11229             }
  11230             BCM_IF_ERROR_RETURN
  11231                 (_bcm_th_cosq_index_resolve
  11232                     (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11233                     NULL, &startq, NULL));
  11234         }
  11235 
  11236         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11237 
  11238         base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
  11239         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11240         if (type == bcmCosqControlEgressUCQueueLimitEnable) {
  11241             field_name = Q_LIMIT_ENABLEf;
  11242         } else if (type == bcmCosqControlEgressUCQueueColorLimitEnable) {
  11243             field_name = Q_COLOR_ENABLE_CELLf;
  11244         }
  11245         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11246         *arg = soc_mem_field32_get(unit, mem, entry, field_name);
  11247     } else if ((type == bcmCosqControlEgressMCQueueLimitEnable) ||
  11248                (type == bcmCosqControlEgressMCQueueColorLimitEnable)) {
  11249         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11250             return BCM_E_PARAM;
  11251         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11252             BCM_IF_ERROR_RETURN
  11253                 (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  11254                                      _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11255                                      &local_port, &startq, NULL));
  11256         } else {
  11257             if (cosq < 0) {
  11258                 return BCM_E_PARAM;
  11259             }
  11260             BCM_IF_ERROR_RETURN
  11261                 (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11262             if (local_port < 0) {
  11263                 return BCM_E_PORT;
  11264             }
  11265             BCM_IF_ERROR_RETURN
  11266                 (_bcm_th_cosq_index_resolve(unit, local_port, cosq,
  11267                                     _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  11268                                      NULL, &startq, NULL));
  11269         }
  11270         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11271 
  11272         base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
  11273         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11274 
  11275         if (type == bcmCosqControlEgressMCQueueLimitEnable) {
  11276            base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
  11277            mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11278            field_name = Q_LIMIT_ENABLEf;
  11279         } else if (type == bcmCosqControlEgressMCQueueColorLimitEnable) {
  11280            base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
  11281            mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11282            field_name = Q_COLOR_LIMIT_ENABLEf;
  11283         }
  11284 
  11285         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11286         *arg = soc_mem_field32_get(unit, mem, entry, field_name);
  11287     } else {
  11288         return BCM_E_PARAM;
  11289     }
  11290     return BCM_E_NONE;
  11291 }
  11292 
  11293 /*
  11294  * This function is used to get ingress pool
  11295  * limit given Ingress [Port, Priority]
  11296  */
  11297 STATIC int
  11298 _bcm_th_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq,
  11299                                bcm_cosq_buffer_id_t buffer, 
  11300                                bcm_cosq_control_t type, int *arg)
  11301 {
  11302     uint32 rval = 0x0;
  11303     int pool;
  11304     int local_port, pipe, layer, xpe;
  11305     soc_reg_t reg = INVALIDr;
  11306     soc_field_t fld_limit = INVALIDf;
  11307 
  11308     if (arg == NULL) {
  11309         return BCM_E_PARAM;
  11310     }
  11311 
  11312     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11313         BCM_GPORT_IS_SCHEDULER(gport) ||
  11314         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11315         return BCM_E_PARAM;
  11316     }
  11317 
  11318     BCM_IF_ERROR_RETURN
  11319             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11320 
  11321     if (!SOC_PORT_VALID(unit, local_port)) {
  11322         return BCM_E_PORT;
  11323     }
  11324 
  11325     if (type == bcmCosqControlIngressPoolLimitBytes ||
  11326         type == bcmCosqControlIngressPoolResetOffsetLimitBytes) {
  11327         BCM_IF_ERROR_RETURN
  11328             (_bcm_th_cosq_ing_pool_get(unit, gport, cosq,
  11329                                        bcmCosqControlIngressPool,
  11330                                        &pool));
  11331         if (type == bcmCosqControlIngressPoolLimitBytes) {
  11332             reg = THDI_BUFFER_CELL_LIMIT_SPr;
  11333             fld_limit = LIMITf;
  11334         } else { /* bcmCosqControlIngressPoolResetOffsetLimitBytes */
  11335             reg = THDI_CELL_RESET_LIMIT_OFFSET_SPr;
  11336             fld_limit = OFFSETf;
  11337         }
  11338     } else if (type == bcmCosqControlIngressHeadroomPoolLimitBytes) {
  11339         BCM_IF_ERROR_RETURN
  11340             (_bcm_th_cosq_ing_pool_get(unit, gport, cosq,
  11341                                        bcmCosqControlIngressHeadroomPool,
  11342                                        &pool));
  11343         reg = THDI_HDRM_BUFFER_CELL_LIMIT_HPr;
  11344         fld_limit = LIMITf;
  11345     } else if (type == bcmCosqControlIngressPublicPoolLimitBytes) {
  11346         pool = -1;
  11347         reg = THDI_BUFFER_CELL_LIMIT_PUBLIC_POOLr;
  11348         fld_limit = LIMITf;
  11349     } else {
  11350         return BCM_E_PARAM;
  11351     }
  11352 
  11353     SOC_IF_ERROR_RETURN(
  11354         soc_port_pipe_get(unit, local_port, &pipe));
  11355     SOC_IF_ERROR_RETURN(
  11356         soc_tomahawk_mmu_layer_get(unit, pipe, &layer));
  11357     
  11358     if (buffer == BCM_COSQ_BUFFER_ID_INVALID) {
  11359         xpe = -1;
  11360     } else if (SOC_INFO(unit).ipipe_xpe_map[pipe] & (1 << buffer)) {
  11361         xpe = buffer;
  11362     } else {
  11363         return BCM_E_PARAM;
  11364     }
  11365     
  11366     SOC_IF_ERROR_RETURN(
  11367         soc_tomahawk_xpe_reg32_get(unit,reg,
  11368                                    xpe, layer, pool, &rval));
  11369     *arg = soc_reg_field_get(unit, reg, rval, fld_limit);
  11370 
  11371     *arg *= _TH_MMU_BYTES_PER_CELL;
  11372 
  11373     return BCM_E_NONE;
  11374 }
  11375 
  11376 /*
  11377  * This function is used to set ingress pool
  11378  * limit given Ingress [Port, Priority]
  11379  */
  11380 STATIC int
  11381 _bcm_th_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq,
  11382                                bcm_cosq_buffer_id_t buffer,
  11383                                bcm_cosq_control_t type, int arg)
  11384 {
  11385     uint32 rval = 0x0;
  11386     int pool;
  11387     int local_port, pipe, layer, xpe;
  11388     soc_reg_t reg = INVALIDr;
  11389     soc_field_t fld_limit = INVALIDf;
  11390     int max_value;
  11391     int pool_limit = 0;
  11392     int headroom_limit = 0;
  11393     int public_limit = 0;
  11394     int total_limit = 0;
  11395     int mmu_total_cells = 0;
  11396 
  11397     if (arg < 0) {
  11398         return BCM_E_PARAM;
  11399     }
  11400 
  11401     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
  11402         BCM_GPORT_IS_SCHEDULER(gport) ||
  11403         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11404         return BCM_E_PARAM;
  11405     }
  11406     BCM_IF_ERROR_RETURN
  11407             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11408 
  11409     if (!SOC_PORT_VALID(unit, local_port)) {
  11410         return BCM_E_PORT;
  11411     }
  11412 
  11413     BCM_IF_ERROR_RETURN(_bcm_th_cosq_ing_res_limit_get(
  11414         unit, gport, cosq, buffer,
  11415         bcmCosqControlIngressPoolLimitBytes, &pool_limit));
  11416     BCM_IF_ERROR_RETURN(_bcm_th_cosq_ing_res_limit_get(
  11417         unit, gport, cosq, buffer,
  11418         bcmCosqControlIngressHeadroomPoolLimitBytes, &headroom_limit));
  11419     BCM_IF_ERROR_RETURN(_bcm_th_cosq_ing_res_limit_get(
  11420         unit, gport, cosq, buffer,
  11421         bcmCosqControlIngressPublicPoolLimitBytes, &public_limit));
  11422 
  11423     if (type == bcmCosqControlIngressPoolLimitBytes ||
  11424         type == bcmCosqControlIngressPoolResetOffsetLimitBytes) {
  11425         BCM_IF_ERROR_RETURN
  11426             (_bcm_th_cosq_ing_pool_get(unit, gport, cosq,
  11427                                        bcmCosqControlIngressPool,
  11428                                        &pool));
  11429         if (type == bcmCosqControlIngressPoolLimitBytes) {
  11430             reg = THDI_BUFFER_CELL_LIMIT_SPr;
  11431             fld_limit = LIMITf;
  11432             total_limit = arg + headroom_limit + public_limit;
  11433         } else { /* bcmCosqControlIngressPoolResetOffsetLimitBytes */
  11434             reg = THDI_CELL_RESET_LIMIT_OFFSET_SPr;
  11435             fld_limit = OFFSETf;
  11436         }
  11437 #ifdef BCM_TOMAHAWK2_SUPPORT
  11438         if (SOC_IS_TOMAHAWK2(unit)) {
  11439             max_value = _TH2_THDI_BUFFER_CELL_LIMIT_SP_MAX;
  11440         } else
  11441 #endif
  11442 #ifdef BCM_TOMAHAWKPLUS_SUPPORT
  11443         if (SOC_IS_TOMAHAWKPLUS(unit)) {
  11444             max_value = _THP_THDI_BUFFER_CELL_LIMIT_SP_MAX;
  11445         } else
  11446 #endif
  11447         {
  11448             max_value = _TH_THDI_BUFFER_CELL_LIMIT_SP_MAX;
  11449         }
  11450     } else if (type == bcmCosqControlIngressHeadroomPoolLimitBytes) {
  11451         BCM_IF_ERROR_RETURN
  11452             (_bcm_th_cosq_ing_pool_get(unit, gport, cosq,
  11453                                        bcmCosqControlIngressHeadroomPool,
  11454                                        &pool));
  11455         reg = THDI_HDRM_BUFFER_CELL_LIMIT_HPr;
  11456         fld_limit = LIMITf;
  11457         total_limit = arg + pool_limit + public_limit;
  11458 #ifdef BCM_TOMAHAWK2_SUPPORT
  11459         if (SOC_IS_TOMAHAWK2(unit)) {
  11460             max_value = _TH2_THDI_HDRM_BUFFER_CELL_LIMIT_HP_MAX;
  11461         } else
  11462 #endif
  11463 #ifdef BCM_TOMAHAWKPLUS_SUPPORT
  11464         if (SOC_IS_TOMAHAWKPLUS(unit)) {
  11465             max_value = _THP_THDI_HDRM_BUFFER_CELL_LIMIT_HP_MAX;
  11466         } else
  11467 #endif
  11468         {
  11469             max_value = _TH_THDI_HDRM_BUFFER_CELL_LIMIT_HP_MAX;
  11470         }
  11471     } else if (type == bcmCosqControlIngressPublicPoolLimitBytes) {
  11472         reg = THDI_BUFFER_CELL_LIMIT_PUBLIC_POOLr;
  11473         fld_limit = LIMITf;
  11474         total_limit = arg + pool_limit + headroom_limit;
  11475 #ifdef BCM_TOMAHAWK2_SUPPORT
  11476         if (SOC_IS_TOMAHAWK2(unit)) {
  11477             max_value = _TH2_THDI_BUFFER_CELL_LIMIT_SP_MAX;
  11478         } else
  11479 #endif
  11480 #ifdef BCM_TOMAHAWKPLUS_SUPPORT
  11481         if (SOC_IS_TOMAHAWKPLUS(unit)) {
  11482             max_value = _THP_THDI_BUFFER_CELL_LIMIT_SP_MAX;
  11483         } else
  11484 #endif
  11485         {
  11486             max_value = _TH_THDI_BUFFER_CELL_LIMIT_SP_MAX;
  11487         }
  11488     } else {
  11489         return BCM_E_PARAM;
  11490     }
  11491 
  11492     arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL;
  11493     if (arg > max_value) {
  11494        LOG_WARN(BSL_LS_BCM_COSQ,
  11495            (BSL_META_U(unit, "Warning: Request of %d bytes exceeds maximum of %d bytes\n"),
  11496             arg * _TH_MMU_BYTES_PER_CELL,
  11497            max_value * _TH_MMU_BYTES_PER_CELL));
  11498         return BCM_E_PARAM;
  11499     }
  11500     total_limit = (total_limit + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL;
  11501 #ifdef BCM_TOMAHAWK2_SUPPORT
  11502     if (SOC_IS_TOMAHAWK2(unit)) {
  11503         mmu_total_cells = _TH2_MMU_TOTAL_CELLS_PER_XPE;
  11504     } else
  11505 #endif
  11506 #ifdef BCM_TOMAHAWKPLUS_SUPPORT
  11507     if (SOC_IS_TOMAHAWKPLUS(unit)) {
  11508         mmu_total_cells = _THP_MMU_TOTAL_CELLS_PER_XPE;
  11509     } else
  11510 #endif
  11511     {
  11512         mmu_total_cells = _TH_MMU_TOTAL_CELLS_PER_XPE;
  11513     }
  11514     if (total_limit > mmu_total_cells) {
  11515        LOG_WARN(BSL_LS_BCM_COSQ,
  11516            (BSL_META_U(unit, "Warning: Total allocation of %d bytes exceeds maximum of %d bytes\n"),
  11517             total_limit * _TH_MMU_BYTES_PER_CELL,
  11518            mmu_total_cells * _TH_MMU_BYTES_PER_CELL));
  11519         return BCM_E_PARAM;
  11520     }
  11521 
  11522     soc_reg_field_set(unit, reg, &rval, fld_limit, arg);
  11523     SOC_IF_ERROR_RETURN(
  11524         soc_port_pipe_get(unit, local_port, &pipe));
  11525     SOC_IF_ERROR_RETURN(
  11526         soc_tomahawk_mmu_layer_get(unit, pipe, &layer));
  11527     
  11528     if (buffer == BCM_COSQ_BUFFER_ID_INVALID) {
  11529         xpe = -1;
  11530     } else if (SOC_INFO(unit).ipipe_xpe_map[pipe] & (1 << buffer)) {
  11531         xpe = buffer;
  11532     } else {
  11533         return BCM_E_PARAM;
  11534     }
  11535 
  11536     SOC_IF_ERROR_RETURN(
  11537         soc_tomahawk_xpe_reg32_set(unit, reg,
  11538                                    xpe, layer, pool, rval));
  11539 
  11540     if (type == bcmCosqControlIngressPoolLimitBytes) {
  11541         int xpe_map = 0;
  11542         if (xpe == -1) {
  11543             xpe_map = SOC_INFO(unit).ipipe_xpe_map[pipe];
  11544         } else {
  11545             xpe_map = 1 << xpe;
  11546         }
  11547         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
  11548             if (xpe_map & (1 << xpe)) {
  11549                 _BCM_TH_MMU_INFO(unit)->ing_shared_limit[xpe] = arg;
  11550             }
  11551         }
  11552     }
  11553     return BCM_E_NONE;
  11554 }
  11555 
  11556 /*
  11557  * This function is used to set enables
  11558  * for Qgroup Min and Shared Limits for a given Egress Unicast Queue
  11559  */
  11560 STATIC int
  11561 _bcm_th_cosq_qgroup_limit_enables_set(int unit, bcm_gport_t gport,
  11562                                bcm_cos_t cosq, bcm_cosq_control_t type,
  11563                                int arg)
  11564 {
  11565     bcm_port_t local_port;
  11566     int startq=0, pipe=0, count=1, lc=0, to_cos=0;
  11567     uint32 entry[SOC_MAX_MEM_WORDS], entry2[SOC_MAX_MEM_WORDS];
  11568     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
  11569     int enable;
  11570     int valid;
  11571     soc_field_t field = INVALIDf;
  11572     soc_field_t field2 = INVALIDf;
  11573     int new_shared_limit_cell, egr_qe_shd_size[_TH_XPES_PER_DEV], egr_db_shd_size[_TH_XPES_PER_DEV];
  11574     int rv;
  11575     int xpe, temp_val, pipe2=-1;
  11576     uint32 pipe_map;
  11577     soc_info_t *si=&SOC_INFO(unit);
  11578 
  11579     if (arg < 0) {
  11580         return BCM_E_PARAM;
  11581     }
  11582     arg = arg ? 1 : 0;
  11583 
  11584     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11585         BCM_IF_ERROR_RETURN
  11586             (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  11587                                         _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11588                                         &local_port, &startq, NULL));
  11589     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11590         return BCM_E_PARAM;
  11591     } else {
  11592         if (cosq < -1) {
  11593             return BCM_E_PARAM;
  11594         }
  11595         BCM_IF_ERROR_RETURN
  11596             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11597         if (local_port < 0) {
  11598             return BCM_E_PORT;
  11599         }
  11600         BCM_IF_ERROR_RETURN
  11601             (_bcm_th_cosq_index_resolve
  11602              (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11603               NULL, &startq, &count));
  11604     }
  11605 
  11606     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11607     base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
  11608     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11609     if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) {
  11610        field = QGROUP_LIMIT_ENABLEf;
  11611        field2 = QGROUP_VALIDf;
  11612     } else if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
  11613         field = USE_QGROUP_MINf;
  11614         field2 = QGROUP_VALIDf;
  11615     } else {
  11616         return BCM_E_PARAM;
  11617     }
  11618 
  11619     to_cos = startq + count;
  11620     for (lc = startq; lc < to_cos; lc++) {
  11621         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 
  11622                     lc, entry));
  11623         enable = soc_mem_field32_get(unit, mem, entry, field);
  11624         if (enable != arg) {
  11625             soc_mem_field32_set(unit, mem, entry, field, arg);
  11626             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
  11627                         lc, entry));
  11628         }
  11629         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  11630                     lc, entry2));
  11631         valid = soc_mem_field32_get(unit, mem, entry2, field2);
  11632         if (valid != 1) {
  11633             soc_mem_field32_set(unit, mem, entry2, field2, 1);
  11634             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
  11635                         lc, entry2));
  11636         }
  11637     }
  11638 
  11639     /*If qgroup min limit enable is being set, 
  11640      *buffer shared limits need to be recalculated
  11641      */
  11642     if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
  11643         sal_memcpy(egr_db_shd_size, _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, 
  11644             sizeof(egr_db_shd_size));
  11645         sal_memcpy(egr_qe_shd_size, _BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit, 
  11646             sizeof(egr_qe_shd_size));
  11647         /*Calculate the new value of shared limit*/
  11648         soc_th_recalc_new_egress_shared_limit(unit, pipe,
  11649                 &new_shared_limit_cell);
  11650         /*Getting the two egress pipes with the new value of shared limit*/
  11651         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
  11652             pipe_map = si->xpe_epipe_map[xpe];
  11653             if (pipe_map & (1 << pipe)) {
  11654                 count = 0;
  11655                while(pipe_map) {
  11656                     temp_val = (pipe_map >> 1);
  11657                     if ((temp_val != 0) && (count != pipe)) {
  11658                         pipe2=count;
  11659                         break;
  11660                     }
  11661                     count++;
  11662                }
  11663             }
  11664         }
  11665         /*Assign new value to both xpes for the egress pipe*/
  11666         egr_db_shd_size[pipe] = new_shared_limit_cell;
  11667         if (pipe2!=-1) {
  11668             egr_db_shd_size[pipe2] = new_shared_limit_cell;
  11669         }
  11670         /*Passing the modified values to the funtion to re-adjust shared limits*/
  11671         rv = soc_th_mmu_config_res_limits_update(unit, 2 /* egr */, NULL,
  11672                                                      egr_db_shd_size,
  11673                                                      egr_qe_shd_size, 1);
  11674         if (rv < 0) {
  11675             return rv;
  11676         }
  11677         sal_memcpy( _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit,egr_db_shd_size,
  11678             sizeof(egr_db_shd_size));
  11679     }
  11680     return BCM_E_NONE;
  11681 }
  11682 
  11683 /*
  11684  * This function is used to get enables
  11685  * for Qgroup Min and Shared Limits for a given Egress Unicast Queue
  11686  */
  11687 STATIC int
  11688 _bcm_th_cosq_qgroup_limit_enables_get(int unit, bcm_gport_t gport,
  11689                                          bcm_cos_queue_t cosq,
  11690                                          bcm_cosq_control_t type,
  11691                                          int *arg)
  11692 {
  11693     bcm_port_t local_port;
  11694     int startq, pipe;
  11695     uint32 entry[SOC_MAX_MEM_WORDS];
  11696     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
  11697     soc_field_t field = INVALIDf;
  11698     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11699         BCM_IF_ERROR_RETURN
  11700             (_bcm_th_cosq_index_resolve(unit, gport, cosq,
  11701                                       _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11702                                       &local_port, &startq, NULL));
  11703     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11704         return BCM_E_PARAM;
  11705     } else {
  11706         if (cosq < 0) {
  11707             return BCM_E_PARAM;
  11708         }
  11709         BCM_IF_ERROR_RETURN
  11710             (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11711         if (local_port < 0) {
  11712             return BCM_E_PORT;
  11713         }
  11714         BCM_IF_ERROR_RETURN
  11715             (_bcm_th_cosq_index_resolve
  11716                 (unit, local_port, cosq, _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  11717                 NULL, &startq, NULL));
  11718     }
  11719     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11720     base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
  11721     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11722     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  11723      if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
  11724         field = USE_QGROUP_MINf;
  11725     } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) {
  11726         field = QGROUP_LIMIT_ENABLEf;
  11727     } else {
  11728         return BCM_E_PARAM;
  11729     }
  11730         *arg = soc_mem_field32_get(unit, mem, entry, field);
  11731     return BCM_E_NONE;
  11732 }
  11733 
  11734 /*
  11735  * This function is used to set limits
  11736  * for Qgroup Min and Shared Limits for a given Egress Unicast Queue
  11737  */
  11738 STATIC int
  11739 _bcm_th_cosq_qgroup_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq,
  11740                                bcm_cosq_control_t type, int arg)
  11741 {
  11742     bcm_port_t local_port;
  11743     int phy_port, pipe;
  11744     uint32 entry[SOC_MAX_MEM_WORDS];
  11745     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
  11746     soc_field_t field = INVALIDf;
  11747     int mmu_port; /* global mmu port number */
  11748     int local_mmu_port; /* local mmu port number - local to per pipe */
  11749     soc_info_t *si;
  11750     int granularity;
  11751     int egr_db_shd_size[_TH_XPES_PER_DEV], egr_qe_shd_size[_TH_XPES_PER_DEV], cur_val;
  11752     int rv, xpe;
  11753     int delta[_TH_XPES_PER_DEV] = {0};
  11754     int max_val;
  11755     uint32 xpe_map;
  11756     si = &SOC_INFO(unit);
  11757 
  11758     if (cosq < 0) {
  11759         return BCM_E_PARAM;
  11760     }
  11761     BCM_IF_ERROR_RETURN
  11762         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11763     if (local_port < 0) {
  11764         return BCM_E_PORT;
  11765     }
  11766 
  11767     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes ||
  11768             type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) {
  11769         arg = (arg + _TH_MMU_BYTES_PER_CELL - 1) / _TH_MMU_BYTES_PER_CELL;
  11770     }
  11771 
  11772     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11773     phy_port = si->port_l2p_mapping[local_port];
  11774     mmu_port = si->port_p2m_mapping[phy_port];
  11775     local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1);
  11776     base_mem = MMU_THDU_CONFIG_QGROUPm;
  11777     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11778     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, local_mmu_port,
  11779                 entry));
  11780 
  11781     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) {
  11782         field = Q_MIN_LIMIT_CELLf;
  11783         granularity =1;
  11784         /* Recalculate Shared Values if Min Changed */
  11785         sal_memcpy(egr_db_shd_size, _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit, 
  11786              sizeof(egr_db_shd_size));
  11787         sal_memcpy(egr_qe_shd_size, _BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit, 
  11788              sizeof(egr_qe_shd_size));
  11789 
  11790         cur_val = soc_mem_field32_get(unit, mem, entry, field);
  11791         /* adjustment delta */
  11792         xpe_map = SOC_INFO(unit).epipe_xpe_map[pipe];
  11793         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
  11794             if (xpe_map & (1 << xpe)) {
  11795                 delta[xpe] = ((arg / granularity) - cur_val) * granularity;
  11796             }
  11797         }
  11798         /* shared limits to be increased/decreased */
  11799         for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) {
  11800             if ((xpe_map & (1 << xpe)) && (delta[xpe] > 0)) {
  11801                 /* no space to decrease shared limit */
  11802                 if (delta[xpe] > egr_db_shd_size[xpe]) {
  11803                     return BCM_E_PARAM;
  11804                 }
  11805                 egr_db_shd_size[xpe] -= delta[xpe];
  11806             }
  11807             if ((xpe_map & (1 << xpe)) && (delta[xpe] < 0)) {
  11808                 egr_db_shd_size[xpe] -= delta[xpe];
  11809             }
  11810         }
  11811 
  11812         rv = soc_th_mmu_config_res_limits_update(unit, 2 /* egr */, NULL,
  11813                                                      egr_db_shd_size ,
  11814                                                      egr_qe_shd_size, 1);
  11815         if (rv < 0) {
  11816             return rv;
  11817         }
  11818 
  11819         sal_memcpy(_BCM_TH_MMU_INFO(unit)->egr_db_shared_limit,egr_db_shd_size,
  11820              sizeof(egr_db_shd_size));
  11821     } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) {
  11822         field = Q_SHARED_LIMIT_CELLf;
  11823         granularity = 1;
  11824     } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) {
  11825         field = Q_LIMIT_DYNAMIC_CELLf;
  11826         granularity = 1;
  11827     } else {
  11828         return BCM_E_PARAM;
  11829     }
  11830 
  11831     /* Check for min/max values */
  11832     max_val = (1 << soc_mem_field_length(unit, mem, field)) - 1;
  11833     if ((arg < 0) || ((arg/granularity) > max_val)) {
  11834         return BCM_E_PARAM;
  11835     } else {
  11836         soc_mem_field32_set(unit, mem, entry, field, (arg/granularity));
  11837     }
  11838     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, local_mmu_port,
  11839                 entry));
  11840     return BCM_E_NONE;
  11841 }
  11842 
  11843 /*
  11844  * This function is used to get limits
  11845  * for Qgroup Min and Shared Limits for a given Egress Unicast Queue
  11846  */
  11847 
  11848 STATIC int
  11849 _bcm_th_cosq_qgroup_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq,
  11850                                bcm_cosq_control_t type, int *arg)
  11851 {
  11852     bcm_port_t local_port;
  11853     int phy_port, pipe;
  11854     uint32 entry[SOC_MAX_MEM_WORDS];
  11855     soc_mem_t mem = INVALIDm, base_mem = INVALIDm ;
  11856     soc_field_t field = INVALIDf;
  11857     int mmu_port; /* global mmu port number */
  11858     int local_mmu_port; /* local mmu port number - local to per pipe */
  11859     soc_info_t *si;
  11860     si = &SOC_INFO(unit);
  11861     if (cosq < 0) {
  11862         return BCM_E_PARAM;
  11863     }
  11864     BCM_IF_ERROR_RETURN
  11865         (_bcm_th_cosq_localport_resolve(unit, gport, &local_port));
  11866     if (local_port < 0) {
  11867         return BCM_E_PORT;
  11868     }
  11869     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  11870     phy_port = si->port_l2p_mapping[local_port];
  11871     mmu_port = si->port_p2m_mapping[phy_port];
  11872     local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1);
  11873     base_mem = MMU_THDU_CONFIG_QGROUPm;
  11874     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
  11875     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, local_mmu_port,
  11876                 entry));
  11877     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) {
  11878        field = Q_MIN_LIMIT_CELLf;
  11879     } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) {
  11880         field = Q_SHARED_LIMIT_CELLf;
  11881     } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) {
  11882         field = Q_LIMIT_DYNAMIC_CELLf;
  11883     } else {
  11884         return BCM_E_PARAM;
  11885     }
  11886     *arg = soc_mem_field32_get(unit, mem, entry, field);
  11887     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes ||
  11888             type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) {
  11889         *arg = (*arg) * _TH_MMU_BYTES_PER_CELL;
  11890     }
  11891     return BCM_E_NONE;
  11892 }
  11893 
  11894 int
  11895 bcm_th_cosq_priority_mapping_get_all(int unit, bcm_gport_t gport, int index,
  11896                                      bcm_cosq_priority_mapping_t type,
  11897                                      int pri_max, int *pri_array,
  11898                                      int *pri_count)
  11899 {
  11900     bcm_port_t port;
  11901     int i, pg, sp, count = 0;
  11902 
  11903     BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, gport, &port));
  11904     if (!SOC_PORT_VALID(unit, port)) {
  11905         return BCM_E_PORT;
  11906     }
  11907 
  11908     switch (type) {
  11909         case bcmCosqPriorityGroup:
  11910             if ((index < TH_PRIOROTY_GROUP_ID_MIN) ||
  11911                 (index > TH_PRIOROTY_GROUP_ID_MAX)) {
  11912                 return BCM_E_PARAM;
  11913             }
  11914             for (i = 0; i < 16; i++) {
  11915                 BCM_IF_ERROR_RETURN
  11916                     (bcm_th_port_priority_group_mapping_get(unit, gport,
  11917                                                         i, &pg));
  11918                 if (pg == index) {
  11919                     if (pri_max != 0 && pri_array != NULL) {
  11920                         if (count < pri_max) {
  11921                             pri_array[count] = i;
  11922                         }
  11923                     }
  11924                     count++;
  11925                 }
  11926             }
  11927             break;
  11928         case bcmCosqIngressPool:
  11929             if ((index < 0) || (index >= _TH_MMU_NUM_POOL)) {
  11930                 return BCM_E_PARAM;
  11931             }
  11932             for (i = 0; i < 16; i++) {
  11933                 BCM_IF_ERROR_RETURN
  11934                     (_bcm_th_cosq_ing_pool_get(unit, gport, i,
  11935                                                bcmCosqControlIngressPool,
  11936                                                &sp));
  11937                 if (sp == index) {
  11938                     if (pri_max != 0 && pri_array != NULL) {
  11939                         if (count < pri_max) {
  11940                             pri_array[count] = i;
  11941                         }
  11942                     }
  11943                     count++;
  11944                 }
  11945             }
  11946             break;
  11947         default:
  11948             return BCM_E_UNAVAIL;
  11949     }
  11950 
  11951     if ((count < pri_max) && (pri_array != NULL)) {
  11952         for (i = count; i < pri_max; i++) {
  11953             pri_array[i] = -1;
  11954         }
  11955         *pri_count = count;
  11956     } else if (pri_max == 0) {
  11957         *pri_count = count;
  11958     } else {
  11959         *pri_count = pri_max;
  11960     } 
  11961     return BCM_E_NONE; 
  11962 }
  11963 
  11964 /*
  11965  * Function:
  11966  *      bcm_th_cosq_control_set
  11967  * Purpose:
  11968  *      Set specified feature configuration
  11969  *
  11970  * Parameters:
  11971  *      unit - (IN) Unit number.
  11972  *      port - (IN) GPORT ID.
  11973  *      cosq - (IN) COS queue.
  11974  *      buffer-(IN) XPE ID
  11975  *      type - (IN) feature
  11976  *      arg  - (IN) feature value
  11977  * Returns:
  11978  *      BCM_E_XXX
  11979  * Notes:
  11980  */
  11981 int
  11982 bcm_th_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  11983                         bcm_cosq_buffer_id_t buffer,
  11984                         bcm_cosq_control_t type, int arg)
  11985 {
  11986     uint32 kbits_burst_min, kbits_burst_max;
  11987     uint32 kbits_burst;
  11988 
  11989     kbits_burst_min = 0;
  11990     kbits_burst_max = 0;
  11991 
  11992     COMPILER_REFERENCE(kbits_burst_min);
  11993     COMPILER_REFERENCE(kbits_burst_max);
  11994 
  11995     switch (type) {
  11996         case bcmCosqControlBandwidthBurstMax:
  11997             kbits_burst = arg & 0x7fffffff; /* Convert to uint32  */
  11998             BCM_IF_ERROR_RETURN
  11999                 (bcm_th_cosq_gport_bandwidth_burst_get(unit, gport, cosq,
  12000                                                        &kbits_burst_min,
  12001                                                        &kbits_burst_max));
  12002             return bcm_th_cosq_gport_bandwidth_burst_set(unit, gport, cosq,
  12003                                                          kbits_burst_min,
  12004                                                          kbits_burst);
  12005         case bcmCosqControlBandwidthBurstMin:
  12006             kbits_burst = arg & 0x7fffffff; /* Convert to uint32  */
  12007             BCM_IF_ERROR_RETURN
  12008                 (bcm_th_cosq_gport_bandwidth_burst_get(unit, gport, cosq,
  12009                                                        &kbits_burst_min,
  12010                                                        &kbits_burst_max));
  12011             return bcm_th_cosq_gport_bandwidth_burst_set(unit, gport, cosq,
  12012                                                          kbits_burst,
  12013                                                          kbits_burst_max);
  12014         case bcmCosqControlEgressPool:
  12015         case bcmCosqControlEgressPoolLimitBytes:
  12016         case bcmCosqControlEgressPoolYellowLimitBytes:
  12017         case bcmCosqControlEgressPoolRedLimitBytes:
  12018         case bcmCosqControlEgressPoolLimitEnable:
  12019         case bcmCosqControlUCEgressPool:
  12020         case bcmCosqControlMCEgressPool:
  12021         case bcmCosqControlEgressPoolSharedLimitBytes:
  12022         case bcmCosqControlEgressPoolResumeLimitBytes:
  12023         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  12024         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  12025         case bcmCosqControlEgressPoolRedSharedLimitBytes:
  12026         case bcmCosqControlEgressPoolRedResumeLimitBytes:
  12027         case bcmCosqControlEgressPoolHighCongestionLimitBytes:
  12028         case bcmCosqControlEgressPoolLowCongestionLimitBytes:
  12029             return _bcm_th_cosq_egr_pool_set(unit, gport, cosq, buffer, type, arg);
  12030         case bcmCosqControlEgressUCQueueSharedLimitBytes:
  12031         case bcmCosqControlEgressMCQueueSharedLimitBytes:
  12032         case bcmCosqControlEgressUCQueueMinLimitBytes:
  12033         case bcmCosqControlEgressMCQueueMinLimitBytes:
  12034             return _bcm_th_cosq_egr_queue_set(unit, gport, cosq, type, arg);
  12035         case bcmCosqControlIngressPortPGSharedLimitBytes:
  12036         case bcmCosqControlIngressPortPGMinLimitBytes:
  12037         case bcmCosqControlIngressPortPoolMaxLimitBytes:
  12038         case bcmCosqControlIngressPortPoolMinLimitBytes:
  12039         case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  12040         case bcmCosqControlIngressPortPGResetFloorBytes:
  12041         case bcmCosqControlIngressPortPGResetOffsetBytes:
  12042         case bcmCosqControlIngressPortPoolResumeLimitBytes:
  12043             return _bcm_th_cosq_ing_res_set(unit, gport, cosq, type, arg);
  12044         case bcmCosqControlIngressPortPGGlobalHeadroomEnable:
  12045             return _bcm_th_cosq_ing_res_enable_set(unit, gport, cosq, type, arg);
  12046         case bcmCosqControlIngressPool:
  12047         case bcmCosqControlIngressHeadroomPool:
  12048             return _bcm_th_cosq_ing_pool_set(unit, gport, cosq, type, arg);
  12049         case bcmCosqControlDropLimitAlpha:
  12050             return _bcm_th_cosq_alpha_set(unit, gport, cosq,
  12051                                 (bcm_cosq_control_drop_limit_alpha_value_t)arg);
  12052         case bcmCosqControlIngressPortPGSharedDynamicEnable:
  12053         case bcmCosqControlEgressUCSharedDynamicEnable:
  12054         case bcmCosqControlEgressMCSharedDynamicEnable:
  12055             return _bcm_th_cosq_dynamic_thresh_enable_set(unit, gport, cosq,
  12056                                                           type, arg);
  12057         case bcmCosqControlEgressPortPoolYellowLimitBytes:
  12058         case bcmCosqControlEgressPortPoolRedLimitBytes:
  12059         case bcmCosqControlEgressPortPoolSharedLimitBytes:
  12060         case bcmCosqControlEgressPortPoolRedResumeBytes:
  12061         case bcmCosqControlEgressPortPoolYellowResumeBytes:
  12062         case bcmCosqControlEgressPortPoolSharedResumeBytes:
  12063             return _bcm_th_cosq_egr_port_pool_set(unit, gport, cosq, type, arg);
  12064         case bcmCosqControlEgressUCQueueLimitEnable:
  12065         case bcmCosqControlEgressMCQueueLimitEnable:
  12066         case bcmCosqControlEgressMCQueueColorLimitEnable:
  12067         case bcmCosqControlEgressUCQueueColorLimitEnable:
  12068             return _bcm_th_cosq_egr_queue_limit_enable_set(unit, gport, cosq,
  12069                                                            type, arg);
  12070         case bcmCosqControlIngressPoolLimitBytes:
  12071         case bcmCosqControlIngressPoolResetOffsetLimitBytes:
  12072         case bcmCosqControlIngressHeadroomPoolLimitBytes:
  12073         case bcmCosqControlIngressPublicPoolLimitBytes:
  12074             return _bcm_th_cosq_ing_res_limit_set(unit, gport, cosq, buffer, type, arg);
  12075         case bcmCosqControlEgressUCQueueGroupMinEnable:
  12076         case bcmCosqControlEgressUCQueueGroupSharedLimitEnable:
  12077             return _bcm_th_cosq_qgroup_limit_enables_set(unit, gport, cosq,
  12078                     type, arg);
  12079         case bcmCosqControlEgressUCQueueGroupMinLimitBytes:
  12080         case bcmCosqControlEgressUCQueueGroupSharedLimitBytes:
  12081         case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable:
  12082             return _bcm_th_cosq_qgroup_limit_set(unit, gport, cosq, type, arg);
  12083         case bcmCosqControlEgressUCQueueColorLimitDynamicEnable:
  12084         case bcmCosqControlEgressMCQueueColorLimitDynamicEnable:
  12085             return _bcm_th_cosq_egr_queue_color_limit_mode_set(unit, gport, cosq,
  12086                                                            type, arg);
  12087         case bcmCosqControlEgressUCQueueRedLimit:
  12088         case bcmCosqControlEgressUCQueueYellowLimit:
  12089         case bcmCosqControlEgressMCQueueRedLimit:
  12090         case bcmCosqControlEgressMCQueueYellowLimit:
  12091             return _bcm_th_cosq_egr_queue_color_limit_set(unit, gport, cosq, type, arg);
  12092 
  12093         default:
  12094             break;
  12095     }
  12096     return BCM_E_UNAVAIL;
  12097 }
  12098 
  12099 /*
  12100  * Function:
  12101  *      bcm_th_cosq_control_get
  12102  * Purpose:
  12103  *      Get specified feature configuration
  12104  *
  12105  * Parameters:
  12106  *      unit - (IN) Unit number.
  12107  *      port - (IN) GPORT ID.
  12108  *      cosq - (IN) COS queue.
  12109  *      buffer-(IN) XPE ID
  12110  *      type - (IN) feature
  12111  *      arg  - (OUT) feature value
  12112  * Returns:
  12113  *      BCM_E_XXX
  12114  * Notes:
  12115  */
  12116 int
  12117 bcm_th_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
  12118                         bcm_cosq_buffer_id_t buffer,
  12119                         bcm_cosq_control_t type, int *arg)
  12120 {
  12121     uint32 kburst_tmp, kbits_burst;
  12122 
  12123     switch (type) {
  12124         case bcmCosqControlBandwidthBurstMax:
  12125             BCM_IF_ERROR_RETURN
  12126                 (bcm_th_cosq_gport_bandwidth_burst_get(unit, gport, cosq,
  12127                                                        &kburst_tmp,
  12128                                                        &kbits_burst));
  12129             *arg = kbits_burst & 0x7fffffff; /* Convert to int  */
  12130             return BCM_E_NONE;
  12131 
  12132         case bcmCosqControlBandwidthBurstMin:
  12133             return bcm_th_cosq_gport_bandwidth_burst_get(unit, gport, cosq,
  12134                                                          (uint32*)arg,
  12135                                                          &kburst_tmp);
  12136         case bcmCosqControlEgressPool:
  12137         case bcmCosqControlEgressPoolLimitBytes:
  12138         case bcmCosqControlEgressPoolYellowLimitBytes:
  12139         case bcmCosqControlEgressPoolRedLimitBytes:
  12140         case bcmCosqControlEgressPoolLimitEnable:
  12141         case bcmCosqControlUCEgressPool:
  12142         case bcmCosqControlMCEgressPool:
  12143         case bcmCosqControlEgressPoolSharedLimitBytes:
  12144         case bcmCosqControlEgressPoolResumeLimitBytes:
  12145         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
  12146         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
  12147         case bcmCosqControlEgressPoolRedSharedLimitBytes:
  12148         case bcmCosqControlEgressPoolRedResumeLimitBytes:
  12149         case bcmCosqControlEgressPoolHighCongestionLimitBytes:
  12150         case bcmCosqControlEgressPoolLowCongestionLimitBytes:
  12151             return _bcm_th_cosq_egr_pool_get(unit, gport, cosq, buffer, type, arg);
  12152         case bcmCosqControlEgressUCQueueSharedLimitBytes:
  12153         case bcmCosqControlEgressMCQueueSharedLimitBytes:
  12154         case bcmCosqControlEgressUCQueueMinLimitBytes:
  12155         case bcmCosqControlEgressMCQueueMinLimitBytes:
  12156             return _bcm_th_cosq_egr_queue_get(unit, gport, cosq, type, arg);
  12157         case bcmCosqControlIngressPortPGSharedLimitBytes:
  12158         case bcmCosqControlIngressPortPGMinLimitBytes:
  12159         case bcmCosqControlIngressPortPoolMaxLimitBytes:
  12160         case bcmCosqControlIngressPortPoolMinLimitBytes:
  12161         case bcmCosqControlIngressPortPGHeadroomLimitBytes:
  12162         case bcmCosqControlIngressPortPGResetFloorBytes:
  12163         case bcmCosqControlIngressPortPGResetOffsetBytes:
  12164         case bcmCosqControlIngressPortPoolResumeLimitBytes:
  12165             return _bcm_th_cosq_ing_res_get(unit, gport, cosq, type, arg);
  12166         case bcmCosqControlIngressPortPGGlobalHeadroomEnable:
  12167             return _bcm_th_cosq_ing_res_enable_get(unit, gport, cosq, type, arg);
  12168         case bcmCosqControlIngressPool:
  12169         case bcmCosqControlIngressHeadroomPool:
  12170             return _bcm_th_cosq_ing_pool_get(unit, gport, cosq, type, arg);
  12171         case bcmCosqControlDropLimitAlpha:
  12172             return _bcm_th_cosq_alpha_get(unit, gport, cosq,
  12173                             (bcm_cosq_control_drop_limit_alpha_value_t *)arg);
  12174         case bcmCosqControlIngressPortPGSharedDynamicEnable:
  12175         case bcmCosqControlEgressUCSharedDynamicEnable:
  12176         case bcmCosqControlEgressMCSharedDynamicEnable:
  12177             return _bcm_th_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
  12178                                                           type, arg);
  12179         case bcmCosqControlEgressPortPoolYellowLimitBytes:
  12180         case bcmCosqControlEgressPortPoolRedLimitBytes:
  12181         case bcmCosqControlEgressPortPoolSharedLimitBytes:
  12182         case bcmCosqControlEgressPortPoolRedResumeBytes:
  12183         case bcmCosqControlEgressPortPoolYellowResumeBytes:
  12184         case bcmCosqControlEgressPortPoolSharedResumeBytes:
  12185             return _bcm_th_cosq_egr_port_pool_get(unit, gport, cosq, type, arg);
  12186         case bcmCosqControlEgressUCQueueLimitEnable:
  12187         case bcmCosqControlEgressMCQueueLimitEnable:
  12188         case bcmCosqControlEgressMCQueueColorLimitEnable:
  12189         case bcmCosqControlEgressUCQueueColorLimitEnable:
  12190             return _bcm_th_cosq_egr_queue_limit_enable_get(unit, gport, cosq,
  12191                                                            type, arg);
  12192         case bcmCosqControlIngressPoolLimitBytes:
  12193         case bcmCosqControlIngressPoolResetOffsetLimitBytes:
  12194         case bcmCosqControlIngressHeadroomPoolLimitBytes:
  12195         case bcmCosqControlIngressPublicPoolLimitBytes:
  12196             return _bcm_th_cosq_ing_res_limit_get(unit, gport, cosq, buffer, type, arg);
  12197         case bcmCosqControlEgressUCQueueGroupMinEnable:
  12198         case bcmCosqControlEgressUCQueueGroupSharedLimitEnable:
  12199             return _bcm_th_cosq_qgroup_limit_enables_get(unit, gport, cosq,
  12200                     type, arg);
  12201         case bcmCosqControlEgressUCQueueGroupMinLimitBytes:
  12202         case bcmCosqControlEgressUCQueueGroupSharedLimitBytes:
  12203         case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable:
  12204             return _bcm_th_cosq_qgroup_limit_get(unit, gport, cosq, type, arg);
  12205         case bcmCosqControlEgressUCQueueColorLimitDynamicEnable:
  12206         case bcmCosqControlEgressMCQueueColorLimitDynamicEnable:
  12207             return _bcm_th_cosq_egr_queue_color_limit_mode_get(unit, gport, cosq,
  12208                                                            type, arg);
  12209         case bcmCosqControlEgressUCQueueRedLimit:
  12210         case bcmCosqControlEgressUCQueueYellowLimit:
  12211         case bcmCosqControlEgressMCQueueRedLimit:
  12212         case bcmCosqControlEgressMCQueueYellowLimit:
  12213             return _bcm_th_cosq_egr_queue_color_limit_get(unit, gport, cosq, type, arg);
  12214 
  12215             default:
  12216             break;
  12217     }
  12218     return BCM_E_UNAVAIL;
  12219 }
  12220 
  12221 STATIC int
  12222 _bcm_th_cosq_obmhighwatermark_set(int unit, bcm_port_t port, uint64 value)
  12223 {
  12224     int pipe, obm_id, obm_max, lane;
  12225     soc_reg_t reg;
  12226     uint64 rval64;
  12227     soc_info_t *si;
  12228     soc_reg_t obm_high_watermark_reg[] = {
  12229         IDB_OBM0_MAX_USAGEr, IDB_OBM1_MAX_USAGEr,
  12230         IDB_OBM2_MAX_USAGEr, IDB_OBM3_MAX_USAGEr,
  12231         IDB_OBM4_MAX_USAGEr, IDB_OBM5_MAX_USAGEr,
  12232         IDB_OBM6_MAX_USAGEr, IDB_OBM7_MAX_USAGEr,
  12233 #ifdef BCM_TOMAHAWK2_SUPPORT
  12234         IDB_OBM8_MAX_USAGEr, IDB_OBM9_MAX_USAGEr,
  12235         IDB_OBM10_MAX_USAGEr, IDB_OBM11_MAX_USAGEr,
  12236         IDB_OBM12_MAX_USAGEr, IDB_OBM13_MAX_USAGEr,
  12237         IDB_OBM14_MAX_USAGEr, IDB_OBM15_MAX_USAGEr,
  12238 #endif
  12239     };
  12240 
  12241     soc_field_t obm_high_watermark_fields[] = {
  12242         PORT0_MAX_USAGEf, PORT1_MAX_USAGEf,
  12243         PORT2_MAX_USAGEf, PORT3_MAX_USAGEf
  12244     };
  12245 
  12246     SOC_IF_ERROR_RETURN
  12247             (soc_tomahawk_port_obm_info_get(unit, port, &obm_id, &lane));
  12248 #ifdef BCM_TOMAHAWK2_SUPPORT
  12249     obm_max = SOC_IS_TOMAHAWK2(unit) ? _TH2_PBLKS_PER_PIPE : _TH_PBLKS_PER_PIPE;
  12250 #else
  12251     obm_max = _TH_PBLKS_PER_PIPE;
  12252 #endif
  12253     if (obm_id >= obm_max || (lane < 0 || lane >= _TH_PORTS_PER_PBLK)) {
  12254             return BCM_E_PARAM;
  12255     }
  12256     if(!COMPILER_64_IS_ZERO(value)) {
  12257         return BCM_E_PARAM;
  12258     }
  12259     si = &SOC_INFO(unit);
  12260     pipe = si->port_pipe[port];
  12261 
  12262     reg = SOC_REG_UNIQUE_ACC(unit, obm_high_watermark_reg[obm_id])[pipe];
  12263     COMPILER_64_ZERO(rval64);
  12264     BCM_IF_ERROR_RETURN
  12265             (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64));
  12266 
  12267     soc_reg64_field32_set(unit, reg, &rval64, obm_high_watermark_fields[lane], 0);
  12268     BCM_IF_ERROR_RETURN
  12269             (soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval64));
  12270     return BCM_E_NONE;
  12271 }
  12272 
  12273 STATIC int
  12274 _bcm_th_cosq_obmhighwatermark_get(int unit, bcm_port_t port, uint64 *value)
  12275 {
  12276     int pipe, obm_id, obm_max, lane, gran;
  12277     soc_reg_t reg;
  12278     uint64 rval64;
  12279     soc_info_t *si;
  12280     soc_reg_t obm_high_watermark_reg[] = {
  12281         IDB_OBM0_MAX_USAGEr, IDB_OBM1_MAX_USAGEr,
  12282         IDB_OBM2_MAX_USAGEr, IDB_OBM3_MAX_USAGEr,
  12283         IDB_OBM4_MAX_USAGEr, IDB_OBM5_MAX_USAGEr,
  12284         IDB_OBM6_MAX_USAGEr, IDB_OBM7_MAX_USAGEr,
  12285 #ifdef BCM_TOMAHAWK2_SUPPORT
  12286         IDB_OBM8_MAX_USAGEr, IDB_OBM9_MAX_USAGEr,
  12287         IDB_OBM10_MAX_USAGEr, IDB_OBM11_MAX_USAGEr,
  12288         IDB_OBM12_MAX_USAGEr, IDB_OBM13_MAX_USAGEr,
  12289         IDB_OBM14_MAX_USAGEr, IDB_OBM15_MAX_USAGEr,
  12290 #endif
  12291     };
  12292 
  12293     soc_field_t obm_high_watermark_fields[] = {
  12294         PORT0_MAX_USAGEf, PORT1_MAX_USAGEf,
  12295         PORT2_MAX_USAGEf, PORT3_MAX_USAGEf
  12296     };
  12297 
  12298     SOC_IF_ERROR_RETURN
  12299             (soc_tomahawk_port_obm_info_get(unit, port, &obm_id, &lane));
  12300 #ifdef BCM_TOMAHAWK2_SUPPORT
  12301     obm_max = SOC_IS_TOMAHAWK2(unit) ? _TH2_PBLKS_PER_PIPE : _TH_PBLKS_PER_PIPE;
  12302 #else
  12303     obm_max = _TH_PBLKS_PER_PIPE;
  12304 #endif
  12305     if (obm_id >= obm_max || (lane < 0 || lane >= _TH_PORTS_PER_PBLK)) {
  12306             return BCM_E_PARAM;
  12307     }
  12308     si = &SOC_INFO(unit);
  12309     pipe = si->port_pipe[port];
  12310 
  12311     reg = SOC_REG_UNIQUE_ACC(unit, obm_high_watermark_reg[obm_id])[pipe];
  12312     COMPILER_64_ZERO(rval64);
  12313     BCM_IF_ERROR_RETURN
  12314             (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64));
  12315 
  12316     *value = soc_reg64_field_get(unit, reg, rval64, obm_high_watermark_fields[lane]);
  12317     gran = SOC_IS_TOMAHAWK2(unit) ? 16 : 48;
  12318     COMPILER_64_UMUL_32(*value, gran);
  12319 
  12320     return BCM_E_NONE;
  12321 }
  12322 
  12323 STATIC int
  12324 _bcm_th_cosq_obm_buf_use_cnt_set(int unit, bcm_port_t port, uint64 value)
  12325 {
  12326     int pipe, obm_id, obm_max, lane;
  12327     soc_reg_t reg;
  12328     soc_field_t fld;
  12329     uint64 rval64;
  12330     soc_info_t *si;
  12331     soc_reg_t obm_usage_reg[] = {
  12332         IDB_OBM0_USAGEr, IDB_OBM1_USAGEr,
  12333         IDB_OBM2_USAGEr, IDB_OBM3_USAGEr,
  12334         IDB_OBM4_USAGEr, IDB_OBM5_USAGEr,
  12335         IDB_OBM6_USAGEr, IDB_OBM7_USAGEr,
  12336 #ifdef BCM_TOMAHAWK2_SUPPORT
  12337         IDB_OBM8_USAGEr, IDB_OBM9_USAGEr,
  12338         IDB_OBM10_USAGEr, IDB_OBM11_USAGEr,
  12339         IDB_OBM12_USAGEr, IDB_OBM13_USAGEr,
  12340         IDB_OBM14_USAGEr, IDB_OBM15_USAGEr,
  12341 #endif
  12342     };
  12343 
  12344     SOC_IF_ERROR_RETURN
  12345             (soc_tomahawk_port_obm_info_get(unit, port, &obm_id, &lane));
  12346 #ifdef BCM_TOMAHAWK2_SUPPORT
  12347     obm_max = SOC_IS_TOMAHAWK2(unit) ? _TH2_PBLKS_PER_PIPE : _TH_PBLKS_PER_PIPE;
  12348 #else
  12349     obm_max = _TH_PBLKS_PER_PIPE;
  12350 #endif
  12351     if (obm_id >= obm_max || (lane < 0 || lane >= _TH_PORTS_PER_PBLK)) {
  12352         return BCM_E_PARAM;
  12353     }
  12354     if(!COMPILER_64_IS_ZERO(value)) {
  12355         return BCM_E_PARAM;
  12356     }
  12357     si = &SOC_INFO(unit);
  12358     pipe = si->port_pipe[port];
  12359 
  12360     reg = SOC_REG_UNIQUE_ACC(unit, obm_usage_reg[obm_id])[pipe];
  12361     fld = si->mmu_lossless ? LOSSLESS0_COUNTf : LOSSY_COUNTf;
  12362     COMPILER_64_ZERO(rval64);
  12363     BCM_IF_ERROR_RETURN
  12364             (soc_reg64_get(unit, reg, REG_PORT_ANY, lane, &rval64));
  12365 
  12366     soc_reg64_field_set(unit, reg, &rval64, fld, value);
  12367     BCM_IF_ERROR_RETURN
  12368             (soc_reg64_set(unit, reg, REG_PORT_ANY, lane, rval64));
  12369     return BCM_E_NONE;
  12370 }
  12371 
  12372 STATIC int
  12373 _bcm_th_cosq_obm_buf_use_cnt_get(int unit, bcm_port_t port, uint64 *value)
  12374 {
  12375     int pipe, obm_id, obm_max, lane, gran;
  12376     soc_reg_t reg;
  12377     soc_field_t fld;
  12378     uint64 rval64;
  12379     soc_info_t *si;
  12380     soc_reg_t obm_usage_reg[] = {
  12381         IDB_OBM0_USAGEr, IDB_OBM1_USAGEr,
  12382         IDB_OBM2_USAGEr, IDB_OBM3_USAGEr,
  12383         IDB_OBM4_USAGEr, IDB_OBM5_USAGEr,
  12384         IDB_OBM6_USAGEr, IDB_OBM7_USAGEr,
  12385 #ifdef BCM_TOMAHAWK2_SUPPORT
  12386         IDB_OBM8_USAGEr, IDB_OBM9_USAGEr,
  12387         IDB_OBM10_USAGEr, IDB_OBM11_USAGEr,
  12388         IDB_OBM12_USAGEr, IDB_OBM13_USAGEr,
  12389         IDB_OBM14_USAGEr, IDB_OBM15_USAGEr,
  12390 #endif
  12391     };
  12392 
  12393     SOC_IF_ERROR_RETURN
  12394             (soc_tomahawk_port_obm_info_get(unit, port, &obm_id, &lane));
  12395 #ifdef BCM_TOMAHAWK2_SUPPORT
  12396     obm_max = SOC_IS_TOMAHAWK2(unit) ? _TH2_PBLKS_PER_PIPE : _TH_PBLKS_PER_PIPE;
  12397 #else
  12398     obm_max = _TH_PBLKS_PER_PIPE;
  12399 #endif
  12400     if (obm_id >= obm_max || (lane < 0 || lane >= _TH_PORTS_PER_PBLK)) {
  12401             return BCM_E_PARAM;
  12402     }
  12403     si = &SOC_INFO(unit);
  12404     pipe = si->port_pipe[port];
  12405 
  12406     reg = SOC_REG_UNIQUE_ACC(unit, obm_usage_reg[obm_id])[pipe];
  12407     fld = si->mmu_lossless ? LOSSLESS0_COUNTf : LOSSY_COUNTf;
  12408     COMPILER_64_ZERO(rval64);
  12409     BCM_IF_ERROR_RETURN
  12410             (soc_reg64_get(unit, reg, REG_PORT_ANY, lane, &rval64));
  12411 
  12412     *value = soc_reg64_field_get(unit, reg, rval64, fld);
  12413     gran = SOC_IS_TOMAHAWK2(unit) ? 16 : 48;
  12414     COMPILER_64_UMUL_32(*value, gran);
  12415 
  12416     return BCM_E_NONE;
  12417 }
  12418 
  12419 int
  12420 bcm_th_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
  12421                      bcm_cosq_stat_t stat, uint64 value)
  12422 {
  12423     soc_ctr_control_info_t ctrl_info;
  12424     soc_reg_t ctr_reg, ctr_reg_uc, ctr_reg_mc;
  12425     _bcm_th_cosq_index_style_t style = _BCM_TH_COSQ_INDEX_STYLE_COUNT;
  12426     int startq = 0, ci, from_cos, to_cos;
  12427     bcm_port_t local_port = -1;
  12428 
  12429     ctrl_info.instance = -1;
  12430     ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE;
  12431 
  12432     BCM_IF_ERROR_RETURN
  12433         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
  12434     if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) {
  12435         return BCM_E_PARAM;
  12436     }
  12437 
  12438     switch (stat) {
  12439         case bcmCosqStatDroppedPackets:
  12440         case bcmCosqStatDroppedBytes:
  12441         case bcmCosqStatOutPackets:
  12442         case bcmCosqStatOutBytes:
  12443         case bcmCosqStatUCOutPackets:
  12444         case bcmCosqStatUCOutBytes:
  12445         case bcmCosqStatMCOutPackets:
  12446         case bcmCosqStatMCOutBytes:
  12447         case bcmCosqStatDiscardUCDroppedPackets:
  12448             style = _BCM_TH_COSQ_INDEX_STYLE_COS;
  12449             if (stat == bcmCosqStatDroppedBytes) {
  12450                 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC;
  12451                 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE;
  12452             } else if (stat == bcmCosqStatDroppedPackets) {
  12453                 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC;
  12454                 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT;
  12455             } else if (stat == bcmCosqStatUCOutBytes) {
  12456                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12457                     return BCM_E_PARAM;
  12458                 }
  12459                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC;
  12460                 ctr_reg_mc = INVALIDr;
  12461                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12462             } else if (stat == bcmCosqStatUCOutPackets) {
  12463                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12464                     return BCM_E_PARAM;
  12465                 }
  12466                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC;
  12467                 ctr_reg_mc = INVALIDr;
  12468                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12469             } else if (stat == bcmCosqStatMCOutBytes) {
  12470                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  12471                     return BCM_E_PARAM;
  12472                 }
  12473                 ctr_reg_uc = INVALIDr;
  12474                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
  12475                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12476             } else if (stat == bcmCosqStatMCOutPackets) {
  12477                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  12478                     return BCM_E_PARAM;
  12479                 }
  12480                 ctr_reg_uc = INVALIDr;
  12481                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT;
  12482                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12483             } else if (stat == bcmCosqStatOutBytes) {
  12484                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC;
  12485                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
  12486                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12487             } else if (stat == bcmCosqStatDiscardUCDroppedPackets) {
  12488                if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
  12489                    BCM_GPORT_IS_SCHEDULER(port)) {
  12490                    return BCM_E_PARAM;
  12491                }
  12492                ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_WRED_PKT;
  12493                ctr_reg_mc = INVALIDr;
  12494            } else { /* (stat == bcmCosqStatOutPackets) */
  12495                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC;
  12496                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT;
  12497                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12498             }
  12499             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  12500                 if (ctr_reg_uc != INVALIDr) {
  12501                     BCM_IF_ERROR_RETURN
  12502                         (_bcm_th_cosq_index_resolve
  12503                          (unit, port, cosq, style, &local_port, &startq, NULL));
  12504 
  12505                     ctrl_info.instance = local_port;
  12506                     BCM_IF_ERROR_RETURN
  12507                         (soc_counter_generic_set(unit, ctr_reg_uc, ctrl_info, 0,
  12508                                                  startq, value));
  12509                 }
  12510             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12511                 if (ctr_reg_mc != INVALIDr) {
  12512                     BCM_IF_ERROR_RETURN
  12513                         (_bcm_th_cosq_index_resolve
  12514                          (unit, port, cosq, style, &local_port, &startq, NULL));
  12515 
  12516                     ctrl_info.instance = local_port;
  12517                     BCM_IF_ERROR_RETURN
  12518                         (soc_counter_generic_set(unit, ctr_reg_mc, ctrl_info, 0,
  12519                                                  startq, value));
  12520                 }
  12521             } else {
  12522                 if (BCM_GPORT_IS_SCHEDULER(port)) {
  12523                     BCM_IF_ERROR_RETURN
  12524                         (_bcm_th_cosq_index_resolve
  12525                          (unit, port, cosq, style, &local_port, &startq, NULL));
  12526                     from_cos = to_cos = startq;
  12527                 } else {
  12528                     BCM_IF_ERROR_RETURN
  12529                         (_bcm_th_cosq_localport_resolve(unit, port,
  12530                                                         &local_port));
  12531 
  12532                     if (cosq == BCM_COS_INVALID) {
  12533                         /* if (cosq == -1) set value for the first cosq */
  12534                         cosq = 0;
  12535                     }
  12536                     from_cos = to_cos = cosq;
  12537                 }
  12538                 ctrl_info.instance = local_port;
  12539                 for (ci = from_cos; ci <= to_cos; ci++) {
  12540 
  12541                     if (!IS_CPU_PORT(unit, local_port)) {
  12542                         if (ctr_reg_uc != INVALIDr) {
  12543                             /* Get UC values if NOT CPU port */
  12544                             BCM_IF_ERROR_RETURN
  12545                                 (soc_counter_generic_set(unit, ctr_reg_uc,
  12546                                                          ctrl_info, 0,
  12547                                                          ci, value));
  12548                         }
  12549                     }
  12550 
  12551                     if (ctr_reg_mc != INVALIDr) {
  12552                         BCM_IF_ERROR_RETURN
  12553                             (soc_counter_generic_set(unit, ctr_reg_mc,
  12554                                                      ctrl_info, 0, ci, value));
  12555                     }
  12556                 }
  12557             }
  12558             break;
  12559         case bcmCosqStatYellowCongestionDroppedPackets:
  12560         case bcmCosqStatRedCongestionDroppedPackets:
  12561         case bcmCosqStatGreenDiscardDroppedPackets:
  12562         case bcmCosqStatYellowDiscardDroppedPackets:
  12563         case bcmCosqStatRedDiscardDroppedPackets:
  12564             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  12565                 BCM_GPORT_IS_SCHEDULER(port) ||
  12566                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12567                 return BCM_E_PARAM;
  12568             }
  12569             if (cosq != BCM_COS_INVALID) {
  12570                 return BCM_E_UNAVAIL;
  12571             }
  12572             if (stat == bcmCosqStatYellowCongestionDroppedPackets) {
  12573                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW;
  12574             } else if (stat == bcmCosqStatRedCongestionDroppedPackets) {
  12575                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED;
  12576             } else if (stat == bcmCosqStatYellowDiscardDroppedPackets) {
  12577                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW;
  12578             } else if (stat == bcmCosqStatRedDiscardDroppedPackets) {
  12579                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED;
  12580             } else {
  12581                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN;
  12582             }
  12583             BCM_IF_ERROR_RETURN
  12584                 (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
  12585 
  12586             ctrl_info.instance = local_port;
  12587             BCM_IF_ERROR_RETURN
  12588                 (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0,
  12589                                          startq, value));
  12590             break;
  12591         case bcmCosqStatHighPriDroppedPackets:
  12592         case bcmCosqStatOBMLossyHighPriDroppedPackets:
  12593         case bcmCosqStatLowPriDroppedPackets:
  12594         case bcmCosqStatOBMLossyLowPriDroppedPackets:
  12595         case bcmCosqStatHighPriDroppedBytes:
  12596         case bcmCosqStatOBMLossyHighPriDroppedBytes:
  12597         case bcmCosqStatLowPriDroppedBytes:
  12598         case bcmCosqStatOBMLossyLowPriDroppedBytes:
  12599         case bcmCosqStatOBMLossless0DroppedPackets:
  12600         case bcmCosqStatOBMLossless1DroppedPackets:
  12601         case bcmCosqStatOBMLossless0DroppedBytes:
  12602         case bcmCosqStatOBMLossless1DroppedBytes:
  12603         case bcmCosqStatOBMFlowControlEvents:
  12604             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  12605                 BCM_GPORT_IS_SCHEDULER(port) ||
  12606                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12607                 return BCM_E_PARAM;
  12608             }
  12609             if ((stat == bcmCosqStatHighPriDroppedPackets) ||
  12610                 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) {
  12611                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI;
  12612             } else if ((stat == bcmCosqStatLowPriDroppedPackets) ||
  12613                        (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) {
  12614                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO;
  12615             } else if ((stat == bcmCosqStatHighPriDroppedBytes) ||
  12616                        (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) {
  12617                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI;
  12618             } else if ((stat == bcmCosqStatLowPriDroppedBytes) ||
  12619                        (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) {
  12620                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO;
  12621             } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) {
  12622                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0;
  12623             } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) {
  12624                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1;
  12625             } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) {
  12626                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0;
  12627             } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) {
  12628                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1;
  12629             } else { /* (stat == bcmCosqStatOBMFlowControlEvents)  */
  12630                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_OBM_FC_EVENTS;
  12631             }
  12632             ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12633             ctrl_info.instance = local_port;
  12634             BCM_IF_ERROR_RETURN
  12635                 (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0,
  12636                                          0, value));
  12637             break;
  12638         case bcmCosqStatOBMHighWatermark:
  12639         case bcmCosqStatOBMBufferBytes:
  12640             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  12641                 BCM_GPORT_IS_SCHEDULER(port) ||
  12642                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12643                 return BCM_E_PARAM;
  12644             }
  12645             if (stat == bcmCosqStatOBMHighWatermark) {
  12646                 BCM_IF_ERROR_RETURN
  12647                     (_bcm_th_cosq_obmhighwatermark_set(unit, local_port, value));
  12648             } else {
  12649                 BCM_IF_ERROR_RETURN
  12650                     (_bcm_th_cosq_obm_buf_use_cnt_set(unit, local_port, value));
  12651             }
  12652             break;
  12653         default:
  12654             return BCM_E_PARAM;
  12655     }
  12656 
  12657     return BCM_E_NONE;
  12658 }
  12659 
  12660 int
  12661 bcm_th_cosq_stat_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
  12662                      bcm_cosq_stat_t stat, int sync_mode, uint64 *value)
  12663 {
  12664     soc_ctr_control_info_t ctrl_info;
  12665     soc_reg_t ctr_reg, ctr_reg_uc, ctr_reg_mc;
  12666     _bcm_th_cosq_index_style_t style = _BCM_TH_COSQ_INDEX_STYLE_COUNT;
  12667     uint64 sum, value64;
  12668     int startq = 0, ci, from_cos, to_cos, i, start_hw_index, end_hw_index;
  12669     bcm_port_t local_port = -1;
  12670     int sync = sync_mode ? SOC_COUNTER_SYNC_ENABLE : 0;
  12671     soc_info_t *si = &SOC_INFO(unit);
  12672     soc_mem_t mem = INVALIDm;
  12673     soc_mem_t base_mem;
  12674     uint32 entry[SOC_MAX_MEM_WORDS];
  12675     uint32 sum32;
  12676     int pipe, xpe, factor = 1;
  12677     int pool, mem_idx;
  12678     uint32 value32, rval, valid;
  12679     soc_field_t field = INVALIDf;
  12680     soc_reg_t reg = INVALIDr;
  12681     soc_reg_t base_reg = INVALIDr;
  12682 
  12683     BCM_IF_ERROR_RETURN
  12684         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
  12685     ctrl_info.instance = -1;
  12686     ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE;
  12687 
  12688     switch (stat) {
  12689         case bcmCosqStatDroppedPackets:
  12690         case bcmCosqStatDroppedBytes:
  12691         case bcmCosqStatOutPackets:
  12692         case bcmCosqStatOutBytes:
  12693         case bcmCosqStatUCOutPackets:
  12694         case bcmCosqStatUCOutBytes:
  12695         case bcmCosqStatMCOutPackets:
  12696         case bcmCosqStatMCOutBytes:
  12697         case bcmCosqStatEgressMCQueueBytesPeak:
  12698         case bcmCosqStatEgressUCQueueBytesPeak:
  12699         case bcmCosqStatDiscardUCDroppedPackets:
  12700             if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) {
  12701                 return BCM_E_PARAM;
  12702             }
  12703             style = _BCM_TH_COSQ_INDEX_STYLE_COS;
  12704             if (stat == bcmCosqStatEgressMCQueueBytesPeak) {
  12705                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  12706                     BCM_GPORT_IS_SCHEDULER(port)) {
  12707                     return BCM_E_PARAM;
  12708                 }
  12709                 ctr_reg_uc = INVALIDr;
  12710                 ctr_reg_mc = SOC_COUNTER_NON_DMA_QUEUE_PEAK;
  12711                 factor = _TH_MMU_BYTES_PER_CELL;
  12712             } else if (stat == bcmCosqStatEgressUCQueueBytesPeak) {
  12713                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
  12714                     BCM_GPORT_IS_SCHEDULER(port)) {
  12715                     return BCM_E_PARAM;
  12716                 }
  12717                 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  12718                     BCM_IF_ERROR_RETURN
  12719                         (_bcm_th_cosq_localport_resolve(unit, port,
  12720                                                         &local_port));
  12721                     if (IS_CPU_PORT(unit, local_port)) {
  12722                         return BCM_E_PARAM;
  12723                     }
  12724                 }
  12725                 ctr_reg_uc = SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK;
  12726                 ctr_reg_mc = INVALIDr;
  12727                 factor = _TH_MMU_BYTES_PER_CELL;
  12728             } else if (stat == bcmCosqStatDroppedBytes) {
  12729                 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC;
  12730                 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE;
  12731             } else if (stat == bcmCosqStatDroppedPackets) {
  12732                 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC;
  12733                 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT;
  12734             } else if (stat == bcmCosqStatUCOutBytes) {
  12735                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12736                     return BCM_E_PARAM;
  12737                 }
  12738                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC;
  12739                 ctr_reg_mc = INVALIDr;
  12740                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12741             } else if (stat == bcmCosqStatUCOutPackets) {
  12742                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12743                     return BCM_E_PARAM;
  12744                 }
  12745                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC;
  12746                 ctr_reg_mc = INVALIDr;
  12747                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12748             } else if (stat == bcmCosqStatMCOutBytes) {
  12749                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  12750                     return BCM_E_PARAM;
  12751                 }
  12752                 ctr_reg_uc = INVALIDr;
  12753                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
  12754                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12755             } else if (stat == bcmCosqStatMCOutPackets) {
  12756                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  12757                     return BCM_E_PARAM;
  12758                 }
  12759                 ctr_reg_uc = INVALIDr;
  12760                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT;
  12761                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12762             } else if (stat == bcmCosqStatOutBytes) {
  12763                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC;
  12764                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
  12765                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12766             } else if (stat == bcmCosqStatDiscardUCDroppedPackets) {
  12767                if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
  12768                    BCM_GPORT_IS_SCHEDULER(port)) {
  12769                    return BCM_E_PARAM;
  12770                }
  12771                ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_WRED_PKT;
  12772                ctr_reg_mc = INVALIDr;
  12773            } else { /* (stat == bcmCosqStatOutPackets) */
  12774                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC;
  12775                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT;
  12776                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  12777             }
  12778 
  12779             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  12780                 if (ctr_reg_uc != INVALIDr) {
  12781                     BCM_IF_ERROR_RETURN
  12782                         (_bcm_th_cosq_index_resolve
  12783                          (unit, port, cosq, style, &local_port, &startq, NULL));
  12784 
  12785                     ctrl_info.instance = local_port;
  12786                     BCM_IF_ERROR_RETURN
  12787                         (soc_counter_generic_get(unit, ctr_reg_uc, ctrl_info,
  12788                                                  sync, startq, value));
  12789                 }
  12790             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12791                 if (ctr_reg_mc != INVALIDr) {
  12792                     BCM_IF_ERROR_RETURN
  12793                         (_bcm_th_cosq_index_resolve
  12794                          (unit, port, cosq, style, &local_port, &startq, NULL));
  12795                     ctrl_info.instance = local_port;
  12796                     BCM_IF_ERROR_RETURN
  12797                         (soc_counter_generic_get(unit, ctr_reg_mc, ctrl_info,
  12798                                                  sync, startq, value));
  12799                 }
  12800             } else {
  12801                 COMPILER_64_ZERO(sum);
  12802                 if (BCM_GPORT_IS_SCHEDULER(port)) {
  12803                     BCM_IF_ERROR_RETURN
  12804                         (_bcm_th_cosq_index_resolve
  12805                          (unit, port, cosq, style, &local_port, &startq, NULL));
  12806                     from_cos = to_cos = startq;
  12807                 } else {
  12808                     BCM_IF_ERROR_RETURN
  12809                         (_bcm_th_cosq_localport_resolve(unit, port,
  12810                                                         &local_port));
  12811 
  12812                     if (cosq == BCM_COS_INVALID) {
  12813                         from_cos = 0;
  12814                         to_cos = (IS_CPU_PORT(unit, local_port)) ?
  12815                                     NUM_CPU_COSQ(unit) - 1 : _TH_NUM_COS(unit)
  12816                                     - 1;
  12817                     } else {
  12818                         from_cos = to_cos = cosq;
  12819                     }
  12820                 }
  12821                 ctrl_info.instance = local_port;
  12822                 for (ci = from_cos; ci <= to_cos; ci++) {
  12823 
  12824                     if (!IS_CPU_PORT(unit, local_port)) {
  12825                         /* Get UC values if NOT CPU port */
  12826                         if (ctr_reg_uc != INVALIDr) {
  12827                             BCM_IF_ERROR_RETURN
  12828                                 (soc_counter_generic_get(unit, ctr_reg_uc,
  12829                                                          ctrl_info,
  12830                                                          sync, ci, &value64));
  12831                             COMPILER_64_ADD_64(sum, value64);
  12832                         }
  12833                     }
  12834 
  12835                     if (ctr_reg_mc != INVALIDr) {
  12836                         BCM_IF_ERROR_RETURN
  12837                             (soc_counter_generic_get(unit, ctr_reg_mc,
  12838                                                      ctrl_info,
  12839                                                      sync, ci, &value64));
  12840                         COMPILER_64_ADD_64(sum, value64);
  12841                     }
  12842                 }
  12843                 COMPILER_64_COPY(*value, sum);
  12844                 COMPILER_64_UMUL_32(*value, factor);
  12845             }
  12846             break;
  12847         case bcmCosqStatYellowCongestionDroppedPackets:
  12848         case bcmCosqStatRedCongestionDroppedPackets:
  12849         case bcmCosqStatGreenDiscardDroppedPackets:
  12850         case bcmCosqStatYellowDiscardDroppedPackets:
  12851         case bcmCosqStatRedDiscardDroppedPackets:
  12852             if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) {
  12853                 return BCM_E_PARAM;
  12854             }
  12855             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  12856                 BCM_GPORT_IS_SCHEDULER(port) ||
  12857                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12858                 return BCM_E_PARAM;
  12859             }
  12860             if (cosq != BCM_COS_INVALID) {
  12861                 return BCM_E_UNAVAIL;
  12862             }
  12863             if (stat == bcmCosqStatYellowCongestionDroppedPackets) {
  12864                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW;
  12865             } else if (stat == bcmCosqStatRedCongestionDroppedPackets) {
  12866                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED;
  12867             } else if (stat == bcmCosqStatYellowDiscardDroppedPackets) {
  12868                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW;
  12869             } else if (stat == bcmCosqStatRedDiscardDroppedPackets) {
  12870                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED;
  12871             } else { /* (stat == bcmCosqStatGreenDiscardDroppedPackets) */
  12872                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN;
  12873             }
  12874             BCM_IF_ERROR_RETURN
  12875                 (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
  12876 
  12877             ctrl_info.instance = local_port;
  12878             BCM_IF_ERROR_RETURN
  12879                 (soc_counter_generic_get(unit, ctr_reg, ctrl_info,
  12880                                          sync, startq, value));
  12881             break;
  12882         case bcmCosqStatIngressPortPGMinBytesPeak:
  12883         case bcmCosqStatIngressPortPGMinBytesCurrent:
  12884         case bcmCosqStatIngressPortPGSharedBytesPeak:
  12885         case bcmCosqStatIngressPortPGSharedBytesCurrent:
  12886         case bcmCosqStatIngressPortPGHeadroomBytesPeak:
  12887         case bcmCosqStatIngressPortPGHeadroomBytesCurrent:
  12888             if ( cosq < -1 ) {
  12889                 return BCM_E_PARAM;
  12890             }
  12891             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  12892                 BCM_GPORT_IS_SCHEDULER(port) ||
  12893                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12894                 return BCM_E_PARAM;
  12895             }
  12896             COMPILER_64_ZERO(sum);
  12897             if (stat == bcmCosqStatIngressPortPGMinBytesPeak) {
  12898                 ctr_reg = SOC_COUNTER_NON_DMA_PG_MIN_PEAK;
  12899             } else if (stat == bcmCosqStatIngressPortPGMinBytesCurrent) {
  12900                 ctr_reg = SOC_COUNTER_NON_DMA_PG_MIN_CURRENT;
  12901             } else if (stat == bcmCosqStatIngressPortPGSharedBytesPeak) {
  12902                 ctr_reg = SOC_COUNTER_NON_DMA_PG_SHARED_PEAK;
  12903             } else if (stat == bcmCosqStatIngressPortPGSharedBytesCurrent) {
  12904                 ctr_reg = SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT;
  12905             } else if (stat == bcmCosqStatIngressPortPGHeadroomBytesPeak) {
  12906                 ctr_reg = SOC_COUNTER_NON_DMA_PG_HDRM_PEAK;
  12907             } else {
  12908                 /* (stat == bcmCosqStatIngressPortPGHeadroomBytesCurrent) */
  12909                 ctr_reg = SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT;
  12910             }
  12911             BCM_IF_ERROR_RETURN
  12912                 (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
  12913             BCM_IF_ERROR_RETURN
  12914                 (_bcm_th_cosq_ingress_pg_get(unit, port, cosq,
  12915                                              &start_hw_index, &end_hw_index));
  12916 
  12917             for (i = start_hw_index; i <= end_hw_index; i++) {
  12918                 ctrl_info.instance = local_port;
  12919                 BCM_IF_ERROR_RETURN
  12920                     (soc_counter_generic_get(unit, ctr_reg, ctrl_info,
  12921                                              sync, i, &value64));
  12922                 COMPILER_64_ADD_64(sum, value64);
  12923             }
  12924 
  12925             COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL);
  12926             *value = sum;
  12927             break;
  12928         case bcmCosqStatIngressPortPoolSharedBytesPeak:
  12929             if ( cosq < -1 ) {
  12930                 return BCM_E_PARAM;
  12931             }
  12932             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  12933                 BCM_GPORT_IS_SCHEDULER(port) ||
  12934                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12935                 return BCM_E_PARAM;
  12936             }
  12937             COMPILER_64_ZERO(sum);
  12938             BCM_IF_ERROR_RETURN
  12939                 (_bcm_th_cosq_ingress_sp_get_by_pg(unit, port, cosq,
  12940                                              &start_hw_index, &end_hw_index));
  12941 
  12942             BCM_IF_ERROR_RETURN(
  12943                 _bcm_th_cosq_localport_resolve(unit, port, &local_port));
  12944 
  12945             ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE;
  12946             ctrl_info.instance = local_port;
  12947             ctr_reg = SOC_COUNTER_NON_DMA_POOL_PEAK;
  12948 
  12949             for (i = start_hw_index; i <= end_hw_index; i++) {
  12950                 BCM_IF_ERROR_RETURN
  12951                     (soc_counter_generic_get(unit, ctr_reg, ctrl_info,
  12952                                              sync, i, &value64));
  12953                 COMPILER_64_ADD_64(sum, value64);
  12954             }
  12955 
  12956             COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL);
  12957             *value = sum;
  12958             break;
  12959         case bcmCosqStatIngressPortPoolSharedBytesCurrent:
  12960             if ( cosq < -1 ) {
  12961                 return BCM_E_PARAM;
  12962             }
  12963             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  12964                 BCM_GPORT_IS_SCHEDULER(port) ||
  12965                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  12966                 return BCM_E_PARAM;
  12967             }
  12968             BCM_IF_ERROR_RETURN
  12969                 (_bcm_th_cosq_ingress_sp_get_by_pg(unit, port, cosq,
  12970                                              &start_hw_index, &end_hw_index));
  12971             BCM_IF_ERROR_RETURN(
  12972                 _bcm_th_cosq_localport_resolve(unit, port, &local_port));
  12973 
  12974             ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE;
  12975             ctrl_info.instance = local_port;
  12976             ctr_reg = SOC_COUNTER_NON_DMA_POOL_CURRENT;
  12977 
  12978             COMPILER_64_ZERO(sum);
  12979             for (i = start_hw_index; i <= end_hw_index; i++) {
  12980                 BCM_IF_ERROR_RETURN
  12981                     (soc_counter_generic_get(unit, ctr_reg, ctrl_info,
  12982                                              sync, i, &value64));
  12983                COMPILER_64_ADD_64(sum, value64);
  12984             }
  12985 
  12986             COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL);
  12987             *value = sum;
  12988             break;
  12989         case bcmCosqStatHighPriDroppedPackets:
  12990         case bcmCosqStatOBMLossyHighPriDroppedPackets:
  12991         case bcmCosqStatLowPriDroppedPackets:
  12992         case bcmCosqStatOBMLossyLowPriDroppedPackets:
  12993         case bcmCosqStatHighPriDroppedBytes:
  12994         case bcmCosqStatOBMLossyHighPriDroppedBytes:
  12995         case bcmCosqStatLowPriDroppedBytes:
  12996         case bcmCosqStatOBMLossyLowPriDroppedBytes:
  12997         case bcmCosqStatOBMLossless0DroppedPackets:
  12998         case bcmCosqStatOBMLossless1DroppedPackets:
  12999         case bcmCosqStatOBMLossless0DroppedBytes:
  13000         case bcmCosqStatOBMLossless1DroppedBytes:
  13001         case bcmCosqStatOBMFlowControlEvents:
  13002             if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) {
  13003                 return BCM_E_PARAM;
  13004             }
  13005             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  13006                 BCM_GPORT_IS_SCHEDULER(port) ||
  13007                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  13008                 return BCM_E_PARAM;
  13009             }
  13010             if ((stat == bcmCosqStatHighPriDroppedPackets) ||
  13011                 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) {
  13012                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI;
  13013             } else if ((stat == bcmCosqStatLowPriDroppedPackets) ||
  13014                        (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) {
  13015                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO;
  13016             } else if ((stat == bcmCosqStatHighPriDroppedBytes) ||
  13017                        (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) {
  13018                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI;
  13019             } else if ((stat == bcmCosqStatLowPriDroppedBytes) ||
  13020                        (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) {
  13021                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO;
  13022             } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) {
  13023                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0;
  13024             } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) {
  13025                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1;
  13026             } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) {
  13027                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0;
  13028             } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) {
  13029                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1;
  13030             } else { /* (stat == bcmCosqStatOBMFlowControlEvents)  */
  13031                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_OBM_FC_EVENTS;
  13032             }
  13033             ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  13034             ctrl_info.instance = local_port;
  13035             BCM_IF_ERROR_RETURN
  13036                 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 0,
  13037                                          0, value));
  13038             break;
  13039         case bcmCosqStatOBMHighWatermark:
  13040         case bcmCosqStatOBMBufferBytes:
  13041             if ((cosq < -1) || (cosq >= _TH_PORT_NUM_COS(unit, local_port))) {
  13042                 return BCM_E_PARAM;
  13043             }
  13044             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  13045                 BCM_GPORT_IS_SCHEDULER(port) ||
  13046                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  13047                 return BCM_E_PARAM;
  13048             }
  13049             if (stat == bcmCosqStatOBMHighWatermark) {
  13050                 BCM_IF_ERROR_RETURN
  13051                     (_bcm_th_cosq_obmhighwatermark_get(unit, local_port, value));
  13052             } else {
  13053                 BCM_IF_ERROR_RETURN
  13054                     (_bcm_th_cosq_obm_buf_use_cnt_get(unit, local_port, value));
  13055             }
  13056             break;
  13057         case bcmCosqStatEgressUCQueueMinBytesCurrent:
  13058         case bcmCosqStatEgressUCQueueBytesCurrent:
  13059             if (local_port < 0 || local_port >= SOC_MAX_NUM_PORTS) {
  13060                 return BCM_E_PORT;
  13061             }
  13062             if (stat == bcmCosqStatEgressUCQueueMinBytesCurrent) {
  13063                 field = MIN_COUNTf;
  13064             } else if (stat == bcmCosqStatEgressUCQueueBytesCurrent) {
  13065                 field = SHARED_COUNTf;
  13066             }
  13067             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  13068                 BCM_IF_ERROR_RETURN
  13069                     (_bcm_th_cosq_index_resolve(unit, port, cosq,
  13070                                                 _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13071                                                 NULL, &start_hw_index, NULL));
  13072                 pipe = si->port_pipe[local_port];
  13073                 COMPILER_64_ZERO(sum);
  13074                 sum32 = 0;
  13075                 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
  13076                     base_mem = MMU_THDU_COUNTER_QUEUEm;
  13077                     /* Get XPE/PIPE view from base mem */
  13078                     mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe);
  13079                     if (mem == INVALIDm) {
  13080                         continue;
  13081                     }
  13082                     SOC_IF_ERROR_RETURN
  13083                         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, start_hw_index, &entry));
  13084                     sum32 += soc_mem_field32_get(unit, mem, entry, field);
  13085                 }
  13086                 COMPILER_64_ADD_32(sum, sum32);
  13087                 COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL);
  13088             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  13089                 return BCM_E_PARAM;
  13090             } else {
  13091                 if (IS_CPU_PORT(unit, local_port)) {
  13092                     return BCM_E_PARAM;
  13093                 }
  13094 
  13095                 pipe = si->port_pipe[local_port];
  13096                 COMPILER_64_ZERO(sum);
  13097                 sum32 =0;
  13098 
  13099                 if (cosq == BCM_COS_INVALID) {
  13100                     from_cos = 0;
  13101                     to_cos = NUM_COS(unit) - 1;
  13102                 } else {
  13103                     from_cos = to_cos = cosq;
  13104                 }
  13105 
  13106                 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
  13107                     base_mem = MMU_THDU_COUNTER_QUEUEm;
  13108                     /* Get XPE/PIPE view from base mem */
  13109                     mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe);
  13110                     if (mem == INVALIDm) {
  13111                         continue;
  13112                     }
  13113                     for (ci = from_cos; ci <= to_cos; ci++) {
  13114                         BCM_IF_ERROR_RETURN
  13115                             (_bcm_th_cosq_index_resolve(unit, local_port, ci,
  13116                                                         _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13117                                                         NULL, &start_hw_index, NULL));
  13118                         SOC_IF_ERROR_RETURN
  13119                             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, start_hw_index, &entry));
  13120                         sum32 += soc_mem_field32_get(unit, mem, entry, field);
  13121                     }
  13122                 }
  13123                 COMPILER_64_ADD_32(sum, sum32);
  13124                 COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL);
  13125             }
  13126             *value = sum;
  13127             break;
  13128 
  13129         case bcmCosqStatEgressUCQueuePortBytesCurrent:
  13130             BCM_IF_ERROR_RETURN
  13131                 (_bcm_th_cosq_index_resolve(unit, port, cosq,
  13132                                              _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL,
  13133                                              &local_port, &pool, NULL));
  13134             value32 = 0;
  13135             base_mem = MMU_THDU_COUNTER_PORTm;
  13136             BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  13137             for (xpe = 0; xpe < NUM_XPE(unit); xpe++)  {
  13138                 if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) {
  13139                     continue;
  13140                 }
  13141                 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe);
  13142                 if (mem == INVALIDm) {
  13143                     continue;
  13144                 }
  13145                 mem_idx = SOC_TH_MMU_PIPED_MEM_INDEX(unit,
  13146                                 local_port, base_mem, pool);
  13147                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  13148                                          mem_idx, entry));
  13149                 value32 += soc_mem_field32_get(unit, mem, entry, SHARED_COUNTf);
  13150             }
  13151 
  13152             COMPILER_64_ADD_32(*value, value32);
  13153             COMPILER_64_UMUL_32(*value, _TH_MMU_BYTES_PER_CELL);
  13154             break;
  13155 
  13156         case bcmCosqStatEgressPortPoolTotalBytesCurrent:
  13157             if (cosq != BCM_COS_INVALID) {
  13158                 return BCM_E_UNAVAIL;
  13159             }
  13160             if (!SOC_REG_IS_VALID(unit, MMU_THDM_DB_PORT_TOTAL_COUNTr)) {
  13161                 return BCM_E_UNAVAIL;
  13162             }
  13163             BCM_IF_ERROR_RETURN
  13164                 (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
  13165             value32 = 0;
  13166             base_reg = MMU_THDM_DB_PORT_TOTAL_COUNTr;
  13167             BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  13168             for (xpe = 0; xpe < NUM_XPE(unit); xpe++)  {
  13169                 if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) {
  13170                     continue;
  13171                 }
  13172                 reg = SOC_REG_UNIQUE_ACC(unit, base_reg)[xpe];
  13173                 if (reg == INVALIDr) {
  13174                     continue;
  13175                 }
  13176                 BCM_IF_ERROR_RETURN
  13177                     (soc_reg32_get(unit, reg, local_port, 0, &rval));
  13178                 value32 += soc_reg_field_get(unit, reg, rval, COUNTf);
  13179             }
  13180 
  13181             COMPILER_64_ADD_32(*value, value32);
  13182             COMPILER_64_UMUL_32(*value, _TH_MMU_BYTES_PER_CELL);
  13183             break;
  13184 
  13185         case bcmCosqStatEgressPortPoolSharedBytesCurrent:
  13186             if (!SOC_REG_IS_VALID(unit, MMU_THDM_DB_PORTSP_SHARED_COUNTr)) {
  13187                 return BCM_E_UNAVAIL;
  13188             }
  13189             BCM_IF_ERROR_RETURN
  13190                 (_bcm_th_cosq_index_resolve(unit, port, cosq,
  13191                                             _BCM_TH_COSQ_INDEX_STYLE_EGR_POOL,
  13192                                             &local_port, &pool, NULL));
  13193             value32 = 0;
  13194             base_reg = MMU_THDM_DB_PORTSP_SHARED_COUNTr;
  13195             BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  13196             for (xpe = 0; xpe < NUM_XPE(unit); xpe++)  {
  13197                 if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) {
  13198                     continue;
  13199                 }
  13200                 reg = SOC_REG_UNIQUE_ACC(unit, base_reg)[xpe];
  13201                 if (reg == INVALIDr) {
  13202                     continue;
  13203                 }
  13204                 BCM_IF_ERROR_RETURN
  13205                     (soc_reg32_get(unit, reg, local_port, pool, &rval));
  13206                 value32 += soc_reg_field_get(unit, reg, rval, COUNTf);
  13207             }
  13208 
  13209             COMPILER_64_ADD_32(*value, value32);
  13210             COMPILER_64_UMUL_32(*value, _TH_MMU_BYTES_PER_CELL);
  13211             break;
  13212 
  13213         case bcmCosqStatEgressMCQueueMinBytesCurrent:
  13214         case bcmCosqStatEgressMCQueueBytesCurrent:
  13215             if (stat == bcmCosqStatEgressMCQueueMinBytesCurrent) {
  13216                 field = MIN_COUNTf;
  13217             } else if (stat == bcmCosqStatEgressMCQueueBytesCurrent) {
  13218                 field = SHARED_COUNTf;
  13219             }
  13220             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  13221                 return BCM_E_PARAM;
  13222             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  13223                 BCM_IF_ERROR_RETURN
  13224                     (_bcm_th_cosq_index_resolve(unit, port, cosq,
  13225                                                  _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13226                                                  &local_port, &startq, NULL));
  13227                 value32 = 0;
  13228                 base_mem = MMU_THDM_DB_QUEUE_COUNTm;
  13229                 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  13230                 for (xpe = 0; xpe < NUM_XPE(unit); xpe++)  {
  13231                     if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) {
  13232                         continue;
  13233                     }
  13234                     mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe);
  13235                     if (mem == INVALIDm) {
  13236                         continue;
  13237                     }
  13238                     mem_idx = SOC_TH_MMU_PIPED_MEM_INDEX(unit,
  13239                                     local_port, base_mem, pool);
  13240                     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  13241                                              mem_idx, entry));
  13242                     value32 += soc_mem_field32_get(unit, mem, entry, field);
  13243                 }
  13244 
  13245                 COMPILER_64_ADD_32(*value, value32);
  13246                 COMPILER_64_UMUL_32(*value, _TH_MMU_BYTES_PER_CELL);
  13247             } else {
  13248                 BCM_IF_ERROR_RETURN(_bcm_th_cosq_localport_resolve(unit, port,
  13249                                         &local_port));
  13250                 COMPILER_64_ZERO(sum);
  13251                 sum32 =0;
  13252                 if (cosq == BCM_COS_INVALID) {
  13253                     from_cos = 0;
  13254                     to_cos = (IS_CPU_PORT(unit, local_port)) ?
  13255                                 NUM_CPU_COSQ(unit) - 1 : _TH_NUM_COS(unit) - 1;
  13256                 } else {
  13257                     from_cos = to_cos = cosq;
  13258                 }
  13259 
  13260                 if (local_port < 0) {
  13261                     return BCM_E_PORT;
  13262                 }
  13263 
  13264                 sum32 = 0;
  13265                 base_mem = MMU_THDM_DB_QUEUE_COUNTm;
  13266                 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  13267                 for (xpe = 0; xpe < NUM_XPE(unit); xpe++)  {
  13268                     if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) {
  13269                         continue;
  13270                     }
  13271                     mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe);
  13272                     if (mem == INVALIDm) {
  13273                         continue;
  13274                     }
  13275                     for (ci = from_cos; ci <= to_cos; ci++) {
  13276                         BCM_IF_ERROR_RETURN
  13277                             (_bcm_th_cosq_index_resolve
  13278                              (unit, local_port, ci, _BCM_TH_COSQ_INDEX_STYLE_MCAST_QUEUE,
  13279                               NULL, &startq, NULL));
  13280                         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
  13281                                                  startq, entry));
  13282                         sum32 += soc_mem_field32_get(unit, mem, entry, field);
  13283                     }
  13284                 }
  13285 
  13286                 COMPILER_64_ADD_32(sum, sum32);
  13287                 COMPILER_64_UMUL_32(sum, _TH_MMU_BYTES_PER_CELL);
  13288                 *value = sum;
  13289             }
  13290             break;
  13291 
  13292         case bcmCosqStatEgressQgroupMinBytesCurrent:
  13293         case bcmCosqStatEgressQgroupBytesCurrent:
  13294             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  13295                 BCM_IF_ERROR_RETURN
  13296                     (_bcm_th_cosq_index_resolve(unit, port, cosq,
  13297                                                  _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13298                                                  &local_port, &startq, NULL));
  13299             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  13300                 return BCM_E_PARAM;
  13301             } else {
  13302                 BCM_IF_ERROR_RETURN
  13303                     (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
  13304                 if (local_port < 0) {
  13305                     return BCM_E_PORT;
  13306                 }
  13307                 BCM_IF_ERROR_RETURN
  13308                     (_bcm_th_cosq_index_resolve(unit, local_port, cosq,
  13309                                                  _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE,
  13310                                                  NULL, &startq, NULL));
  13311             }
  13312 
  13313             value32 = 0;
  13314             BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  13315             for (xpe = 0; xpe < NUM_XPE(unit); xpe++)  {
  13316                 if (!(si->epipe_xpe_map[pipe] & (1 << xpe))) {
  13317                     continue;
  13318                 }
  13319                 base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
  13320                 mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, base_mem, pipe);
  13321                 if (mem == INVALIDm) {
  13322                     continue;
  13323                 }
  13324                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
  13325                 valid = soc_mem_field32_get(unit, mem, entry, QGROUP_VALIDf);
  13326                 if (!valid) {
  13327                     LOG_INFO(BSL_LS_BCM_COSQ,
  13328                              (BSL_META_U(unit,
  13329                              "UCQ doesn't associate with a queue group!\n")));
  13330                     return BCM_E_UNAVAIL;
  13331                 }
  13332                 base_mem = MMU_THDU_COUNTER_QGROUPm;
  13333                 BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  13334                 mem = SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, base_mem, xpe, pipe);
  13335                 if (stat == bcmCosqStatEgressQgroupMinBytesCurrent) {
  13336                     field = MIN_COUNTf;
  13337                 } else if (stat == bcmCosqStatEgressQgroupBytesCurrent) {
  13338                     field = SHARED_COUNTf;
  13339                 }
  13340 
  13341                 mem_idx = si->port_p2m_mapping[si->port_l2p_mapping[local_port]];
  13342                 mem_idx &= (SOC_TH_MMU_PORT_STRIDE - 1);
  13343                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, mem_idx, entry));
  13344                 value32 += soc_mem_field32_get(unit, mem, entry, field);
  13345             }
  13346 
  13347             COMPILER_64_ADD_32(*value, value32);
  13348             COMPILER_64_UMUL_32(*value, _TH_MMU_BYTES_PER_CELL);
  13349             break;
  13350 
  13351         default:
  13352             return BCM_E_PARAM;
  13353     }
  13354 
  13355     return BCM_E_NONE;
  13356 }
  13357 
  13358 
  13359 /*
  13360  * Function:
  13361  *     bcm_th_cosq_bst_profile_set
  13362  * Purpose:
  13363  *     Set the BST profile of a given BST stat id.
  13364  * Parameters:
  13365  *     unit     - (IN) unit number
  13366  *     gport    - (IN) gport of the port
  13367  *     cosq     - (IN) COS queue
  13368  *     bid      - (IN) BST statistics ID
  13369  *     profile  - (IN) profile for given BST ID
  13370  * Returns:
  13371  *     BCM_E_XXX
  13372  */
  13373 int
  13374 bcm_th_cosq_bst_profile_set(int unit,
  13375                             bcm_gport_t gport,
  13376                             bcm_cos_queue_t cosq,
  13377                             bcm_bst_stat_id_t bid,
  13378                             bcm_cosq_bst_profile_t *profile)
  13379 {
  13380     if (bid == bcmBstStatIdHeadroomPool) {
  13381         /* Do not have BST profile to set */
  13382         return BCM_E_PARAM;
  13383     } else {
  13384         return _bcm_bst_cmn_profile_set
  13385             (unit, gport, cosq, BCM_BST_DUP_XPE, bid, profile);
  13386     }
  13387 }
  13388 
  13389 /*
  13390  * Function:
  13391  *     bcm_th_cosq_bst_profile_get
  13392  * Purpose:
  13393  *     Get the BST profile of a given BST stat id.
  13394  * Parameters:
  13395  *     unit     - (IN) unit number
  13396  *     gport    - (IN) gport of the port
  13397  *     cosq     - (IN) COS queue
  13398  *     bid      - (IN) BST statistics ID
  13399  *     profile  - (OUT) profile retrieved for given BST ID
  13400  * Returns:
  13401  *     BCM_E_XXX
  13402  */
  13403 int
  13404 bcm_th_cosq_bst_profile_get(int unit,
  13405                             bcm_gport_t gport,
  13406                             bcm_cos_queue_t cosq,
  13407                             bcm_bst_stat_id_t bid,
  13408                             bcm_cosq_bst_profile_t *profile)
  13409 {
  13410     if (bid == bcmBstStatIdHeadroomPool) {
  13411         /* Do not have BST profile to get */
  13412         return BCM_E_PARAM;
  13413     } else {
  13414         return _bcm_bst_cmn_profile_get
  13415             (unit, gport, cosq, BCM_BST_DUP_XPE, bid, profile);
  13416     }
  13417 }
  13418 
  13419 /*
  13420  * Function:
  13421  *     bcm_th_cosq_bst_multi_profile_set
  13422  * Purpose:
  13423  *     Set the BST profiles of a given BST stat id, per XPE.
  13424  * Parameters:
  13425  *     unit     - (IN) unit number
  13426  *     gport    - (IN) gport of the port
  13427  *     cosq     - (IN) COS queue
  13428  *     bid      - (IN) BST statistics ID
  13429  *     size     - (IN) size of the profile array
  13430  *     profile  - (IN) profile array for given BST ID, index with XPE
  13431  * Returns:
  13432  *     BCM_E_XXX
  13433  */
  13434 int
  13435 bcm_th_cosq_bst_multi_profile_set(int unit,
  13436                             bcm_gport_t gport,
  13437                             bcm_cos_queue_t cosq,
  13438                             bcm_bst_stat_id_t bid,
  13439                             int array_size,
  13440                             bcm_cosq_bst_profile_t *profile_array)
  13441 {
  13442     int cnt;
  13443     bcm_cosq_bst_profile_t profile[_TH_XPES_PER_DEV];
  13444 
  13445     if ((!profile_array) || (array_size <=0)) {
  13446         return BCM_E_PARAM;
  13447     }
  13448     if (bid == bcmBstStatIdHeadroomPool) {
  13449         /* Do not have BST profile to set */
  13450         return BCM_E_PARAM;
  13451     }
  13452     if ((bid == bcmBstStatIdDevice)
  13453         || (bid == bcmBstStatIdUcast)
  13454         || (bid == bcmBstStatIdEgrPortPoolSharedUcast)) {
  13455         return BCM_E_UNAVAIL;
  13456     }
  13457 
  13458     cnt = NUM_XPE(unit);
  13459     if (array_size < cnt) {
  13460         cnt = array_size;
  13461     }
  13462     sal_memset(profile, 0, sizeof(profile));
  13463     sal_memcpy(profile, profile_array, cnt*sizeof(bcm_cosq_bst_profile_t));
  13464     
  13465     return _bcm_bst_cmn_profile_set
  13466         (unit, gport, cosq, BCM_BST_MLT_XPE, bid, profile);
  13467 }
  13468 
  13469 /*
  13470  * Function:
  13471  *     bcm_th_cosq_bst_multi_profile_get
  13472  * Purpose:
  13473  *     Get the BST profiles of a given BST stat id, per XPE.
  13474  * Parameters:
  13475  *     unit     - (IN) unit number
  13476  *     gport    - (IN) gport of the port
  13477  *     cosq     - (IN) COS queue
  13478  *     bid      - (IN) BST statistics ID
  13479  *     size     - (IN) max size of the profile array
  13480  *     profile  - (OUT) profile array retrieved for given BST ID, index with XPE
  13481  *     count    - (OUT) actual size of the profile array
  13482  * Returns:
  13483  *     BCM_E_XXX
  13484  */
  13485 int
  13486 bcm_th_cosq_bst_multi_profile_get(int unit,
  13487                             bcm_gport_t gport,
  13488                             bcm_cos_queue_t cosq,
  13489                             bcm_bst_stat_id_t bid,
  13490                             int array_size,
  13491                             bcm_cosq_bst_profile_t *profile_array,
  13492                             int *count)
  13493 {
  13494     int cnt;
  13495     bcm_cosq_bst_profile_t profile[_TH_XPES_PER_DEV];
  13496     
  13497     if (bid == bcmBstStatIdHeadroomPool) {
  13498         /* Do not have BST profile to get */
  13499         return BCM_E_PARAM;
  13500     }
  13501     if ((bid == bcmBstStatIdDevice)
  13502         || (bid == bcmBstStatIdUcast)
  13503         || (bid == bcmBstStatIdEgrPortPoolSharedUcast)) {
  13504         return BCM_E_UNAVAIL;
  13505     }
  13506 
  13507     cnt = NUM_XPE(unit);
  13508     if ((array_size > 0) && (array_size < cnt)) {
  13509         cnt = array_size;
  13510     }
  13511     if (count) {
  13512         *count  = cnt;
  13513     }
  13514     
  13515     if ((array_size == 0) && (!profile_array)) {
  13516         return BCM_E_NONE;
  13517     } else if ((array_size > 0) && (profile_array)) {
  13518         sal_memset(profile, 0, sizeof(profile));
  13519         BCM_IF_ERROR_RETURN(_bcm_bst_cmn_profile_get
  13520             (unit, gport, cosq, BCM_BST_MLT_XPE, bid, profile));
  13521         sal_memcpy(profile_array, profile, cnt*sizeof(bcm_cosq_bst_profile_t));
  13522         return BCM_E_NONE;
  13523     } else {
  13524         return BCM_E_PARAM;
  13525     }
  13526 }
  13527 
  13528 /*
  13529  * Function:
  13530  *     bcm_th_cosq_bst_stat_get
  13531  * Purpose:
  13532  *     Get the statistics of a given BST stat id.
  13533  * Parameters:
  13534  *     unit     - (IN) unit number
  13535  *     gport    - (IN) gport of the port
  13536  *     cosq     - (IN) COS queue
  13537  *     buffer   - (IN) Buffer ID
  13538  *     bid      - (IN) BST statistics ID
  13539  *     options  - (IN) Clear-on-read or not
  13540  *     pvalues  - (OUT) values retrieved for given BST ID
  13541  * Returns:
  13542  *     BCM_E_XXX
  13543  */
  13544 int
  13545 bcm_th_cosq_bst_stat_get(int unit,
  13546                          bcm_gport_t gport,
  13547                          bcm_cos_queue_t cosq,
  13548                          bcm_cosq_buffer_id_t buffer,
  13549                          bcm_bst_stat_id_t bid,
  13550                          uint32 options,
  13551                          uint64 *pvalue)
  13552 {
  13553     if (bid == bcmBstStatIdHeadroomPool) {
  13554         return _bcm_th_cosq_bst_hdrm_stat_get
  13555             (unit, gport, cosq, buffer, options, pvalue);
  13556     } else {
  13557         return _bcm_bst_cmn_stat_get(unit, gport, cosq, buffer, bid, options, pvalue);
  13558     }
  13559 }
  13560 
  13561 /*
  13562  * Function:
  13563  *     bcm_th_cosq_bst_stat_multi_get
  13564  * Purpose:
  13565  *     Get the statistics of a given BST stat id.
  13566  * Parameters:
  13567  *     unit         - (IN) unit number
  13568  *     gport        - (IN) gport of the port
  13569  *     cosq         - (IN) COS queue
  13570  *     options      - (IN) Clear-on-read or not
  13571  *     max_values   - (IN) max value in id_list.
  13572  *     id_list      - (IN) IDs to retrieve.
  13573  *     pvalues      - (OUT) values retrieved for id_list
  13574  * Returns:
  13575  *     BCM_E_XXX
  13576  */
  13577 int
  13578 bcm_th_cosq_bst_stat_multi_get(int unit,
  13579                                bcm_gport_t gport,
  13580                                bcm_cos_queue_t cosq,
  13581                                uint32 options,
  13582                                int max_values,
  13583                                bcm_bst_stat_id_t *id_list,
  13584                                uint64 *pvalues)
  13585 {
  13586     int i;
  13587 
  13588     for (i = 0; i < max_values; i++) {
  13589         if (id_list[i] == bcmBstStatIdHeadroomPool) {
  13590             BCM_IF_ERROR_RETURN
  13591                 (_bcm_th_cosq_bst_hdrm_stat_get(unit, gport, cosq, 
  13592                     BCM_COSQ_BUFFER_ID_INVALID, options, &pvalues[i]));
  13593         } else {
  13594             BCM_IF_ERROR_RETURN(_bcm_bst_cmn_stat_get(unit, gport, cosq,
  13595                             -1, id_list[i], options, &pvalues[i]));
  13596         }
  13597     }
  13598     return BCM_E_NONE;
  13599 }
  13600 
  13601 /*
  13602  * Function:
  13603  *     bcm_th_cosq_bst_stat_clear
  13604  * Purpose:
  13605  *     Clear the statistics from both hardware and
  13606  *     software for a given BST stat id.
  13607  * Parameters:
  13608  *     unit     - (IN) unit number
  13609  *     gport    - (IN) gport of the port
  13610  *     cosq     - (IN) COS queue
  13611  *     buffer   - (IN) Buffer ID
  13612  *     bid      - (IN) BST statistics ID
  13613  * Returns:
  13614  *     BCM_E_XXX
  13615  */
  13616 
  13617 int bcm_th_cosq_bst_stat_clear(int unit, bcm_gport_t gport,
  13618                                bcm_cos_queue_t cosq, bcm_cosq_buffer_id_t buffer,
  13619                                bcm_bst_stat_id_t bid)
  13620 {
  13621     if (bid == bcmBstStatIdHeadroomPool) {
  13622         return _bcm_th_bst_hdrm_stat_clear(unit, gport, cosq, buffer);
  13623     } else {
  13624         return _bcm_bst_cmn_stat_clear(unit, gport, cosq, bid);
  13625     }
  13626 }
  13627 
  13628 int bcm_th_cosq_bst_stat_sync(int unit, bcm_bst_stat_id_t bid)
  13629 {
  13630     return _bcm_bst_cmn_stat_sync(unit, bid);
  13631 }
  13632 
  13633 /*
  13634  * Function:
  13635  *     _bcm_th_port_enqueue_set
  13636  * Purpose:
  13637  *      Set the enqueue state of the port
  13638  * Parameters:
  13639  *     unit       - (IN) unit number
  13640  *     gport      - (IN) gport of the port
  13641  *     enable     - (IN) TRUE to enable
  13642  *                      FALSE to disable
  13643  * Returns:
  13644  *     BCM_E_XXX
  13645  */
  13646 
  13647 int
  13648 _bcm_th_port_enqueue_set(int unit, bcm_port_t gport, int enable)
  13649 {
  13650     int         rv = BCM_E_NONE;
  13651     pbmp_t      mask;
  13652     bcm_port_t port;
  13653     uint64 ctrl;
  13654 
  13655     BCM_IF_ERROR_RETURN(
  13656     _bcm_esw_port_gport_validate(unit, gport, &port));
  13657 
  13658     PORT_LOCK(unit);
  13659     SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl));
  13660 
  13661     /* Don't disable TX since it stops egress and hangs if CPU sends */
  13662     soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, TX_ENf, 1);
  13663     soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, RX_ENf, enable ? 1 : 0);
  13664 
  13665     if (enable) {
  13666         /* Deassert SOFT_RESET */
  13667         soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 0);
  13668         /* Deassert EGR_XLPORT_BUFFER_SFT_RESET */
  13669         rv = soc_tomahawk_edb_buf_reset(unit, port, 0);
  13670         if (BCM_FAILURE(rv)) {
  13671             PORT_UNLOCK(unit);
  13672             return (rv);
  13673         }
  13674         /* Release Ingress buffers from reset */
  13675         rv = soc_tomahawk_idb_buf_reset(unit, port, 0);
  13676         if (BCM_FAILURE(rv)) {
  13677             PORT_UNLOCK(unit);
  13678             return (rv);
  13679         }
  13680 
  13681         rv = WRITE_CLMAC_CTRLr(unit, port, ctrl);
  13682         if (BCM_FAILURE(rv)) {
  13683             PORT_UNLOCK(unit);
  13684             return (rv);
  13685         }
  13686 
  13687 #ifdef  BCM_TOMAHAWKPLUS_SUPPORT
  13688         /* Special handling for new mac version for TH+. Internally MAC
  13689          * loopback looks for rising edge on MAC loopback configuration
  13690          * to enter loopback state.
  13691          */
  13692         if (SOC_IS_TOMAHAWKPLUS(unit)) {
  13693             uint32 ctrl_32;
  13694             COMPILER_64_TO_32_LO(ctrl_32, ctrl);
  13695             if (ctrl_32 & 0x4) {
  13696                 /* Do only if loopback bit is intented to be set */
  13697                 soc_reg_field32_modify(unit, CLMAC_CTRLr, port, LOCAL_LPBKf, 0);
  13698                 sal_usleep(10);
  13699                 /* Wait 10usec as suggested by MAC designer */
  13700                 soc_reg_field32_modify(unit, CLMAC_CTRLr, port, LOCAL_LPBKf, 1);
  13701             }
  13702         }
  13703 #endif /* BCM_TOMAHAWKPLUS_SUPPORT */
  13704 
  13705         soc_link_mask2_get(unit, &mask);
  13706         SOC_PBMP_PORT_ADD(mask, port);
  13707         rv = soc_link_mask2_set(unit, mask);
  13708         if (BCM_FAILURE(rv)) {
  13709             PORT_UNLOCK(unit);
  13710             return (rv);
  13711         }
  13712 
  13713     } else {
  13714         /* Disable MAC RX */
  13715         rv = WRITE_CLMAC_CTRLr(unit, port, ctrl);
  13716         if (BCM_FAILURE(rv)) {
  13717             PORT_UNLOCK(unit);
  13718             return (rv);
  13719         }
  13720         soc_link_mask2_get(unit, &mask);
  13721         SOC_PBMP_PORT_REMOVE(mask, port);
  13722         rv = soc_link_mask2_set(unit, mask);
  13723         if (BCM_FAILURE(rv)) {
  13724             PORT_UNLOCK(unit);
  13725             return (rv);
  13726         }
  13727         /* Delay to ensure EOP is received at Ingress */
  13728         sal_udelay(1000);
  13729 
  13730         /* Reset Ingress buffers */
  13731         rv = soc_tomahawk_idb_buf_reset(unit, port, 1);
  13732         if (BCM_FAILURE(rv)) {
  13733             PORT_UNLOCK(unit);
  13734             return (rv);
  13735         }
  13736         /* Reset egress_buffer */
  13737         rv = soc_tomahawk_edb_buf_reset(unit, port, 1);
  13738         if (BCM_FAILURE(rv)) {
  13739             PORT_UNLOCK(unit);
  13740             return (rv);
  13741         }
  13742         /* Put port into SOFT_RESET */
  13743         soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 1);
  13744         rv = WRITE_CLMAC_CTRLr(unit, port, ctrl);
  13745         if (BCM_FAILURE(rv)) {
  13746             PORT_UNLOCK(unit);
  13747             return (rv);
  13748         }
  13749 
  13750     }
  13751 
  13752     PORT_UNLOCK(unit);
  13753     return BCM_E_NONE;
  13754 
  13755 }
  13756 
  13757 /*
  13758  * Function:
  13759  *     _bcm_th_port_enqueue_get
  13760  * Purpose:
  13761  *      Getting the enqueing state of the port
  13762  * Parameters:
  13763  *     unit       - (IN) unit number
  13764  *     gport      - (IN) gport of the port
  13765  *     enable     - (IN) TRUE to enable
  13766  *                      FALSE to disable
  13767  * Returns:
  13768  *     BCM_E_XXX
  13769  */
  13770 
  13771 int
  13772 _bcm_th_port_enqueue_get(int unit, bcm_port_t gport,
  13773                          int *enable)
  13774 {
  13775     return BCM_E_UNAVAIL;
  13776 }
  13777 
  13778 /*
  13779  * Function:
  13780  *     bcm_th_cosq_safc_class_mapping_set
  13781  * Purpose:
  13782  *     Set SAFC mapping for port.
  13783  *     SAFC class is mapped to cosq or scheduler node gports.
  13784  * Parameters:
  13785  *     unit             - (IN) unit number
  13786  *     port             - (IN) port number
  13787  *     array_count      - (IN) count of mapping
  13788  *     mapping_array    - (IN) mappings
  13789  * Returns:
  13790  *     BCM_E_XXX
  13791  */
  13792 int
  13793 bcm_th_cosq_safc_class_mapping_set(int unit, bcm_gport_t port,
  13794                                    int array_count,
  13795                                    bcm_cosq_safc_class_mapping_t *mapping_array)
  13796 {
  13797     int index, count;
  13798     int cur_class = 0;
  13799     int safc_class[_BCM_TH_NUM_SAFC_CLASS];
  13800     bcm_gport_t cur_gport = 0;
  13801     uint32 uc_cos_bmp[_BCM_TH_NUM_SAFC_CLASS] = {0};
  13802     uint32 mc_cos_bmp[_BCM_TH_NUM_SAFC_CLASS] = {0};
  13803     bcm_port_t local_port = -1;
  13804 
  13805     BCM_IF_ERROR_RETURN
  13806         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
  13807 
  13808     if (local_port < 0) {
  13809         return BCM_E_PORT;
  13810     }
  13811 
  13812     if (IS_CPU_PORT(unit, local_port)) {
  13813         return BCM_E_PARAM;
  13814     }
  13815 
  13816     if ((array_count < 0) || (array_count > _BCM_TH_NUM_SAFC_CLASS)) {
  13817         return BCM_E_PARAM;
  13818     }
  13819 
  13820     if (mapping_array == NULL) {
  13821         return BCM_E_PARAM;
  13822     }
  13823 
  13824     for (count = 0; count < array_count; count++) {
  13825         cur_class = mapping_array[count].class_id;
  13826         if ((cur_class < 0) || (cur_class >= _BCM_TH_NUM_SAFC_CLASS)) {
  13827             return BCM_E_PARAM;
  13828         } else {
  13829             uc_cos_bmp[cur_class] = 0;
  13830             mc_cos_bmp[cur_class] = 0;
  13831         }
  13832 
  13833         for (index = 0; index < BCM_COSQ_SAFC_GPORT_COUNT; index++) {
  13834             cur_gport = mapping_array[count].gport_list[index];
  13835             if (cur_gport == BCM_GPORT_INVALID) {
  13836                 break;
  13837             }
  13838 
  13839             if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) ||
  13840                 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport))) {
  13841                 BCM_IF_ERROR_RETURN
  13842                     (_bcm_th_fc_status_map_gport(unit, local_port, cur_gport,
  13843                                                  &uc_cos_bmp[cur_class],
  13844                                                  &mc_cos_bmp[cur_class]));
  13845             } else {
  13846                 return BCM_E_PARAM;
  13847             }
  13848         }
  13849     }
  13850 
  13851     for (index = 0; index < _BCM_TH_NUM_SAFC_CLASS; index++) {
  13852         safc_class[index] = index;
  13853     }
  13854     BCM_IF_ERROR_RETURN
  13855         (_bcm_th_cosq_port_fc_profile_set(unit, local_port, safc_class,
  13856                                           uc_cos_bmp, mc_cos_bmp,
  13857                                           _BCM_TH_NUM_SAFC_CLASS));
  13858 
  13859     return BCM_E_NONE;
  13860 }
  13861 
  13862 /*
  13863  * Function:
  13864  *     bcm_th_cosq_safc_class_mapping_get
  13865  * Purpose:
  13866  *     Get SAFC mapping for port.
  13867  *     Retrieves cosq or scheduler node gports
  13868  *     associated to SAFC classes.
  13869  * Parameters:
  13870  *     unit             - (IN) unit number
  13871  *     port             - (IN) port number
  13872  *     array_max        - (IN) max retrieve count
  13873  *     mapping_array    - (OUT) mappings
  13874  *     array_count      - (OUT) retrieved mapping count
  13875  * Returns:
  13876  *     BCM_E_XXX
  13877  */
  13878 int
  13879 bcm_th_cosq_safc_class_mapping_get(int unit, bcm_gport_t port,
  13880                                    int array_max,
  13881                                    bcm_cosq_safc_class_mapping_t *mapping_array,
  13882                                    int *array_count)
  13883 {
  13884     int rv = 0;
  13885     int cur_class = 0;
  13886     int actual_gport_count, class_count = 0;
  13887     bcm_port_t local_port = -1;
  13888 
  13889     BCM_IF_ERROR_RETURN
  13890         (_bcm_th_cosq_localport_resolve(unit, port, &local_port));
  13891 
  13892     if (local_port < 0) {
  13893         return BCM_E_PORT;
  13894     }
  13895 
  13896     if (IS_CPU_PORT(unit, local_port)) {
  13897         return BCM_E_PARAM;
  13898     }
  13899 
  13900     if (((mapping_array == NULL) && (array_max > 0)) ||
  13901         ((mapping_array != NULL) && (array_max <= 0)) ||
  13902         (array_count == NULL)) {
  13903         return BCM_E_PARAM;
  13904     }
  13905 
  13906     if (array_max <= 0) {
  13907         *array_count = _BCM_TH_NUM_SAFC_CLASS;
  13908         return BCM_E_NONE;
  13909     }
  13910 
  13911     for (cur_class = 0; cur_class < _BCM_TH_NUM_SAFC_CLASS; cur_class++) {
  13912         actual_gport_count = 0;
  13913         rv = _bcm_th_cosq_port_fc_get(unit, local_port, cur_class,
  13914                                       mapping_array[class_count].gport_list,
  13915                                       &actual_gport_count);
  13916 
  13917         if (rv == BCM_E_NONE) {
  13918             mapping_array[class_count].class_id = cur_class;
  13919             if (actual_gport_count < BCM_COSQ_SAFC_GPORT_COUNT) {
  13920                 mapping_array[class_count].gport_list[actual_gport_count] =
  13921                                                         BCM_GPORT_INVALID;
  13922             }
  13923             class_count++;
  13924         } else if (rv != BCM_E_NOT_FOUND) {
  13925             return rv;
  13926         }
  13927 
  13928         if (class_count == array_max) {
  13929             break;
  13930         }
  13931     }
  13932 
  13933     *array_count = class_count;
  13934     if (class_count == 0) {
  13935         return BCM_E_NOT_FOUND;
  13936     }
  13937 
  13938     return BCM_E_NONE;
  13939 }
  13940 
  13941 /*
  13942  * Function:
  13943  *      bcm_th_cosq_cpu_cosq_enable_set
  13944  * Purpose:
  13945  *      To enable/disable Rx of packets on the specified CPU cosq.
  13946  * Parameters:
  13947  *      unit          - (IN) Unit number.
  13948  *      cosq          - (IN) CPU Cosq ID
  13949  *      enable        - (IN) Enable/Disable
  13950  * Returns:
  13951  *      BCM_E_xxx
  13952  */
  13953 int
  13954 bcm_th_cosq_cpu_cosq_enable_set(int unit, bcm_cos_queue_t cosq, int enable)
  13955 {
  13956     uint32 entry[SOC_MAX_MEM_WORDS];
  13957     int i, index, enable_status;
  13958     _bcm_th_cosq_cpu_cosq_config_t *cpu_cosq_config;
  13959     soc_info_t *si;
  13960     soc_mem_t thdm_mem[] = {
  13961         MMU_THDM_DB_QUEUE_CONFIG_PIPE0m,
  13962         MMU_THDM_MCQE_QUEUE_CONFIG_PIPE0m
  13963     };
  13964 
  13965     si = &SOC_INFO(unit);
  13966 
  13967     if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) {
  13968         return BCM_E_PARAM;
  13969     }
  13970 
  13971     cpu_cosq_config = _bcm_th_cosq_cpu_cosq_config[unit][cosq];
  13972 
  13973     if (!cpu_cosq_config) {
  13974         return BCM_E_INTERNAL;
  13975     }
  13976     if (enable) {
  13977         enable = 1;
  13978     }
  13979 
  13980     BCM_IF_ERROR_RETURN(bcm_th_cosq_cpu_cosq_enable_get(unit, cosq,
  13981                                                          &enable_status));
  13982     if (enable == enable_status) {
  13983         return BCM_E_NONE;
  13984     }
  13985 
  13986     /* CPU Port (0) - MC cosq's range from 330 - 378. */
  13987     index = si->port_cosq_base[CMIC_PORT(unit)] + cosq;
  13988 
  13989     /* To set DB and QE entries */
  13990     for (i = 0; i < 2; i++) {
  13991         BCM_IF_ERROR_RETURN
  13992             (soc_mem_read(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry));
  13993 
  13994         /* When enabled, restore the Min and Shared from the cached value */
  13995         if (!enable) {
  13996             cpu_cosq_config->q_min_limit[i] = soc_mem_field32_get(unit,
  13997                                                            thdm_mem[i],
  13998                                                            &entry,
  13999                                                            Q_MIN_LIMITf);
  14000             cpu_cosq_config->q_shared_limit[i] = soc_mem_field32_get(unit,
  14001                                                               thdm_mem[i],
  14002                                                               &entry,
  14003                                                               Q_SHARED_LIMITf);
  14004             cpu_cosq_config->q_limit_dynamic[i] = soc_mem_field32_get(unit,
  14005                                                                thdm_mem[i],
  14006                                                                &entry,
  14007                                                                Q_LIMIT_DYNAMICf);
  14008             cpu_cosq_config->q_limit_enable[i] = soc_mem_field32_get(unit,
  14009                                                               thdm_mem[i],
  14010                                                               &entry,
  14011                                                               Q_LIMIT_ENABLEf);
  14012             cpu_cosq_config->q_color_limit_enable[i] = soc_mem_field32_get(unit,
  14013                                                               thdm_mem[i],
  14014                                                               &entry,
  14015                                                               Q_COLOR_LIMIT_ENABLEf);
  14016         }
  14017         soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_LIMIT_DYNAMICf,
  14018                             enable ? cpu_cosq_config->q_limit_dynamic[i] : 0);
  14019         soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_LIMIT_ENABLEf,
  14020                             enable ? cpu_cosq_config->q_limit_enable[i] : 1);
  14021         soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_COLOR_LIMIT_ENABLEf,
  14022                             enable ? cpu_cosq_config->q_color_limit_enable[i] : 1);
  14023         soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_MIN_LIMITf,
  14024                             enable ? cpu_cosq_config->q_min_limit[i] : 0);
  14025         soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_SHARED_LIMITf,
  14026                             enable ? cpu_cosq_config->q_shared_limit[i] : 0);
  14027         cpu_cosq_config->enable = enable;
  14028         BCM_IF_ERROR_RETURN(
  14029             soc_mem_write(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry));
  14030     }
  14031 
  14032     return BCM_E_NONE;
  14033 }
  14034 
  14035 /*
  14036  * Function:
  14037  *      bcm_th_cosq_cpu_cosq_enable_get
  14038  * Purpose:
  14039  *      To get enable/disable status on Rx of packets on the specified CPU cosq.
  14040  * Parameters:
  14041  *      unit          - (IN) Unit number.
  14042  *      cosq          - (IN) CPU Cosq ID
  14043  *      enable        - (OUT) Enable/Disable
  14044  * Returns:
  14045  *      BCM_E_xxx
  14046  */
  14047 int
  14048 bcm_th_cosq_cpu_cosq_enable_get(int unit, bcm_cos_queue_t cosq, int *enable)
  14049 {
  14050     _bcm_th_cosq_cpu_cosq_config_t *cpu_cosq;
  14051     soc_info_t *si;
  14052     int index, hw_enable;
  14053     uint32 entry[SOC_MAX_MEM_WORDS];
  14054     soc_field_t min_limit, shared_limit, limit_enable, dynamic_enable;
  14055     soc_mem_t thdm_mem = MMU_THDM_DB_QUEUE_CONFIG_PIPE0m;
  14056 
  14057     si = &SOC_INFO(unit);
  14058 
  14059     if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) {
  14060         return BCM_E_PARAM;
  14061     }
  14062 
  14063     cpu_cosq = _bcm_th_cosq_cpu_cosq_config[unit][cosq];
  14064     if (!cpu_cosq) {
  14065         return BCM_E_INTERNAL;
  14066     }
  14067 
  14068     /* CPU Port (0) - MC cosq's range from 330 - 378. */
  14069     index = si->port_cosq_base[CMIC_PORT(unit)] + cosq;
  14070     hw_enable = 1;
  14071 
  14072     /* Sync up software record with hardware status. */
  14073     BCM_IF_ERROR_RETURN(soc_mem_read(unit, thdm_mem, MEM_BLOCK_ALL,
  14074                                      index, &entry));
  14075     min_limit = soc_mem_field32_get(unit, thdm_mem, &entry,
  14076                                     Q_MIN_LIMITf);
  14077     shared_limit = soc_mem_field32_get(unit, thdm_mem, &entry,
  14078                                     Q_SHARED_LIMITf);
  14079     limit_enable = soc_mem_field32_get(unit, thdm_mem, &entry,
  14080                                     Q_LIMIT_ENABLEf);
  14081     dynamic_enable = soc_mem_field32_get(unit, thdm_mem, &entry,
  14082                                     Q_LIMIT_DYNAMICf);
  14083     if ((limit_enable != 0) && (dynamic_enable == 0) &&
  14084         (min_limit == 0) && (shared_limit == 0)) {
  14085         hw_enable = 0;
  14086     }
  14087     cpu_cosq->enable = hw_enable;
  14088 
  14089     *enable = cpu_cosq->enable;
  14090     return BCM_E_NONE;
  14091 }
  14092 
  14093 /*
  14094  * Function:
  14095  *      bcm_th2_cosq_buffer_id_multi_get
  14096  * Purpose:
  14097  *      Get mutliple buffer ids associated with a specified port.
  14098  * Parameters:
  14099  *      unit - (IN) BCM device number.
  14100  *      gport - (IN) Port     
  14101  *      cosq - (IN) Reserved field
  14102  *      direction - (IN) Specify ingress or egress direction
  14103  *      array_max - (IN) number of entries to be retrieved  
  14104  *      buf_id_array - (OUT) Buffer id array
  14105  *      array_count - (OUT) Actural buffer id count in buf_id_array 
  14106  * Returns:
  14107  *      BCM_E_XXX
  14108  */
  14109 int
  14110 bcm_th_cosq_buffer_id_multi_get(int unit, bcm_gport_t gport,
  14111                               bcm_cos_queue_t cosq, bcm_cosq_dir_t direction,
  14112                               int array_max, bcm_cosq_buffer_id_t *buf_id_array,
  14113                               int *array_count)
  14114 {
  14115     uint8 ipipe2buf[4][2] = {{0, 1}, {2, 3}, {2, 3}, {0, 1}};
  14116     uint8 epipe2buf[4][2] = {{0, 2}, {0, 2}, {1, 3}, {1, 3}};
  14117 
  14118     bcm_port_t local_port;
  14119     int pipe, i;
  14120 
  14121     if ((direction < bcmCosqIngress) ||
  14122         (direction >= bcmCosqDirectionMaxCount)) {
  14123         return BCM_E_PARAM;
  14124     }
  14125 
  14126     if (!BCM_GPORT_IS_SET(gport)) {
  14127         local_port = gport;
  14128     } else if (BCM_GPORT_IS_LOCAL(gport)) {
  14129         local_port = BCM_GPORT_LOCAL_GET(gport);
  14130     } else if (BCM_GPORT_IS_MODPORT(gport)) {
  14131         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &local_port));
  14132     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  14133         int idx;
  14134         BCM_IF_ERROR_RETURN(_bcm_th_cosq_index_resolve(unit, gport, cosq,
  14135             _BCM_TH_COSQ_INDEX_STYLE_UCAST_QUEUE, &local_port, &idx, NULL));
  14136     } else {
  14137         return BCM_E_PARAM;
  14138     }
  14139 
  14140     if (!SOC_PORT_VALID(unit, local_port)) {
  14141         return BCM_E_PORT;
  14142     }
  14143 
  14144     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  14145 
  14146     if (array_max > _BCM_TH_NUM_BUFFER_PER_PIPE) {
  14147         *array_count = _BCM_TH_NUM_BUFFER_PER_PIPE;
  14148     } else if (array_max >= 0){
  14149         *array_count = array_max;
  14150     } else {
  14151         return BCM_E_PARAM;
  14152     }
  14153 
  14154     for (i = 0; i < *array_count; i++) {
  14155         if (bcmCosqIngress == direction) {
  14156             buf_id_array[i] = ipipe2buf[pipe][i];
  14157         } else {
  14158             buf_id_array[i] = epipe2buf[pipe][i];
  14159         }
  14160     }
  14161     for (i = *array_count; i < array_max; i++) {
  14162         buf_id_array[i] = BCM_COSQ_INVALID_BUF_ID;
  14163     }
  14164 
  14165     return BCM_E_NONE;
  14166 }
  14167 
  14168 
  14169 
  14170 #ifdef BCM_WARM_BOOT_SUPPORT
  14171 int
  14172 bcm_th_cosq_reinit(int unit)
  14173 {
  14174     soc_scache_handle_t scache_handle;
  14175     uint8 *scache_ptr = NULL;
  14176     int *int_scache_ptr = NULL;
  14177     uint16 *u16_scache_ptr = NULL;
  14178     uint32 *u32_scache_ptr = NULL;
  14179     _bcm_th_mmu_info_t *mmu_info = NULL;
  14180     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
  14181     int alloc_size = 0, i, j, pipe = -1, xpe, scache_sz;
  14182     soc_profile_mem_t *profile_mem;
  14183     soc_mem_t wred_config_mem = INVALIDm;
  14184     int index, profile_index, resolution_index;
  14185     int stable_size, rv, num, set_index;
  14186     mmu_wred_config_entry_t qentry;
  14187     uint32 entry[SOC_MAX_MEM_WORDS];
  14188     bcm_port_t port;
  14189     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
  14190     uint32 rval;
  14191     _bcm_bst_device_handlers_t bst_callbks;
  14192     _bcm_th_cosq_cpu_cosq_config_t *cpu_cosq_config_p;
  14193     _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL;
  14194     uint16 recovered_ver = 0;
  14195     int index_min, index_max;
  14196     int additional_scache_sz = 0;
  14197     uint32  qcm_app_status[2], host_mem_size;
  14198     uint32  *host_mem_add;
  14199 
  14200     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  14201     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
  14202         /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/
  14203         return BCM_E_NONE;
  14204     }
  14205 
  14206     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
  14207     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr,
  14208                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
  14209     if (BCM_FAILURE(rv)) {
  14210         return rv;
  14211     }
  14212 
  14213     mmu_info = _bcm_th_mmu_info[unit];
  14214 
  14215     if (mmu_info == NULL) {
  14216         return BCM_E_INIT;
  14217     }
  14218 
  14219     cpu_port_info = _bcm_th_cosq_cpu_port_info[unit];
  14220     if (cpu_port_info == NULL) {
  14221         return BCM_E_INIT;
  14222     }
  14223 
  14224     /* Update mmu_info shared limit parameters */
  14225     int_scache_ptr = (int *) scache_ptr;
  14226     /* shared limits are now recovered from hw */
  14227     int_scache_ptr += 3;
  14228     BCM_IF_ERROR_RETURN(
  14229         soc_th_mmu_get_shared_size(unit,
  14230              mmu_info->ing_shared_limit,
  14231              mmu_info->egr_db_shared_limit,
  14232              mmu_info->egr_qe_shared_limit));
  14233 
  14234     alloc_size = sizeof(_bcm_th_cosq_cpu_port_info_t);
  14235     scache_ptr = (uint8*) int_scache_ptr;
  14236     sal_memcpy(cpu_port_info, scache_ptr, alloc_size);
  14237 
  14238     /* Restore the Queue to Channel Mapping */
  14239     if (recovered_ver <= BCM_WB_VERSION_1_1) {
  14240         BCM_IF_ERROR_RETURN
  14241             (_bcm_cosq_rx_queue_channel_reinit(unit));
  14242     }
  14243 
  14244     scache_ptr += alloc_size;
  14245 
  14246     /* Update IFP_COS_MAP memory profile reference counter */
  14247     profile_mem = _bcm_th_ifp_cos_map_profile[unit];
  14248     num = SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TH_MMU_NUM_INT_PRI;
  14249     u16_scache_ptr = (uint16 *)scache_ptr;
  14250     for (i = 0; i < num; i++) {
  14251         for (j = 0; j < *u16_scache_ptr; j++) {
  14252             SOC_IF_ERROR_RETURN(
  14253                 soc_profile_mem_reference(unit, profile_mem,
  14254                                           i * _TH_MMU_NUM_INT_PRI,
  14255                                           _TH_MMU_NUM_INT_PRI));
  14256         }
  14257         u16_scache_ptr++;
  14258     }
  14259 
  14260     /* Recover CPU queue config information from scache */
  14261     if (recovered_ver >= BCM_WB_VERSION_1_1) {
  14262         cpu_cosq_config_p = _bcm_th_cosq_cpu_cosq_config[unit][0];
  14263         if (cpu_cosq_config_p == NULL) {
  14264             return BCM_E_INIT;
  14265         }
  14266         alloc_size = (SOC_TH_NUM_CPU_QUEUES *
  14267                        sizeof(_bcm_th_cosq_cpu_cosq_config_t));
  14268         scache_ptr = (uint8*) u16_scache_ptr;
  14269         sal_memcpy(cpu_cosq_config_p, scache_ptr, alloc_size);
  14270         scache_ptr += alloc_size;
  14271     }
  14272 
  14273     /* Retriving num_cos value */
  14274     if (recovered_ver >= BCM_WB_VERSION_1_1) {
  14275         int_scache_ptr = (int *) scache_ptr;
  14276         _TH_NUM_COS(unit) = *int_scache_ptr++;
  14277         scache_ptr = (uint8*) int_scache_ptr;
  14278     }
  14279 
  14280     /* Update PRIO2COS_PROFILE register profile reference counter */
  14281     PBMP_PORT_ITER(unit, port) {
  14282         BCM_IF_ERROR_RETURN
  14283             (soc_reg32_get(unit, port_fc_reg, port, 0, &rval));
  14284         profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16;
  14285         SOC_IF_ERROR_RETURN
  14286             (soc_profile_reg_reference(unit, _bcm_th_prio2cos_profile[unit],
  14287                                        profile_index, 16));
  14288     }
  14289 
  14290     /* Update PORT_COS_MAP memory profile reference counter */
  14291     profile_mem = _bcm_th_cos_map_profile[unit];
  14292     PBMP_ALL_ITER(unit, port) {
  14293         SOC_IF_ERROR_RETURN
  14294             (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry));
  14295         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
  14296         SOC_IF_ERROR_RETURN
  14297             (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16));
  14298     }
  14299     if (SOC_INFO(unit).cpu_hg_index != -1) {
  14300         SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL,
  14301                                          SOC_INFO(unit).cpu_hg_index, &entry));
  14302         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
  14303         SOC_IF_ERROR_RETURN
  14304             (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16));
  14305     }
  14306 
  14307     index_min = soc_mem_index_min(unit, SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit,
  14308                                                 MMU_WRED_CONFIGm, 0, 0));
  14309     index_max = soc_mem_index_max(unit, SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit,
  14310                                                 MMU_WRED_CONFIGm, 0, 0));
  14311 
  14312     wred_config_mem = MMU_WRED_CONFIGm;
  14313     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  14314         for (xpe = 0; xpe < NUM_XPE(unit); xpe++) {
  14315             if (SOC_INFO(unit).epipe_xpe_map[pipe] & (1 << xpe)) {
  14316                 for (index = index_min; index < index_max; index++) {
  14317                     BCM_IF_ERROR_RETURN
  14318                         (soc_tomahawk_xpe_mem_read(unit, wred_config_mem, 
  14319                             xpe, pipe, MEM_BLOCK_ALL, index, &qentry));
  14320                     profile_index = soc_mem_field32_get(unit, wred_config_mem,
  14321                                                     &qentry, PROFILE_INDEXf);
  14322                     BCM_IF_ERROR_RETURN(soc_profile_mem_reference
  14323                         (unit, _bcm_th_wred_profile[unit], profile_index, 1));
  14324 
  14325                     if (soc_mem_field32_get(unit, wred_config_mem, &qentry,
  14326                         ECN_MARKING_ENf)) {
  14327                         resolution_index = soc_mem_field32_get(
  14328                             unit, wred_config_mem, &qentry,
  14329                             WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf);
  14330                     } else {
  14331                         resolution_index = soc_mem_field32_get(
  14332                             unit, wred_config_mem, &qentry,
  14333                             WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf);
  14334                     }
  14335                     _bcm_th_wred_resolution_tbl[resolution_index] = 1;
  14336                 }
  14337             }
  14338         }
  14339     }
  14340 
  14341     /* Create gport tree */
  14342     _BCM_TH_MMU_INFO(unit)->gport_tree_created = FALSE;
  14343     PBMP_ALL_ITER(unit, port) {
  14344         if (IS_LB_PORT(unit, port) || IS_CPU_PORT(unit, port)) {
  14345             continue;
  14346         }
  14347         BCM_IF_ERROR_RETURN
  14348             (_bcm_th_cosq_gport_tree_create(unit, port));
  14349     }
  14350     _BCM_TH_MMU_INFO(unit)->gport_tree_created = TRUE;
  14351 
  14352     /* BST reinit */
  14353     sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t));
  14354     bst_callbks.resolve_index = &_bcm_th_bst_index_resolve;
  14355     bst_callbks.reverse_resolve_index = NULL;
  14356     BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks));
  14357 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB)
  14358     if (soc_feature(unit, soc_feature_tcb)){
  14359 #ifdef BCM_TOMAHAWK2_SUPPORT
  14360         BCM_IF_ERROR_RETURN(bcm_th2_cosq_tcb_reinit(unit));
  14361 #endif
  14362     }
  14363 #endif
  14364     /* PFC Deadlock recovery should be initialize
  14365        irrespective of scache version to handle
  14366        upgrades */
  14367     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  14368         BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_init(unit));
  14369     }
  14370 
  14371     /* Recover PFC Deadlock recovery information from scache */
  14372     if (SOC_IS_TOMAHAWK(unit) &&
  14373         soc_feature(unit, soc_feature_pfc_deadlock)) {
  14374         if (recovered_ver >= BCM_WB_VERSION_1_1) {
  14375             pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit);
  14376             if (pfc_deadlock_control == NULL) {
  14377                 return BCM_E_INIT;
  14378             }
  14379             alloc_size = sizeof(_bcm_pfc_deadlock_control_t);
  14380             if (recovered_ver >= BCM_WB_VERSION_1_4) {
  14381                 scache_sz = soc_scache_dictionary_entry_get(unit, 
  14382                                          "_bcm_pfc_deadlock_control_t",
  14383                                          alloc_size);
  14384                 scache_ptr += scache_sz;
  14385                 additional_scache_sz += alloc_size - scache_sz;
  14386             } else {
  14387                 sal_memcpy(pfc_deadlock_control, scache_ptr, alloc_size);
  14388                 scache_ptr += alloc_size;
  14389                 /* Re-set the Hardware Registers/Memory info */
  14390                 BCM_IF_ERROR_RETURN(_bcm_th_pfc_deadlock_init(unit));
  14391                 BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_recovery_reset(unit));
  14392                 pfc_deadlock_control->cosq_inv_mapping_get = _bcm_th_cosq_inv_mapping_get;
  14393             }
  14394         } else {
  14395             additional_scache_sz += sizeof(_bcm_pfc_deadlock_control_t);
  14396         }
  14397     }
  14398     /* Recovery TIME_DOMAINr count reference */
  14399     if (recovered_ver >= BCM_WB_VERSION_1_2) {
  14400         int ii;
  14401         for (ii = 0; ii <  _BCM_TH_NUM_TIME_DOMAIN; ii++) {
  14402             alloc_size =  sizeof(uint32);
  14403             sal_memcpy(&time_domain_info[unit][ii].ref_count, scache_ptr, alloc_size);
  14404             scache_ptr += alloc_size;
  14405         }
  14406     } else {
  14407         additional_scache_sz += _BCM_TH_NUM_TIME_DOMAIN * sizeof(uint32);
  14408     }
  14409 
  14410 #ifdef BCM_TOMAHAWK_SUPPORT
  14411     if (soc_feature(unit, soc_feature_ecn_wred)) {
  14412         if (recovered_ver >= BCM_WB_VERSION_1_3) {
  14413             BCM_IF_ERROR_RETURN(bcmi_xgs5_ecn_reinit(unit, &scache_ptr));
  14414         } else {
  14415             uint32 mpls_ecn_map_size = 0;
  14416             BCM_IF_ERROR_RETURN(
  14417                 bcmi_xgs5_ecn_scache_size_get(unit, &mpls_ecn_map_size));
  14418             additional_scache_sz += mpls_ecn_map_size;
  14419         }
  14420     }
  14421 #endif
  14422 
  14423 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB)
  14424     if (soc_feature(unit, soc_feature_tcb)){
  14425 #ifdef BCM_TOMAHAWK2_SUPPORT
  14426         if (recovered_ver >= BCM_WB_VERSION_1_4) {
  14427             _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info;
  14428             tcb_unit_info = TCB_UNIT_CONTROL(unit);
  14429             TCB_INIT(unit);
  14430 
  14431             alloc_size = sizeof(uint16);
  14432             sal_memcpy(&tcb_unit_info->tcb_config_init_bmp, scache_ptr, alloc_size);
  14433             scache_ptr += alloc_size;
  14434         } else {
  14435             additional_scache_sz += sizeof(uint16);
  14436         }
  14437 #endif
  14438     }
  14439 #else
  14440     if (recovered_ver >= BCM_WB_VERSION_1_4) {
  14441         scache_ptr += sizeof(uint16);
  14442     } else {
  14443         additional_scache_sz += sizeof(uint16);
  14444     }
  14445 #endif
  14446 
  14447     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  14448         pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit);
  14449         if (pfc_deadlock_control == NULL) {
  14450             return BCM_E_INIT;
  14451         }
  14452         if (recovered_ver >= BCM_WB_VERSION_1_4) {
  14453             int priority = 0;
  14454             for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) {
  14455                 sal_memcpy(&pfc_deadlock_control->pfc_cos2pri[i],
  14456                            scache_ptr, sizeof(int)); 
  14457                 scache_ptr += sizeof(int);
  14458                 priority = pfc_deadlock_control->pfc_cos2pri[i];
  14459                 if ((priority >= 0) && (priority < _TH_MMU_NUM_INT_PRI)) {
  14460                     pfc_deadlock_control->hw_cos_idx_inuse[i] = TRUE;
  14461                     pfc_deadlock_control->pfc_pri2cos[priority] = i;
  14462                 }
  14463             }
  14464             sal_memcpy(&pfc_deadlock_control->cb_interval,
  14465                        scache_ptr, sizeof(uint32));
  14466             scache_ptr += sizeof(uint32);
  14467             BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_reinit(unit));
  14468             BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_recovery_reset(unit));
  14469             pfc_deadlock_control->cosq_inv_mapping_get = _bcm_th_cosq_inv_mapping_get;
  14470         } else {
  14471             for (i = 0; i < pfc_deadlock_control->pfc_deadlock_cos_max; i++) {
  14472                 additional_scache_sz += sizeof(int);
  14473             }
  14474             additional_scache_sz += sizeof(uint32);
  14475         }
  14476     }
  14477 
  14478     /* Retriving _bcm_th_wred_resolution_tbl value */
  14479     if (recovered_ver >= BCM_WB_VERSION_1_5) {
  14480         u32_scache_ptr = (uint32 *) scache_ptr;
  14481         for (i = 0; i < _BCM_TH_NUM_WRED_RESOLUTION_TABLE; i++) {
  14482             _bcm_th_wred_resolution_tbl[i] = *u32_scache_ptr++;
  14483         }
  14484     } else {
  14485         additional_scache_sz += (_BCM_TH_NUM_WRED_RESOLUTION_TABLE *
  14486                    sizeof(uint32));;
  14487     }
  14488 
  14489 
  14490     /* realloc scache_handle resource*/
  14491     if (additional_scache_sz != 0) {
  14492         rv = soc_scache_realloc(unit, scache_handle, additional_scache_sz);
  14493         if (SOC_FAILURE(rv)) {
  14494             return rv;
  14495         }
  14496     }
  14497 
  14498     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  14499     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  14500 
  14501     /* Validation check whether core 0 R5 is loaded with QCM app srec file
  14502      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  14503      */
  14504     if ((qcm_app_status[0] == SHR_QCM_APP_STATUS_1) &&
  14505         (qcm_app_status[1] == SHR_QCM_APP_STATUS_2)) {
  14506         host_mem_size = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size)));
  14507         if (host_mem_size >= SHR_QCM_MEM_MIN_SIZE) {
  14508             bcm_th_cosq_burst_monitor_dma_config_set(unit, host_mem_size, &host_mem_add);
  14509         }
  14510     }
  14511 
  14512     return BCM_E_NONE;
  14513 }
  14514 
  14515 int
  14516 bcm_th_cosq_sync(int unit)
  14517 {
  14518     soc_scache_handle_t scache_handle;
  14519     uint8 *scache_ptr;
  14520     uint32 *u32_scache_ptr;
  14521     uint16 *u16_scache_ptr;
  14522     int *int_scache_ptr;
  14523     _bcm_th_mmu_info_t *mmu_info = NULL;
  14524     _bcm_th_cosq_cpu_port_info_t *cpu_port_info = NULL;
  14525     int size = 0, ii;
  14526     int ing_shared_limit_min, egr_db_shared_limit_min, egr_qe_shared_limit_min;
  14527     int xpe_map;
  14528     int rv = BCM_E_NONE, ref_count;
  14529     _bcm_th_cosq_cpu_cosq_config_t **cpu_cosq_config_p;
  14530     _bcm_pfc_deadlock_control_t *pfc_deadlock_control = NULL;
  14531     uint32  qcm_app_status[2], qcm_host_status;
  14532 
  14533     mmu_info = _bcm_th_mmu_info[unit];
  14534     if (mmu_info == NULL) {
  14535         return BCM_E_INIT;
  14536     }
  14537 
  14538     cpu_port_info = _bcm_th_cosq_cpu_port_info[unit];
  14539     if (cpu_port_info == NULL) {
  14540         return BCM_E_INIT;
  14541     }
  14542 
  14543     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
  14544     BCM_IF_ERROR_RETURN
  14545         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
  14546                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL));
  14547 
  14548     /* Cache minimal ing_shared_limit/egr_db_shared_limit/egr_qe_shared_limit */
  14549     xpe_map = SOC_INFO(unit).ipipe_xpe_map[0]|SOC_INFO(unit).ipipe_xpe_map[1];
  14550     _TH_ARRAY_MIN(mmu_info->ing_shared_limit, NUM_XPE(unit), xpe_map, 
  14551         ing_shared_limit_min);
  14552     _TH_ARRAY_MIN(mmu_info->egr_db_shared_limit, NUM_XPE(unit), xpe_map, 
  14553         egr_db_shared_limit_min);
  14554     _TH_ARRAY_MIN(mmu_info->egr_qe_shared_limit, NUM_XPE(unit), xpe_map, 
  14555         egr_qe_shared_limit_min);
  14556     u32_scache_ptr = (uint32*) scache_ptr;
  14557     *u32_scache_ptr++ = ing_shared_limit_min;
  14558     *u32_scache_ptr++ = egr_db_shared_limit_min;
  14559     *u32_scache_ptr++ = egr_qe_shared_limit_min / 4;  /* to keep consistence with old version */
  14560 
  14561     /* Cache _bcm_th_cosq_cpu_port_info_t structure */
  14562     size = sizeof(_bcm_th_cosq_cpu_port_info_t);
  14563     scache_ptr = (uint8*)u32_scache_ptr;
  14564     sal_memcpy(scache_ptr, cpu_port_info, size);
  14565     scache_ptr += size/sizeof(uint8);
  14566 
  14567     /* Cache _bcm_th_ifp_cos_map_profile reference count */
  14568     u16_scache_ptr = (uint16 *)scache_ptr;
  14569     for (ii = 0;
  14570          ii < (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TH_MMU_NUM_INT_PRI);
  14571          ii++) {
  14572         rv = soc_profile_mem_ref_count_get(unit,
  14573                                            _bcm_th_ifp_cos_map_profile[unit],
  14574                                            ii * _TH_MMU_NUM_INT_PRI,
  14575                                            &ref_count);
  14576         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  14577             return rv;
  14578         }
  14579         *u16_scache_ptr++ = (uint16)(ref_count & 0xffff);
  14580     }
  14581 
  14582     /* Sync CPU Queue info */
  14583     cpu_cosq_config_p = _bcm_th_cosq_cpu_cosq_config[unit];
  14584     size = (SOC_TH_NUM_CPU_QUEUES * sizeof(_bcm_th_cosq_cpu_cosq_config_t));
  14585     scache_ptr = (uint8*) u16_scache_ptr;
  14586     sal_memcpy(scache_ptr, *cpu_cosq_config_p, size);
  14587     scache_ptr += (size / sizeof(uint8));
  14588 
  14589     /* Sync num_cos value */
  14590     int_scache_ptr = (int*) scache_ptr;
  14591     *int_scache_ptr++ = _TH_NUM_COS(unit);
  14592     scache_ptr = (uint8 *)int_scache_ptr;
  14593 
  14594     /* Sync PFC Deadlock Control info */
  14595     if (SOC_IS_TOMAHAWK(unit) &&
  14596         soc_feature(unit, soc_feature_pfc_deadlock)) {
  14597         pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit);
  14598         if (pfc_deadlock_control == NULL) {
  14599             return BCM_E_INIT;
  14600         }
  14601         size = sizeof(_bcm_pfc_deadlock_control_t);
  14602         sal_memcpy(scache_ptr, pfc_deadlock_control, size);
  14603         scache_ptr += (size / sizeof(uint8));
  14604         SOC_IF_ERROR_RETURN
  14605             (soc_scache_dictionary_entry_set(unit, 
  14606                                              "_bcm_pfc_deadlock_control_t",
  14607                                              size));
  14608     }
  14609     /* Sync TIME_DOMAINr field and count reference */
  14610     u32_scache_ptr = (uint32*) scache_ptr;
  14611     size = sizeof(uint32);
  14612     for (ii = 0; ii <  _BCM_TH_NUM_TIME_DOMAIN; ii++) {
  14613         sal_memcpy(u32_scache_ptr, &time_domain_info[unit][ii].ref_count, size);
  14614         u32_scache_ptr++;
  14615     }
  14616 
  14617     scache_ptr = (uint8*)u32_scache_ptr;
  14618 #ifdef BCM_TOMAHAWK_SUPPORT
  14619     if (soc_feature(unit, soc_feature_ecn_wred)) {
  14620         BCM_IF_ERROR_RETURN(bcmi_xgs5_ecn_sync(unit, &scache_ptr));
  14621     }
  14622 #endif
  14623 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB)
  14624     if (soc_feature(unit, soc_feature_tcb)){
  14625 #ifdef BCM_TOMAHAWK2_SUPPORT
  14626         _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info;
  14627         tcb_unit_info = TCB_UNIT_CONTROL(unit);
  14628         TCB_INIT(unit);
  14629 
  14630         u16_scache_ptr = (uint16*) scache_ptr;
  14631         size = sizeof(uint16);
  14632         sal_memcpy(u16_scache_ptr, &tcb_unit_info->tcb_config_init_bmp, size);
  14633         u16_scache_ptr ++;
  14634         scache_ptr = (uint8*)u16_scache_ptr;
  14635 #endif
  14636     }
  14637 #else
  14638     u16_scache_ptr = (uint16*) scache_ptr;
  14639     u16_scache_ptr ++;
  14640     scache_ptr = (uint8*)u16_scache_ptr;
  14641 #endif
  14642 
  14643     /* Second around to sync PFC Deadlock Control info */
  14644     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  14645         pfc_deadlock_control = _BCM_UNIT_PFC_DEADLOCK_CONTROL(unit);
  14646         if (pfc_deadlock_control == NULL) {
  14647             return BCM_E_INIT;
  14648         }
  14649         for (ii = 0; ii < pfc_deadlock_control->pfc_deadlock_cos_max; ii++) {
  14650             sal_memcpy(scache_ptr, &pfc_deadlock_control->pfc_cos2pri[ii],
  14651                        sizeof(int));
  14652             scache_ptr += sizeof(int);
  14653         }
  14654         sal_memcpy(scache_ptr, &pfc_deadlock_control->cb_interval,
  14655                    sizeof(uint32));
  14656         scache_ptr += sizeof(uint32);
  14657     }
  14658 
  14659     u32_scache_ptr = (uint32*) scache_ptr;
  14660 
  14661     for (ii = 0; ii < _BCM_TH_NUM_WRED_RESOLUTION_TABLE; ii++) {
  14662         *u32_scache_ptr++ = _bcm_th_wred_resolution_tbl[ii];
  14663     }
  14664 
  14665     scache_ptr = (uint8 *)u32_scache_ptr;
  14666 
  14667     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  14668     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  14669 
  14670     /* Validation check whether core 0 R5 is loaded with QCM app srec file
  14671      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  14672      */
  14673     if ((qcm_app_status[0] == SHR_QCM_APP_STATUS_1) &&
  14674         (qcm_app_status[1] == SHR_QCM_APP_STATUS_2)) {
  14675 
  14676         qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)));
  14677         if (qcm_host_status & SHR_QCM_INIT_STATUS_BIT) {
  14678             bcm_th_cosq_burst_monitor_dma_config_reset(unit);
  14679         }
  14680     }
  14681 
  14682     return BCM_E_NONE;
  14683 }
  14684 
  14685 #endif /* BCM_WARM_BOOT_SUPPORT */
  14686 
  14687 /*
  14688  * Function:
  14689  *     bcm_th_cosq_sw_dump
  14690  * Purpose:
  14691  *     Displays COS Queue information maintained by software.
  14692  * Parameters:
  14693  *     unit - Device unit number
  14694  * Returns:
  14695  *     None
  14696  */
  14697 void
  14698 bcm_th_cosq_sw_dump(int unit)
  14699 {
  14700     bcm_port_t port;
  14701     int ii;
  14702     LOG_CLI((BSL_META_U(unit,
  14703                         "\nSW Information COSQ - Unit %d\n"), unit));
  14704     PBMP_ALL_ITER(unit, port) {
  14705         if (IS_CPU_PORT(unit, port)) {
  14706             (void)_bcm_th_cosq_cpu_port_info_dump(unit);
  14707         }
  14708         (void)_bcm_th_cosq_port_info_dump(unit, port);
  14709     }
  14710     for (ii = 0; ii <  _BCM_TH_NUM_TIME_DOMAIN; ii++) {
  14711         LOG_CLI((BSL_META_U(unit,
  14712                             "\nTIME_DOMAIN[%d] - refcnt %d\n"), ii, 
  14713                             time_domain_info[unit][ii].ref_count));
  14714     }
  14715 
  14716 #ifndef BCM_SW_STATE_DUMP_DISABLE
  14717 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT)
  14718     if(soc_feature(unit, soc_feature_tcb)) {
  14719 #ifdef BCM_TOMAHAWK2_SUPPORT
  14720         (void)bcm_th2_cosq_tcb_sw_dump(unit);
  14721 #endif
  14722     }
  14723 #endif
  14724 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  14725 
  14726     return;
  14727 }
  14728 
  14729 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  14730 /*
  14731  * Function:
  14732  *      bcm_th_cosq_port_attach
  14733  * Purpose:
  14734  *      Initialize Cosq for newly added port
  14735  * Parameters:
  14736  *      unit    - (IN) Unit number.
  14737  *      port    - (IN) Logical port.
  14738  * Returns:
  14739  *      SOC_E_XXX
  14740  */
  14741 int
  14742 bcm_th_cosq_port_attach(int unit, bcm_port_t port)
  14743 {
  14744     _bcm_th_cosq_port_info_t *port_info = NULL;
  14745     int default_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN, default_weight = 1;
  14746     int i;
  14747     uint64 rval64s[16], *prval64s[1];
  14748     uint32 rval, profile_index;
  14749 
  14750     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
  14751         IS_MANAGEMENT_PORT(unit, port)) {
  14752         return BCM_E_PARAM;
  14753     }
  14754 
  14755     /* Increase the reference of defalt PRIO2COS_PROFILE */
  14756     sal_memset(rval64s, 0, sizeof(rval64s));
  14757     prval64s[0] = rval64s;
  14758     BCM_IF_ERROR_RETURN
  14759         (soc_profile_reg_add(unit, _bcm_th_prio2cos_profile[unit],
  14760                              prval64s, 16, &profile_index));
  14761     /* update PORT_LLFC_CFG as default profile might not be 0 */
  14762     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, PORT_LLFC_CFGr, port, 0, &rval));
  14763     soc_reg_field_set(unit, PORT_LLFC_CFGr, &rval, PROFILE_INDEXf, profile_index/16);
  14764     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, PORT_LLFC_CFGr, port, 0, rval));
  14765 
  14766     /* Increase the reference of default COS_MAP_PROFILE */
  14767     BCM_IF_ERROR_RETURN
  14768         (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 0));
  14769     BCM_IF_ERROR_RETURN
  14770         (soc_profile_mem_reference(unit, _bcm_th_cos_map_profile[unit], 0, 0));
  14771 
  14772     /* Create gport tree */
  14773     _BCM_TH_MMU_INFO(unit)->gport_tree_created = FALSE;
  14774     BCM_IF_ERROR_RETURN(_bcm_th_cosq_gport_tree_create(unit, port));
  14775     _BCM_TH_MMU_INFO(unit)->gport_tree_created = TRUE;
  14776 
  14777     /* Set Default Scheduler Configuration on the ports */
  14778     port_info = &_bcm_th_cosq_port_info[unit][port];
  14779     for (i = 0; i < _BCM_TH_NUM_SCHEDULER_PER_PORT; i++) {
  14780         BCM_IF_ERROR_RETURN
  14781             (bcm_th_cosq_gport_sched_set(unit, port_info->sched[i].gport,
  14782                 -1, default_mode, default_weight));
  14783     }
  14784     for (i = 0; i < _BCM_TH_NUM_UCAST_QUEUE_PER_PORT; i++) {
  14785         BCM_IF_ERROR_RETURN
  14786             (bcm_th_cosq_gport_sched_set(unit, port_info->ucast[i].gport,
  14787                 -1, default_mode, default_weight));
  14788     }
  14789     for (i = 0; i < _BCM_TH_NUM_MCAST_QUEUE_PER_PORT; i++) {
  14790         BCM_IF_ERROR_RETURN
  14791             (bcm_th_cosq_gport_sched_set(unit, port_info->mcast[i].gport,
  14792                 -1, default_mode, default_weight));
  14793     }
  14794 
  14795 #if defined(BCM_TOMAHAWK2_SUPPORT)
  14796     /* Update shared limit of new ports in case the shared limit has been
  14797      * adjusted by bcm_cosq_control_set() API */
  14798     BCM_IF_ERROR_RETURN
  14799         (soc_th2_mmu_config_shared_buf_set_hw_port(unit, port,
  14800                                 _BCM_TH_MMU_INFO(unit)->ing_shared_limit,
  14801                                 _BCM_TH_MMU_INFO(unit)->egr_db_shared_limit,
  14802                                 _BCM_TH_MMU_INFO(unit)->egr_qe_shared_limit));
  14803 #endif
  14804     return BCM_E_NONE;
  14805 }
  14806 
  14807 #if defined(BCM_TOMAHAWK2_SUPPORT)
  14808 /*
  14809  * Function:
  14810  *      _bcm_th2_cosq_port_guarantee_reset
  14811  * Purpose:
  14812  *      Reset the guarantee of priority group, uc queue, mc queue to the default
  14813  * Parameters:
  14814  *      unit    - (IN) Unit number.
  14815  *      port    - (IN) Logical port.
  14816  * Returns:
  14817  *      BCM_E_XXX
  14818  */
  14819 STATIC int
  14820 _bcm_th2_cosq_port_guarantee_reset(int unit, bcm_port_t port)
  14821 {
  14822     soc_info_t *si = &SOC_INFO(unit);
  14823     _soc_mmu_device_info_t devcfg;
  14824     int lossless, override, default_mtu_cells, idx, numq;
  14825     int pg_guarantee, uc_guarantee, mc_guarantee;
  14826 
  14827     lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 0);
  14828     override = soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1);
  14829 
  14830     _soc_th2_mmu_init_dev_config(unit, &devcfg, lossless);
  14831     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg.default_mtu_size +
  14832                                                     devcfg.mmu_hdr_byte,
  14833                                                     devcfg.mmu_cell_size);
  14834 
  14835     /* priority group */
  14836     for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) {
  14837         pg_guarantee = 0;
  14838         if (idx == 7 && lossless) {
  14839             pg_guarantee = default_mtu_cells;
  14840         }
  14841         if (!override) {
  14842             _soc_mmu_cfg_property_get_cells
  14843                 (unit, port, spn_PRIGROUP, idx, spn_GUARANTEE, FALSE,
  14844                  &pg_guarantee, devcfg.mmu_cell_size,
  14845                  _MMU_DEFAULT_THRES_TYPE);
  14846             pg_guarantee *= devcfg.mmu_cell_size;
  14847         }
  14848         BCM_IF_ERROR_RETURN
  14849             (_bcm_th_cosq_ing_res_set(unit, port, idx,
  14850                                       bcmCosqControlIngressPortPGMinLimitBytes,
  14851                                       pg_guarantee));
  14852     }
  14853 
  14854     /* UC */
  14855     numq = MIN(si->port_num_uc_cosq[port], NUM_COS(unit));
  14856     for (idx = 0; idx < numq; idx++) {
  14857         uc_guarantee = 0;
  14858         if (!override) {
  14859             _soc_mmu_cfg_property_get_cells
  14860                 (unit, port, spn_QUEUE, idx, spn_GUARANTEE, FALSE,
  14861                  &uc_guarantee, devcfg.mmu_cell_size,
  14862                  _MMU_DEFAULT_THRES_TYPE);
  14863             uc_guarantee *= devcfg.mmu_cell_size;
  14864         }
  14865         BCM_IF_ERROR_RETURN
  14866             (_bcm_th_cosq_egr_queue_set(unit, port, idx,
  14867                                        bcmCosqControlEgressUCQueueMinLimitBytes,
  14868                                        uc_guarantee));
  14869     }
  14870 
  14871     /* MC */
  14872     numq = MIN(si->port_num_cosq[port], NUM_COS(unit));
  14873     for (idx = 0; idx < numq; idx++) {
  14874         mc_guarantee = 0;
  14875         if (!override) {
  14876             _soc_mmu_cfg_property_get_cells
  14877                 (unit, port, spn_MQUEUE, idx, spn_GUARANTEE, FALSE,
  14878                  &mc_guarantee, devcfg.mmu_cell_size,
  14879                  _MMU_DEFAULT_THRES_TYPE);
  14880             mc_guarantee *= devcfg.mmu_cell_size;
  14881         }
  14882         BCM_IF_ERROR_RETURN
  14883             (_bcm_th_cosq_egr_queue_set(unit, port, idx,
  14884                                        bcmCosqControlEgressMCQueueMinLimitBytes,
  14885                                        mc_guarantee));
  14886     }
  14887 
  14888     return BCM_E_NONE;
  14889 }
  14890 #endif
  14891 
  14892 /*
  14893  * Function:
  14894  *      bcm_th_cosq_port_detach
  14895  * Purpose:
  14896  *      Clear cosq configuration of port
  14897  * Parameters:
  14898  *      unit    - (IN) Unit number.
  14899  *      port    - (IN) Logical port.
  14900  * Returns:
  14901  *      SOC_E_XXX
  14902  */
  14903 int
  14904 bcm_th_cosq_port_detach(int unit, bcm_port_t port)
  14905 {
  14906     soc_info_t *si = &SOC_INFO(unit);
  14907     _bcm_th_cosq_port_info_t *port_info = NULL;
  14908     uint32 rval, profile_index;
  14909     uint32 entry[SOC_MAX_MEM_WORDS];
  14910 
  14911     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
  14912         IS_MANAGEMENT_PORT(unit, port)) {
  14913         return BCM_E_PARAM;
  14914     }
  14915 
  14916 #if defined(BCM_TOMAHAWK2_SUPPORT)
  14917     /* When update guarantee of PG/UC/MC via API, the shared limit is adjusted
  14918      * accordingly. So MUST reset the gurarntee to the default value before
  14919      * deleting the port to recover the shared limit. */
  14920     BCM_IF_ERROR_RETURN
  14921         (_bcm_th2_cosq_port_guarantee_reset(unit, port));
  14922 #endif
  14923 
  14924     /* Destroy cosq gport tree on port */
  14925     port_info = &_bcm_th_cosq_port_info[unit][port];
  14926     sal_memset(port_info, 0, sizeof(_bcm_th_cosq_port_info_t));
  14927 
  14928     /* Decrease the reference of defalt PRIO2COS_PROFILE */
  14929     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, PORT_LLFC_CFGr, port, 0, &rval));
  14930     profile_index =
  14931         soc_reg_field_get(unit, PORT_LLFC_CFGr, rval, PROFILE_INDEXf) * 16;
  14932     BCM_IF_ERROR_RETURN
  14933         (soc_profile_reg_delete(unit, _bcm_th_prio2cos_profile[unit],
  14934                                 profile_index));
  14935 
  14936     /* Decrease the reference of COS_MAP_PROFILE */
  14937     SOC_IF_ERROR_RETURN
  14938         (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry));
  14939     profile_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
  14940     SOC_IF_ERROR_RETURN
  14941         (soc_profile_mem_delete(unit, _bcm_th_cos_map_profile[unit],
  14942                                 profile_index * 16));
  14943 
  14944     /* Clear cosq */
  14945     si->port_num_cosq[port] = 0;
  14946     si->port_cosq_base[port] = 0;
  14947     si->port_num_uc_cosq[port] = 0;
  14948     si->port_uc_cosq_base[port] = 0;
  14949     si->port_num_ext_cosq[port] = 0;
  14950 
  14951     return BCM_E_NONE;
  14952 }
  14953 #endif /* BCM_TOMAHAWK2_SUPPORT BCM_TRIDENT3_SUPPORT */
  14954 
  14955 int bcm_th_cosq_burst_monitor_dma_config_reset(int unit)
  14956 {
  14957     uint32  qcm_app_status[2], qcm_host_status, qcm_uc_status, time_count;
  14958     uint32  *read_addr_ptr, read_addr;
  14959 
  14960     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  14961     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  14962 
  14963     /* Validation check whether core 0 R5 is loaded with CM app srec file
  14964      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  14965      */
  14966     if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) ||
  14967         (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) {
  14968         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  14969                   "load CM APP srec file to core 0\n")));
  14970         return BCM_E_UNAVAIL;
  14971     }
  14972 
  14973     qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)));
  14974     if (!(qcm_host_status & SHR_QCM_INIT_STATUS_BIT)) {
  14975         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  14976                   "shared memory not allocated yet\n")));
  14977         return BCM_E_INIT;
  14978     }
  14979     read_addr = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr)));
  14980     read_addr_ptr = (uint32 *)soc_cm_p2l(unit, read_addr);
  14981 
  14982     qcm_host_status = (qcm_host_status & (~SHR_QCM_INIT_STATUS_BIT));
  14983     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)), (uint32)qcm_host_status);
  14984 
  14985     time_count = 0;
  14986     while (1) {
  14987         qcm_uc_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(uc_status)));
  14988         qcm_uc_status = qcm_uc_status & SHR_QCM_INIT_STATUS_BIT;
  14989         if (!qcm_uc_status) {
  14990             break;
  14991         }
  14992         ++time_count;
  14993         if ((time_count * QCM_UC_STATUS_TIMEOUT) > QCM_UC_MSG_TIMEOUT) {
  14994             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  14995                       "CM APP R5 core 0 does not responded\n")));
  14996             return BCM_E_TIMEOUT;
  14997         }
  14998         sal_usleep(QCM_UC_STATUS_TIMEOUT);
  14999     }
  15000     soc_cm_sfree(unit, read_addr_ptr);
  15001 
  15002     return BCM_E_NONE;
  15003 }
  15004 
  15005 int bcm_th_cosq_burst_monitor_dma_config_set(int unit,
  15006                                              uint32 host_mem_size,
  15007                                              uint32 **host_mem_add)
  15008 {
  15009     uint32 qcm_app_status[2], qcm_host_status, qcm_uc_status, shared_mem_size, share_mem_add, endianess;
  15010     int    time_count, rv;
  15011 
  15012     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  15013     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  15014 
  15015     /* Validation check whether core 0 R5 is loaded with QCM app srec file
  15016      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  15017      */
  15018     if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) ||
  15019         (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) {
  15020         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15021                   "load QCM app srec file to core 0\n")));
  15022         return BCM_E_UNAVAIL;
  15023     }
  15024 
  15025     qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)));
  15026     if (qcm_host_status & SHR_QCM_INIT_STATUS_BIT) {
  15027         if (host_mem_size == 0) {
  15028             rv = bcm_th_cosq_burst_monitor_dma_config_reset(unit);
  15029             *host_mem_add = NULL;
  15030             soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr)), (uint32)0);
  15031             soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size)), (uint32)0);
  15032             return rv;
  15033         } else {
  15034             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15035                       "already configured\n")));
  15036             return BCM_E_PARAM;
  15037         }
  15038     }
  15039 
  15040     qcm_host_status = qcm_host_status | SHR_QCM_INIT_STATUS_BIT;
  15041     shared_mem_size = (uint32)sizeof(struct bcm_cosq_burst_output_s);
  15042     shared_mem_size = host_mem_size - (host_mem_size % shared_mem_size);
  15043 
  15044     if (shared_mem_size < SHR_QCM_MEM_MIN_SIZE) {
  15045         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15046                   "except's minimum shared memory size : %x\n"),
  15047                   SHR_QCM_MEM_MIN_SIZE));
  15048         return BCM_E_PARAM;
  15049     }
  15050 
  15051     /* Ensure QCM app host memory is not NULL */
  15052     *host_mem_add = (uint32 *) soc_cm_salloc(unit, host_mem_size, "Host buffer");
  15053     if (*host_mem_add == NULL) {
  15054         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15055                   "host memory address NULL\n")));
  15056         return BCM_E_PARAM;
  15057     }
  15058 
  15059     sal_memset(*host_mem_add, 0, host_mem_size);
  15060     share_mem_add = (uint32)soc_cm_l2p(unit, *host_mem_add);
  15061 
  15062     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr)), (uint32)share_mem_add);
  15063     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size)), (uint32)shared_mem_size);
  15064 
  15065     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(drop_table_index)),
  15066                      (uint32)soc_mem_base(unit, MMU_CTR_UC_DROP_MEM_XPE0_PIPE0m));
  15067     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(drop_table_index) + 4),
  15068                      (uint32)soc_mem_base(unit, MMU_CTR_UC_DROP_MEM_XPE0_PIPE1m));
  15069     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(drop_table_index) + 8),
  15070                      (uint32)soc_mem_base(unit, MMU_CTR_UC_DROP_MEM_XPE1_PIPE2m));
  15071     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(drop_table_index) + 12),
  15072                      (uint32)soc_mem_base(unit, MMU_CTR_UC_DROP_MEM_XPE1_PIPE3m));
  15073 
  15074     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(egr_table_index)),
  15075                      (uint32)soc_mem_base(unit, EGR_PERQ_XMT_COUNTERSm));
  15076 
  15077     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(queues_per_pipe)),
  15078                      (uint32)SOC_TH_MMU_GP_UCQ_NUM);
  15079     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(queues_per_port)),
  15080                      (uint32)_BCM_TH_NUM_UCAST_QUEUE_PER_PORT);
  15081     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(ports_per_pipe)),
  15082                      (uint32)_TH_MMU_PORTS_PER_PIPE);
  15083     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(num_pipes)),
  15084                      (uint32)_TH_NUM_PIPES);
  15085     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(num_xpe_per_pipe)),
  15086                      (uint32)_BCM_TH_NUM_BUFFER_PER_PIPE);
  15087 
  15088     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)), (uint32)qcm_host_status);
  15089 
  15090     time_count = 0;
  15091     while (1) {
  15092         qcm_uc_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(uc_status)));
  15093         qcm_uc_status = qcm_uc_status & SHR_QCM_INIT_STATUS_BIT;
  15094         if (qcm_host_status == qcm_uc_status) {
  15095             break;
  15096         }
  15097         ++time_count;
  15098         if ((time_count * QCM_UC_STATUS_TIMEOUT) > QCM_UC_MSG_TIMEOUT) {
  15099             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15100                       "QCM app R5 core 0 does not responded\n")));
  15101             return BCM_E_TIMEOUT;
  15102         }
  15103         sal_usleep(QCM_UC_STATUS_TIMEOUT);
  15104     }
  15105     if (*host_mem_add[0] == 0x1000000) {
  15106         endianess = 1;
  15107     } else {
  15108         endianess = 0;
  15109     }
  15110     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(endianess)), (uint32)endianess);
  15111 
  15112     return BCM_E_NONE;
  15113 }
  15114 
  15115 int bcm_th_cosq_burst_monitor_dma_config_get(int unit,
  15116                                              uint32 *host_mem_size,
  15117                                              uint32 **host_mem_add)
  15118 {
  15119     uint32  qcm_app_status[2], qcm_host_status;
  15120     uint32  host_addr;
  15121 
  15122     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  15123     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  15124 
  15125     /* Validation check whether core 0 R5 is loaded with CM app srec file
  15126      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  15127      */
  15128     if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) || (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) {
  15129         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15130                   "load CM APP srec file to core 0\n")));
  15131         return BCM_E_UNAVAIL;
  15132     }
  15133 
  15134     qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)));
  15135     if (!(qcm_host_status & SHR_QCM_INIT_STATUS_BIT)) {
  15136         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15137                   "shared memory not allocated yet\n")));
  15138         return BCM_E_INIT;
  15139     }
  15140     host_addr = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr)));
  15141     *host_mem_size = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size)));
  15142 
  15143     *host_mem_add = (uint32 *)soc_cm_p2l(unit, host_addr);
  15144 
  15145     return BCM_E_NONE;
  15146 }
  15147 
  15148 STATIC
  15149 void bcm_th_cosq_burst_linked_list_clean(int unit, qcm_gport_port_queue_map_t  *head)
  15150 {
  15151     qcm_gport_port_queue_map_t  *temp, *newnode;
  15152     temp = head;
  15153     while(temp) {
  15154         newnode = temp;
  15155         temp = temp->next;
  15156         soc_cm_sfree(unit, newnode);
  15157     }
  15158 }
  15159 
  15160 
  15161 int bcm_th_cosq_burst_monitor_set(int unit, int num_gports,
  15162                                   bcm_gport_t *gport_list)
  15163 {
  15164     uint32                     qcm_app_status[2], qcm_host_status, qcm_uc_status;
  15165     qcm_gport_port_queue_map_t *head, *newnode, *temp;
  15166     int                        phy_port, pipe, mmu_port, local_mmu_port, i, index, time_count, rv = BCM_E_NONE;
  15167     _bcm_th_cosq_node_t        *node;
  15168     bcm_port_t                 local_port;
  15169     soc_info_t                 *si;
  15170 
  15171     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  15172     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  15173 
  15174     /* Validation check whether core 0 R5 is loaded with QCM app srec file
  15175      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  15176      */
  15177     if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) ||
  15178         (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) {
  15179         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15180                   "load QCM app srec file to core 0\n")));
  15181         return BCM_E_UNAVAIL;
  15182     }
  15183 
  15184     qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)));
  15185     if (!(qcm_host_status & SHR_QCM_INIT_STATUS_BIT)) {
  15186         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15187                   "set shared memory\n")));
  15188         return BCM_E_INIT;
  15189     }
  15190 
  15191     if (gport_list == NULL) {
  15192         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15193                   "gport parameter NULL\n")));
  15194         return BCM_E_PARAM;
  15195     }
  15196 
  15197     if (num_gports > SHR_QCM_MAX_GPORT_MONITOR) {
  15198         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15199                   "Maximum number of entries :%d\n"),
  15200                   SHR_QCM_MAX_GPORT_MONITOR));
  15201         return BCM_E_PARAM;
  15202     }
  15203 
  15204     head = (qcm_gport_port_queue_map_t *)0;
  15205     qcm_host_status = qcm_host_status ^ SHR_QCM_CONFIG_STATUS_BIT;
  15206     si = &SOC_INFO(unit);
  15207 
  15208     for (i = 0; i < num_gports; i++) {
  15209         if (!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport_list[i]))) {
  15210             bcm_th_cosq_burst_linked_list_clean(unit, head);
  15211             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15212                       "%x gport is non unicast queue type"
  15213                       "Only uincast type gport are alone monitored\n"),
  15214                       gport_list[i]));
  15215             return BCM_E_PARAM;
  15216         }
  15217         newnode = (qcm_gport_port_queue_map_t *) soc_cm_salloc(unit,
  15218                                                               sizeof(struct qcm_gport_port_queue_map_s),
  15219                                                               "microburst temp linked list");
  15220 
  15221         if (newnode == NULL) {
  15222             bcm_th_cosq_burst_linked_list_clean(unit, head);
  15223             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15224                       "Failed to create local memory\n")));
  15225             return BCM_E_MEMORY;
  15226         }
  15227         sal_memset(newnode, 0, sizeof(struct qcm_gport_port_queue_map_s));
  15228         newnode->next=(qcm_gport_port_queue_map_t *)0;
  15229 
  15230         rv = _bcm_th_cosq_node_get(unit, gport_list[i], NULL, &local_port,
  15231                                    NULL, &node);
  15232 
  15233         if ((BCM_E_NONE != rv) || (local_port < 0)) {
  15234             bcm_th_cosq_burst_linked_list_clean(unit, head);
  15235             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15236                       "gport %x with wrong local port value\n"),
  15237                       gport_list[i]));
  15238             return rv;
  15239         }
  15240 
  15241         rv = soc_port_pipe_get(unit, local_port, &pipe);
  15242         if (BCM_E_NONE != rv) {
  15243             bcm_th_cosq_burst_linked_list_clean(unit, head);
  15244             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15245                       "gport %x with wrong pipe\n"),
  15246                       gport_list[i]));
  15247             return rv;
  15248         }
  15249 
  15250         newnode->queue_num = node->hw_index % _BCM_TH_NUM_UCAST_QUEUE_PER_PORT;
  15251         if (newnode->queue_num >= _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) {
  15252             bcm_th_cosq_burst_linked_list_clean(unit, head);
  15253             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15254                       "gport %x with wrong queue number\n"),
  15255                       gport_list[i]));
  15256             return BCM_E_PORT;
  15257         }
  15258         phy_port = si->port_l2p_mapping[local_port];
  15259         mmu_port = si->port_p2m_mapping[phy_port];
  15260         local_mmu_port = mmu_port & (SOC_TH_MMU_PORT_STRIDE - 1);
  15261         newnode->pipe_num =  pipe;
  15262         newnode->gport = gport_list[i];
  15263         newnode->port_num = local_mmu_port;
  15264         newnode->global_num = (newnode->pipe_num * SOC_TH_MMU_GP_UCQ_NUM) +
  15265                                (local_mmu_port * _BCM_TH_NUM_UCAST_QUEUE_PER_PORT) +
  15266                                newnode->queue_num;
  15267 
  15268         if (head == NULL || (head)->global_num >= newnode->global_num) {
  15269             newnode->next = head;
  15270             head = newnode;
  15271         } else {
  15272             temp = head;
  15273             while ((temp->next != NULL) &&
  15274                    (temp->next->global_num < newnode->global_num)) {
  15275                 temp = temp->next;
  15276             }
  15277             newnode->next = temp->next;
  15278             temp->next = newnode;
  15279         }
  15280     }
  15281 
  15282     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(total_num_gports)), (uint32)num_gports);
  15283     temp = head;
  15284     index = 0;
  15285     while(temp) {
  15286         uint32 port_pipe_queue_num = (((temp->port_num & 0xFFFF) << 16) |
  15287                                       ((temp->pipe_num & 0xF) << 12) |
  15288                                       (temp->queue_num & 0xFFF));
  15289         soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(port_pipe_queue) + (index * 4)), (uint32)temp->gport);
  15290         soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(port_pipe_queue) + ((index + 1) * 4)), (uint32)port_pipe_queue_num);
  15291         newnode = temp;
  15292         temp = temp->next;
  15293         soc_cm_sfree(unit, newnode);
  15294         index = index + 2;
  15295     }
  15296     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)), (uint32)qcm_host_status);
  15297     qcm_host_status = qcm_host_status & SHR_QCM_CONFIG_STATUS_BIT;
  15298 
  15299     time_count = 0;
  15300     while (1) {
  15301         qcm_uc_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(uc_status)));
  15302         qcm_uc_status = qcm_uc_status & SHR_QCM_CONFIG_STATUS_BIT;
  15303         if (qcm_host_status == qcm_uc_status) {
  15304             break;
  15305         }
  15306         ++time_count;
  15307         if ((time_count * QCM_UC_STATUS_TIMEOUT) > QCM_UC_MSG_TIMEOUT) {
  15308             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15309                       "QCM app R5 core 0 does not responded\n")));
  15310             return BCM_E_TIMEOUT;
  15311         }
  15312         sal_usleep(QCM_UC_STATUS_TIMEOUT);
  15313     }
  15314     qcm_uc_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(uc_status)));
  15315 
  15316     return (qcm_uc_status >> SHR_QCM_INIT_STATUS_BIT);
  15317 }
  15318 
  15319 int bcm_th_cosq_burst_monitor_get(int unit, int max_gports,
  15320                                   bcm_gport_t *gport_list, int *num_gports)
  15321 {
  15322     uint32  qcm_app_status[2], qcm_host_status, i, entries_transfer;
  15323 
  15324     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  15325     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  15326 
  15327     /* Validation check whether core 0 R5 is loaded with QCM app srec file
  15328      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  15329      */
  15330     if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) ||
  15331         (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) {
  15332         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15333                   "load QCM app srec file to core 0\n")));
  15334         return BCM_E_UNAVAIL;
  15335     }
  15336 
  15337     qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)));
  15338     if (!(qcm_host_status & SHR_QCM_INIT_STATUS_BIT)) {
  15339         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15340                   "set shared memory\n")));
  15341         return BCM_E_INIT;
  15342     }
  15343 
  15344     if (gport_list == NULL) {
  15345         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  15346                   "gport parameter NULL\n")));
  15347         return BCM_E_PARAM;
  15348     }
  15349 
  15350     *num_gports = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + (sram_offset(total_num_gports))));
  15351 
  15352     if (!max_gports) {
  15353         return BCM_E_NONE;
  15354     } else if (*num_gports > max_gports) {
  15355         entries_transfer = max_gports;
  15356     } else {
  15357         entries_transfer = *num_gports;
  15358     }
  15359 
  15360     sal_memset(gport_list, 0, (sizeof(bcm_gport_t) * max_gports));
  15361 
  15362     for (i = 0; i < entries_transfer; i++) {
  15363         gport_list[i] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + (sram_offset(port_pipe_queue)) + (i * 2 * 4)));
  15364     }
  15365 
  15366     return BCM_E_NONE;
  15367 
  15368 }
  15369 #endif /* BCM_TOMAHAWK_SUPPORT */