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


      1 
      2 /*
      3  * 
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * COS Queue Management
      9  * Purpose: API to set different cosq, priorities, and scheduler registers.
     10  */
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <soc/defs.h>
     15 #include <sal/core/libc.h>
     16 
     17 #if defined(BCM_TRIDENT3_SUPPORT)
     18 #include <soc/drv.h>
     19 #include <soc/scache.h>
     20 #include <soc/profile_mem.h>
     21 #include <soc/debug.h>
     22 #include <soc/helix5.h>
     23 
     24 #include <bcm/debug.h>
     25 #include <bcm/error.h>
     26 #include <bcm/cosq.h>
     27 #include <bcm_int/esw/mbcm.h>
     28 #include <bcm_int/esw/stack.h>
     29 #include <bcm_int/esw/cosq.h>
     30 #include <bcm_int/esw/virtual.h>
     31 #include <bcm_int/esw/helix5.h>
     32 #include <bcm_int/esw/trident.h>
     33 #include <bcm_int/esw_dispatch.h>
     34 #include <bcm_int/esw/ecn.h>
     35 #include <bcm_int/bst.h>
     36 #include <bcm_int/esw/pfc_deadlock.h>
     37 
     38 #if defined(INCLUDE_PSTATS)
     39 #include <bcm_int/esw/pstats.h>
     40 #endif /* INCLUDE_PSTATS */
     41 
     42 
     43 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT)
     44 #include <bcm_int/esw/tcb.h>
     45 #endif
     46 
     47 #if defined(BCM_TOMAHAWK2_SUPPORT)
     48 #include <bcm_int/esw/tomahawk2.h>
     49 #include <soc/tomahawk2.h>
     50 #endif
     51 #ifdef BCM_WARM_BOOT_SUPPORT
     52 #include <bcm_int/esw/switch.h>
     53 #endif /* BCM_WARM_BOOT_SUPPORT */
     54 
     55 /* COS default value for HX5 is assumed to be 8 */
     56 #define _BCM_HX5_COS_DEFAULT           8
     57 #define _HX5_NUM_COS_MAP_ENTRY         16
     58 #define _HX5_WIRELESS_COS_MAP_BASE     64
     59 /* Number of Class of Service Supported */
     60 #define _BCM_HX5_NUM_COS(unit) NUM_COS(unit)
     61 
     62 #define HX5_WRED_CELL_FIELD_MAX       0x3ffff
     63 #define HX5_WRED_PROFILE_NUM          9
     64 
     65 /* Number of logical Ports */
     66 #define _BCM_HX5_NUM_PORTS 72
     67 /* Number of HG/stacking/uplink  Ports */
     68 #define _BCM_HX5_NUM_ST_PORTS 16
     69 
     70 /* HX5 supports 8 PFC priorities */
     71 #define _BCM_HX5_NUM_PFC_CLASS  8
     72 
     73 /* Base l3 queue number for down link port */
     74 #define _HX5_BASE_L3QUEUE      416
     75 /* Base l2 queue number for down link port */
     76 #define _HX5_BASE_L2QUEUE      416
     77 /* Base l1 queue number for down link port */
     78 #define _HX5_BASE_L1QUEUE      64
     79 /* Base l0 queue number for down link port */
     80 #define _HX5_BASE_L0QUEUE      48
     81 
     82 #define _HX5_ST_NUML0_NODES       3
     83 #define _HX5_ST_NUML1_NODES       4
     84 #define _HX5_ST_NUML2_NODES       26
     85 
     86 #define _HX5_NUML0_NODES          1
     87 #define _HX5_NUML1_NODES          2
     88 #define _HX5_NUML2_NODES          16
     89 
     90 #define _HX5_CPU_LO_NODE_BASE     103
     91 #define _HX5_CPU_L1_NODE_BASE     173
     92 #define _HX5_CPU_L2_NODE_BASE     1290
     93 
     94 #define _HX5_CPU_NUML0_NODES      1
     95 #define _HX5_CPU_NUML1_NODES      1
     96 #define _HX5_CPU_NUML2_NODES      10
     97 
     98 #define _BCM_HX5_NUM_SAFC_CLASS  16
     99 
    100 /* Number of COSQs configured for this unit */
    101 #define BCM_HX5_NUM_COS(unit) NUM_COS(unit)
    102 
    103 #define _HX5_IS_ST_PORT(unit, mmu_port) \
    104     ((mmu_port < 16) ? 1 : 0)
    105 
    106 
    107 
    108 #define _HX5_PORT_INDEX_GET(unit, mmu_port, index)          \
    109     do {                                                    \
    110         if (_HX5_IS_ST_PORT(unit, mmu_port)) {              \
    111                 index = mmu_port;                           \
    112         } else {                                            \
    113                 index = mmu_port - _BCM_HX5_NUM_ST_PORTS;   \
    114         }                                                   \
    115     } while (0)
    116 
    117 
    118 
    119 #define _HX5_PORT_NUM_COS(unit, port) \
    120     ((IS_CPU_PORT(unit, port)) ? NUM_CPU_COSQ(unit) : \
    121     (IS_LB_PORT(unit, port)) ? 10 : BCM_HX5_NUM_COS(unit))
    122 
    123 #define _BCM_HX5_NUM_TIME_DOMAIN    4
    124 
    125 /* Here cosq is < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT */
    126 #define HX5_ST_SCHED_LEVEL_GET(unit, cosq) \
    127         ((cosq < 3) ? SOC_HX5_NODE_LVL_L0 : (cosq >= 3 && cosq < 7) ? SOC_HX5_NODE_LVL_L1 : SOC_HX5_NODE_LVL_L2)
    128 
    129 /* Here cosq is < SOC_HX5_NUM_SCHEDULER_PER_PORT */
    130 #define HX5_SCHED_LEVEL_GET(unit, cosq) \
    131         ((cosq < 1) ? SOC_HX5_NODE_LVL_L0 : (cosq >= 1 && cosq < 3) ? SOC_HX5_NODE_LVL_L1 : SOC_HX5_NODE_LVL_L2)
    132 
    133 #define HX5_CPU_SCHED_LEVEL_GET(unit, cosq) \
    134         ((cosq < 1) ? SOC_HX5_NODE_LVL_L0 : (cosq == 1) ? SOC_HX5_NODE_LVL_L1 : SOC_HX5_NODE_LVL_L2)
    135 
    136 #define _BCM_HX5_NUM_TIME_DOMAIN    4
    137 
    138 typedef struct _bcm_hx5_cosq_time_info_s {
    139     uint32 ref_count;
    140 } _bcm_hx5_cosq_time_info_t;
    141 
    142 STATIC _bcm_hx5_cosq_time_info_t hx5_time_domain_info[BCM_MAX_NUM_UNITS][_BCM_HX5_NUM_TIME_DOMAIN];
    143 /* WRED resolution table */
    144 #define _BCM_HX5_NUM_WRED_RESOLUTION_TABLE   4
    145 STATIC uint32 _bcm_hx5_wred_resolution_tbl[_BCM_HX5_NUM_WRED_RESOLUTION_TABLE] = {
    146     1,
    147     0,
    148     0,
    149     0,
    150 };
    151 
    152 
    153 typedef struct _bcm_hx5_cosq_cpu_cosq_config_s {
    154     /* All MC queues have DB[idx 0] and MCQE[idx 1] space */
    155     int q_min_limit[2];
    156     int q_shared_limit[2];
    157     uint8 q_limit_dynamic[2];
    158     uint8 q_limit_enable[2];
    159     uint8 q_color_limit_enable[2];
    160     uint8 enable;
    161 } _bcm_hx5_cosq_cpu_cosq_config_t;
    162 
    163 typedef struct _bcm_hx5_cosq_node_s {
    164     bcm_gport_t gport;
    165     int numq;
    166     int level;
    167     int hw_index;
    168     int in_use;
    169     bcm_gport_t parent_gport;
    170 } _bcm_hx5_cosq_node_t;
    171 
    172 
    173 typedef struct _bcm_hx5_cosq_st_port_info_s {
    174     _bcm_hx5_cosq_node_t ucast[SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT];
    175     _bcm_hx5_cosq_node_t mcast[SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT];
    176     _bcm_hx5_cosq_node_t sched[SOC_HX5_NUM_SCHEDULER_PER_ST_PORT];
    177 } _bcm_hx5_cosq_st_port_info_t;
    178 
    179 typedef struct _bcm_hx5_cosq_port_info_s {
    180     _bcm_hx5_cosq_node_t ucast[SOC_HX5_NUM_UCAST_QUEUE_PER_PORT];
    181     _bcm_hx5_cosq_node_t mcast[SOC_HX5_NUM_MCAST_QUEUE_PER_PORT];
    182     _bcm_hx5_cosq_node_t sched[SOC_HX5_NUM_SCHEDULER_PER_PORT];
    183 } _bcm_hx5_cosq_port_info_t;
    184 
    185 typedef struct _bcm_hx5_cosq_cpu_port_info_s {
    186     _bcm_hx5_cosq_node_t sched[SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT];
    187     _bcm_hx5_cosq_node_t mcast[SOC_HX5_NUM_CPU_QUEUES];
    188 } _bcm_hx5_cosq_cpu_port_info_t;
    189 
    190 typedef struct _bcm_hx5_mmu_info_s {
    191     _bcm_hx5_cosq_port_info_t *_bcm_hx5_port_info;
    192     _bcm_hx5_cosq_cpu_port_info_t *_bcm_hx5_cpu_port_info;
    193     _bcm_hx5_cosq_st_port_info_t *_bcm_hx5_st_port_info;
    194     int gport_tree_created; /* FALSE: No GPORT tree exists */
    195 } _bcm_hx5_mmu_info_t;
    196 
    197 STATIC _bcm_hx5_mmu_info_t *_bcm_hx5_mmu_info[BCM_MAX_NUM_UNITS]; /* MMU info */
    198 STATIC _bcm_hx5_cosq_port_info_t *_bcm_hx5_cosq_port_info[BCM_MAX_NUM_UNITS];
    199 STATIC _bcm_hx5_cosq_st_port_info_t *_bcm_hx5_cosq_st_port_info[BCM_MAX_NUM_UNITS];
    200 STATIC _bcm_hx5_cosq_cpu_port_info_t *_bcm_hx5_cosq_cpu_port_info[BCM_MAX_NUM_UNITS];
    201 STATIC _bcm_hx5_cosq_cpu_cosq_config_t
    202     *_bcm_hx5_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][SOC_HX5_NUM_CPU_QUEUES];
    203 
    204 STATIC soc_profile_mem_t *_bcm_hx5_ifp_cos_map_profile[BCM_MAX_NUM_UNITS];
    205 
    206 typedef enum {
    207     _BCM_HX5_COSQ_TYPE_UCAST,
    208     _BCM_HX5_COSQ_TYPE_MCAST
    209 } _bcm_hx5_cosq_type_t;
    210 
    211 /* Memory Profiles */
    212 STATIC soc_profile_mem_t *_bcm_hx5_cos_map_profile[BCM_MAX_NUM_UNITS];
    213 STATIC soc_profile_mem_t *_bcm_hx5_wred_profile[BCM_MAX_NUM_UNITS];
    214 STATIC soc_profile_reg_t *_bcm_hx5_prio2cos_profile[BCM_MAX_NUM_UNITS];
    215 
    216 #define _BCM_HX5_MMU_INFO(unit) _bcm_hx5_mmu_info[(unit)]
    217 
    218 #define _BCM_HX5_CPU_COS_MAPS_RSVD   9
    219 #define _BCM_HX5_INT_PRI_8_15_MASK   0x8
    220 #define _BCM_HX5_INT_PRI_0_7_MASK    0xf
    221 
    222 /*
    223  * index: degree, value: contangent(degree) * 100
    224  * max value is 0xffff (16-bit) at 0 degree
    225  * Same as TD2.
    226  */
    227 STATIC int
    228 _bcm_hx5_cotangent_lookup_table[] =
    229 {
    230     /*  0.. 5 */  65535, 5728, 2863, 1908, 1430, 1143,
    231     /*  6..11 */    951,  814,  711,  631,  567,  514,
    232     /* 12..17 */    470,  433,  401,  373,  348,  327,
    233     /* 18..23 */    307,  290,  274,  260,  247,  235,
    234     /* 24..29 */    224,  214,  205,  196,  188,  180,
    235     /* 30..35 */    173,  166,  160,  153,  148,  142,
    236     /* 36..41 */    137,  132,  127,  123,  119,  115,
    237     /* 42..47 */    111,  107,  103,  100,   96,   93,
    238     /* 48..53 */     90,   86,   83,   80,   78,   75,
    239     /* 54..59 */     72,   70,   67,   64,   62,   60,
    240     /* 60..65 */     57,   55,   53,   50,   48,   46,
    241     /* 66..71 */     44,   42,   40,   38,   36,   34,
    242     /* 72..77 */     32,   30,   28,   26,   24,   23,
    243     /* 78..83 */     21,   19,   17,   15,   14,   12,
    244     /* 84..89 */     10,    8,    6,    5,    3,    1,
    245     /* 90     */      0
    246 };
    247 
    248 /*
    249  * Function:
    250  *     _bcm_hx5_ecn_init
    251  * Purpose:
    252  *     Initialize (clear) all ECN memories/registers
    253  * Parameters:
    254  *     unit - unit number
    255  * Returns:
    256  *     BCM_E_XXX
    257  */
    258 STATIC int
    259 _bcm_hx5_ecn_init(int unit)
    260 {
    261     egr_tunnel_ecn_encap_entry_t egr_tunnel_ecn_encap;
    262     int count, i;
    263     uint32  fld_val;
    264 
    265     BCM_IF_ERROR_RETURN(_bcm_esw_ecn_init(unit));
    266 
    267     if (!SOC_WARM_BOOT(unit)) {
    268         count = soc_mem_index_count(unit, EGR_TUNNEL_ECN_ENCAPm);
    269         for (i = 0; i < count; i++) {
    270             sal_memset(&egr_tunnel_ecn_encap, 0, sizeof(egr_tunnel_ecn_encap));
    271             switch (i%4) {
    272                 case 0:
    273                     fld_val = _BCM_ECN_INT_CN_RESPONSIVE_DROP;
    274                     break;
    275                 case 1:
    276                     fld_val = _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP;
    277                     break;
    278                 case 2:
    279                     fld_val = _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN;
    280                     break;
    281                 case 3:
    282                     fld_val = _BCM_ECN_INT_CN_CONGESTION_MARK_ECN;
    283                     break;
    284                     /*
    285                      * COVERITY
    286                      *
    287                      *This default is unreachable. It is kept intentionally
    288                      *as a defensive default for future development.
    289                      */
    290                     /* coverity[dead_error_begin] */
    291                 default:
    292                     fld_val = _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN;
    293                     break;
    294             }
    295             soc_mem_field32_set(unit, EGR_TUNNEL_ECN_ENCAPm,
    296                 &egr_tunnel_ecn_encap, OUTER_ECNf, fld_val);
    297             SOC_IF_ERROR_RETURN
    298                 (soc_mem_write(unit, EGR_TUNNEL_ECN_ENCAPm, MEM_BLOCK_ALL,
    299                                i, (void *)&egr_tunnel_ecn_encap));
    300         }
    301     }
    302     return BCM_E_NONE;
    303 }
    304 /*
    305  * Given a slope (angle in degrees) from 0 to 90, return the number of cells
    306  * in the range from 0% drop probability to 100% drop probability.
    307  * Same as TD2.
    308  */
    309 STATIC int
    310 _bcm_hx5_angle_to_cells(int angle)
    311 {
    312     return (_bcm_hx5_cotangent_lookup_table[angle]);
    313 }
    314 
    315 /*
    316  * Given a number of packets in the range from 0% drop probability
    317  * to 100% drop probability, return the slope (angle in degrees).
    318  * Same as TD2.
    319  */
    320 STATIC int
    321 _bcm_hx5_cells_to_angle(int packets)
    322 {
    323     int angle;
    324 
    325     for (angle = 90; angle >= 0 ; angle--) {
    326         if (packets <= _bcm_hx5_cotangent_lookup_table[angle]) {
    327             break;
    328         }
    329     }
    330     return angle;
    331 }
    332 
    333 
    334 /*
    335  *  Convert HW drop probability to percent value
    336  *  Same as TD2.
    337  */
    338 STATIC int
    339 _bcm_hx5_hw_drop_prob_to_percent[] = {
    340     0,     /* 0  */
    341     1,     /* 1  */
    342     2,     /* 2  */
    343     3,     /* 3  */
    344     4,     /* 4  */
    345     5,     /* 5  */
    346     6,     /* 6  */
    347     7,     /* 7  */
    348     8,     /* 8  */
    349     9,     /* 9  */
    350     10,    /* 10 */
    351     25,    /* 11 */
    352     50,    /* 12 */
    353     75,    /* 13 */
    354     100,   /* 14 */
    355     -1     /* 15 */
    356 };
    357 
    358 STATIC int
    359 _bcm_hx5_percent_to_drop_prob(int percent)
    360 {
    361    int i;
    362 
    363    for (i = 14; i > 0 ; i--) {
    364       if (percent >= _bcm_hx5_hw_drop_prob_to_percent[i]) {
    365           break;
    366       }
    367    }
    368    return i;
    369 }
    370 
    371 STATIC int
    372 _bcm_hx5_drop_prob_to_percent(int drop_prob) {
    373    return (_bcm_hx5_hw_drop_prob_to_percent[drop_prob]);
    374 }
    375 
    376 
    377 STATIC int
    378 _bcm_hx5_cosq_bucket_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
    379                          uint32 min_quantum, uint32 max_quantum,
    380                          uint32 kbits_burst_min, uint32 kbits_burst_max,
    381                          uint32 flags);
    382 STATIC int
    383 _bcm_hx5_cosq_bucket_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
    384                         uint32 *min_quantum, uint32 *max_quantum,
    385                         uint32 *kbits_burst_min, uint32 *kbits_burst_max,
    386                         uint32 *flags);
    387 
    388 
    389 /*
    390  * Function:
    391  *     _bcm_hx5_cosq_node_get
    392  * Purpose:
    393  *     Get internal information of queue group or scheduler type GPORT
    394  * Parameters:
    395  *     unit       - (IN) unit number
    396  *     gport      - (IN) queue group/scheduler GPORT identifier
    397  *     modid      - (OUT) module identifier
    398  *     port       - (OUT) port number
    399  *     id         - (OUT) queue group or scheduler identifier
    400  *     node       - (OUT) node structure for the specified GPORT
    401  * Returns:
    402  *     BCM_E_XXX
    403  */
    404 int
    405 _bcm_hx5_cosq_node_get(int unit, bcm_gport_t gport, bcm_module_t *modid,
    406                        bcm_port_t *port, int *id, _bcm_hx5_cosq_node_t **node)
    407 {
    408     _bcm_hx5_cosq_port_info_t *port_info = NULL;
    409     _bcm_hx5_cosq_st_port_info_t *stport_info = NULL;
    410     _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
    411     _bcm_hx5_cosq_node_t *node_base = NULL;
    412     bcm_module_t modid_out;
    413     bcm_port_t port_out;
    414     int index, port_index;
    415     int num_sched_port = 0;
    416     int phy_port, mmu_port;
    417     soc_info_t *si = &SOC_INFO(unit);
    418 
    419     if (_bcm_hx5_cosq_port_info[unit] == NULL) {
    420         return BCM_E_INIT;
    421     }
    422 
    423     if (_bcm_hx5_cosq_st_port_info[unit] == NULL) {
    424         return BCM_E_INIT;
    425     }
    426 
    427     if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) {
    428         return BCM_E_INIT;
    429     }
    430 
    431     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    432     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    433         port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
    434     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    435         port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
    436     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
    437         port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff;
    438     } else {
    439         return BCM_E_PORT;
    440     }
    441 
    442     if (!SOC_PORT_VALID(unit, port_out) || IS_LB_PORT(unit, port_out) ) {
    443         return BCM_E_PORT;
    444     }
    445 
    446     phy_port = si->port_l2p_mapping[port_out];
    447     mmu_port = si->port_p2m_mapping[phy_port];
    448     _HX5_PORT_INDEX_GET(unit, mmu_port, port_index);
    449 
    450     if (IS_CPU_PORT(unit, port_out)) {
    451         cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit];
    452         num_sched_port = SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT;
    453     } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
    454         stport_info = &_bcm_hx5_cosq_st_port_info[unit][port_index];
    455         num_sched_port = SOC_HX5_NUM_SCHEDULER_PER_ST_PORT;
    456     } else {
    457         port_info = &_bcm_hx5_cosq_port_info[unit][port_index];
    458         num_sched_port = SOC_HX5_NUM_SCHEDULER_PER_PORT;
    459     }
    460 
    461     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    462         index = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
    463         node_base = (_HX5_IS_ST_PORT(unit, mmu_port)) ? stport_info->ucast : port_info->ucast;
    464     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    465         index = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport);
    466         if (IS_CPU_PORT(unit, port_out)) {
    467             node_base = cpu_port_info->mcast;
    468         } else {
    469             node_base = (_HX5_IS_ST_PORT(unit, mmu_port)) ? stport_info->mcast : port_info->mcast;
    470         }
    471     } else {
    472         index = (BCM_GPORT_SCHEDULER_GET(gport) >> 16) & 0x3ff;
    473         if (index >= num_sched_port) {
    474             return BCM_E_PORT;
    475         }
    476         if (IS_CPU_PORT(unit, port_out)) {
    477             node_base = cpu_port_info->sched;
    478         } else {
    479             node_base = (_HX5_IS_ST_PORT(unit, mmu_port)) ? stport_info->sched : port_info->sched;
    480         }
    481     }
    482 
    483     if ((node_base == NULL) ||
    484         (node_base[index].numq == 0) ||
    485         (node_base[index].in_use == 0)) {
    486         return BCM_E_NOT_FOUND;
    487     }
    488 
    489     if (modid != NULL) {
    490         *modid = modid_out;
    491     }
    492     if (port != NULL) {
    493         *port = port_out;
    494     }
    495     if (id != NULL) {
    496         *id = index;
    497     }
    498     if (node != NULL) {
    499         *node = &node_base[index];
    500     }
    501 
    502     return BCM_E_NONE;
    503 
    504 }
    505 
    506 
    507 /*
    508  * Function:
    509  *     _bcm_hx5_cosq_port_resolve
    510  * Purpose:
    511  *     Resolve following COS queue related GPORT
    512  *         BCM_GPORT_TYPE_UCAST_QUEUE_GROUP
    513  *         BCM_GPORT_TYPE_MCAST_QUEUE_GROUP
    514  *         BCM_GPORT_TYPE SCHEDULER
    515  * Parameters:
    516  *     unit       - (IN) unit number
    517  *     gport      - (IN) GPORT identifier
    518  *     modid      - (OUT) module identifier
    519  *     port       - (OUT) port number
    520  *     trunk_id   - (OUT) trunk identifier
    521  *     id         - (OUT) queue group or scheduler identifier
    522  *     qnum       - (OUT) hw_index for given queue gport
    523  * Returns:
    524  *     BCM_E_XXX
    525  */
    526 int
    527 _bcm_hx5_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid,
    528                            bcm_port_t *port, bcm_trunk_t *trunk_id, int *id,
    529                            int *qnum)
    530 {
    531     _bcm_hx5_cosq_node_t *node;
    532 
    533     BCM_IF_ERROR_RETURN
    534         (_bcm_hx5_cosq_node_get(unit, gport, modid, port, id, &node));
    535     *trunk_id = -1;
    536 
    537     if (qnum) {
    538         if (node->hw_index == -1) {
    539             return BCM_E_PARAM;
    540         }
    541         *qnum = node->hw_index;
    542     }
    543 
    544     return BCM_E_NONE;
    545 }
    546 
    547 /*
    548  * Function:
    549  *     _bcm_hx5_cosq_localport_resolve
    550  * Purpose:
    551  *     Resolve GPORT if it is a local port
    552  * Parameters:
    553  *     unit       - (IN) unit number
    554  *     gport      - (IN) GPORT identifier
    555  *     local_port - (OUT) local port number
    556  * Returns:
    557  *     BCM_E_XXX
    558  */
    559 STATIC int
    560 _bcm_hx5_cosq_localport_resolve(int unit, bcm_gport_t gport,
    561                                 bcm_port_t *local_port)
    562 {
    563     bcm_module_t module;
    564     bcm_port_t port;
    565     bcm_trunk_t trunk;
    566     int id, result, rv;
    567 
    568     if (!BCM_GPORT_IS_SET(gport)) {
    569         if (!SOC_PORT_VALID(unit, gport)) {
    570             return BCM_E_PORT;
    571         }
    572         *local_port = gport;
    573         return BCM_E_NONE;
    574     }
    575 
    576     rv = _bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id);
    577     if (rv == BCM_E_PORT) {
    578         /* returning E_PARAM when invalid gport is given as param */
    579         return BCM_E_PARAM;
    580     } else if (BCM_FAILURE(rv)) {
    581         return rv;
    582     }
    583 
    584     BCM_IF_ERROR_RETURN
    585         (_bcm_esw_modid_is_local(unit, module, &result));
    586     if (result == FALSE) {
    587         return BCM_E_PARAM;
    588     }
    589 
    590     *local_port = port;
    591 
    592     return BCM_E_NONE;
    593 }
    594 
    595 
    596 /*
    597  * Function:
    598  *     _bcm_hx5_cosq_cleanup
    599  * Purpose:
    600  *     Clean resource in case of error during Cosq Init
    601  * Parameters:
    602  *     unit - (IN) unit number
    603  * Returns:
    604  *     No return value
    605  */
    606 STATIC void
    607 _bcm_hx5_cosq_cleanup(int unit)
    608 {
    609     if (_bcm_hx5_cosq_port_info[unit] != NULL) {
    610         sal_free(_bcm_hx5_cosq_port_info[unit]);
    611         _bcm_hx5_cosq_port_info[unit] = NULL;
    612     }
    613 
    614     if (_bcm_hx5_cosq_st_port_info[unit] != NULL) {
    615         sal_free(_bcm_hx5_cosq_st_port_info[unit]);
    616         _bcm_hx5_cosq_st_port_info[unit] = NULL;
    617     }
    618 
    619     if (_bcm_hx5_cosq_cpu_port_info[unit] != NULL) {
    620         sal_free(_bcm_hx5_cosq_cpu_port_info[unit]);
    621         _bcm_hx5_cosq_cpu_port_info[unit] = NULL;
    622     }
    623 
    624     if (_bcm_hx5_mmu_info[unit] != NULL) {
    625         sal_free(_bcm_hx5_mmu_info[unit]);
    626         _bcm_hx5_mmu_info[unit] = NULL;
    627     }
    628 
    629     if (_bcm_hx5_wred_profile[unit] != NULL) {
    630         (void)soc_profile_mem_destroy(unit, _bcm_hx5_wred_profile[unit]);
    631         sal_free(_bcm_hx5_wred_profile[unit]);
    632         _bcm_hx5_wred_profile[unit] = NULL;
    633     }
    634 
    635     /* Cleanup profile for PRIO2COS_PROFILE register */
    636     if (_bcm_hx5_prio2cos_profile[unit] != NULL) {
    637         (void)soc_profile_reg_destroy(unit, _bcm_hx5_prio2cos_profile[unit]);
    638         sal_free(_bcm_hx5_prio2cos_profile[unit]);
    639         _bcm_hx5_prio2cos_profile[unit] = NULL;
    640     }
    641 
    642     if (_bcm_hx5_ifp_cos_map_profile[unit] != NULL) {
    643         (void)soc_profile_mem_destroy(unit, _bcm_hx5_ifp_cos_map_profile[unit]);
    644         sal_free(_bcm_hx5_ifp_cos_map_profile[unit]);
    645         _bcm_hx5_ifp_cos_map_profile[unit] = NULL;
    646     }
    647 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT)
    648     if (soc_feature(unit, soc_feature_tcb)) {
    649         _bcm_hx5_cosq_tcb_deinit(unit);
    650     }
    651 #endif /* INCLUDE_TCB && BCM_TCB_SUPPORT */
    652 }
    653 
    654 /*
    655  * Function:
    656  *     _bcm_hx5_cosq_node_hw_index_get
    657  * Purpose:
    658  *     Get cosq node hardware index
    659  * Parameters:
    660  *     unit        - (IN) unit number
    661  *     gport       - (IN) GPORT identifier
    662  *     cosq        - (OUT) COS queue number
    663  * Returns:
    664  *     BCM_E_XXX
    665  */
    666 STATIC int
    667 _bcm_hx5_cosq_node_hw_index_get(int unit, bcm_gport_t gport,
    668         bcm_cos_queue_t *cosq)
    669 {
    670     _bcm_hx5_cosq_node_t *node = NULL;
    671     int local_port = -1;
    672     int phy_port, mmu_port;
    673     int num_uc, num_mc;
    674 
    675     soc_info_t *si = &SOC_INFO(unit);
    676 
    677     BCM_IF_ERROR_RETURN
    678         (_bcm_hx5_cosq_node_get(unit, gport, NULL, &local_port, NULL,
    679                                 &node));
    680 
    681     phy_port = si->port_l2p_mapping[local_port];
    682     mmu_port = si->port_p2m_mapping[phy_port];
    683 
    684     if(IS_CPU_PORT(unit, local_port)){
    685         num_uc = 0;
    686         num_mc = SOC_HX5_NUM_CPU_QUEUES;
    687     }else {
    688         if(_HX5_IS_ST_PORT(unit, mmu_port)) {
    689             num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT;
    690             num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT;
    691         }else {
    692             num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT;
    693             num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_PORT;
    694         }
    695     }
    696 
    697     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    698         if(_HX5_IS_ST_PORT(unit, mmu_port)){
    699             *cosq = node->hw_index - (mmu_port * num_uc);
    700         } else {
    701             *cosq = node->hw_index - (_HX5_BASE_L3QUEUE +
    702                     ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * num_uc));
    703         }
    704     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    705         if(IS_CPU_PORT(unit, local_port)){
    706             *cosq = node->hw_index - _HX5_CPU_L2_NODE_BASE;
    707         } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
    708             *cosq = node->hw_index - (mmu_port * num_mc);
    709         } else {
    710             *cosq = node->hw_index - (_HX5_BASE_L3QUEUE +
    711                     ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * num_mc));
    712         }
    713     } else {
    714          switch(node->level) {
    715              case SOC_HX5_NODE_LVL_L0:
    716                  if(IS_CPU_PORT(unit, local_port)){
    717                      *cosq = node->hw_index - _HX5_CPU_LO_NODE_BASE;
    718                  } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
    719                      *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML0_NODES);
    720                  } else {
    721                      *cosq = node->hw_index - (_HX5_BASE_L0QUEUE +
    722                              ((mmu_port  - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML0_NODES));
    723                  }
    724                  break;
    725              case SOC_HX5_NODE_LVL_L1:
    726                  if(IS_CPU_PORT(unit, local_port)){
    727                      *cosq = node->hw_index - _HX5_CPU_L1_NODE_BASE;
    728                  } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
    729                      *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML1_NODES);
    730                  } else {
    731                      *cosq = node->hw_index - (_HX5_BASE_L1QUEUE +
    732                              ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML1_NODES));
    733                  }
    734                  break;
    735              case SOC_HX5_NODE_LVL_L2:
    736                  if(IS_CPU_PORT(unit, local_port)){
    737                      *cosq = node->hw_index - _HX5_CPU_L2_NODE_BASE;
    738                  } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
    739                      *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML2_NODES);
    740                  } else {
    741                      *cosq = node->hw_index - (_HX5_BASE_L2QUEUE +
    742                              ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML2_NODES));
    743                  }
    744                  break;
    745              default:
    746                  return BCM_E_PARAM;
    747          }
    748 
    749     }
    750 
    751     return BCM_E_NONE;
    752 }
    753 
    754 
    755 /*
    756  * Function:
    757  *     bcm_hx5_cosq_gport_get
    758  * Purpose:
    759  *     Get a cosq gport structure
    760  * Parameters:
    761  *     unit       - (IN) unit number
    762  *     gport      - (IN) GPORT identifier
    763  *     port       - (OUT) port number
    764  *     numq       - (OUT) number of COS queues
    765  *     flags      - (OUT) flags (BCM_COSQ_GPORT_XXX)
    766  * Returns:
    767  *     BCM_E_XXX
    768  */
    769 int
    770 bcm_hx5_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port,
    771                        int *numq, uint32 *flags)
    772 {
    773     _bcm_hx5_cosq_node_t *node;
    774     bcm_port_t local_port;
    775     bcm_module_t modid;
    776     _bcm_gport_dest_t dest;
    777     int phy_port, mmu_port;
    778     soc_info_t *si = &SOC_INFO(unit);
    779 
    780     if (port == NULL || numq == NULL || flags == NULL) {
    781         return BCM_E_PARAM;
    782     }
    783 
    784     LOG_INFO(BSL_LS_BCM_COSQ,
    785              (BSL_META_U(unit,
    786               "bcm_hx5_cosq_gport_get: unit=%d gport=0x%x\n"),
    787               unit, gport));
    788 
    789     if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
    790         BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
    791         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
    792         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
    793         BCM_IF_ERROR_RETURN
    794             (_bcm_hx5_cosq_node_get(unit, gport, NULL, &local_port, NULL,
    795                                     &node));
    796 
    797         *numq = node->numq;
    798 
    799         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    800             *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
    801         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    802             *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP;
    803         } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
    804             *flags = BCM_COSQ_GPORT_SCHEDULER;
    805         } else {
    806             *flags = 0;
    807         }
    808     } else {
    809         BCM_IF_ERROR_RETURN
    810             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
    811         *flags = 0;
    812         phy_port = si->port_l2p_mapping[local_port];
    813         mmu_port = si->port_p2m_mapping[phy_port];
    814         *numq = (_HX5_IS_ST_PORT(unit, mmu_port)) ? SOC_HX5_NUM_SCHEDULER_PER_ST_PORT :
    815                                                    SOC_HX5_NUM_SCHEDULER_PER_PORT;
    816     }
    817 
    818     if (SOC_USE_GPORT(unit)) {
    819         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
    820         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
    821         dest.modid = modid;
    822         dest.port = local_port;
    823         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port));
    824     } else {
    825         *port = local_port;
    826     }
    827 
    828     LOG_INFO(BSL_LS_BCM_COSQ,
    829              (BSL_META_U(unit,
    830               "                       port=0x%x numq=%d flags=0x%x\n"),
    831               *port, *numq, *flags));
    832 
    833     return BCM_E_NONE;
    834 }
    835 
    836 /*
    837  * Function:
    838  *     _bcm_hx5_cosq_gport_add
    839  * Purpose:
    840  *     Create a cosq gport structure
    841  * Parameters:
    842  *     unit  - (IN) unit number
    843  *     port  - (IN) port number
    844  *     numq  - (IN) number of COS queues
    845  *     flags - (IN) flags (BCM_COSQ_GPORT_XXX)
    846  *     gport - (OUT) GPORT identifier
    847  * Returns:
    848  *     BCM_E_XXX
    849  */
    850 STATIC int
    851 _bcm_hx5_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags,
    852                        bcm_gport_t *gport)
    853 {
    854     _bcm_hx5_cosq_port_info_t *port_info = NULL;
    855     _bcm_hx5_cosq_st_port_info_t *stport_info = NULL;
    856     _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
    857     _bcm_hx5_cosq_node_t *node = NULL;
    858     int phy_port, mmu_port;
    859     bcm_port_t local_port;
    860     uint32 sched_encap;
    861     int id;
    862     int num_uc, num_mc, num_sc, index;
    863 
    864     soc_info_t *si = &SOC_INFO(unit);
    865 
    866     LOG_INFO(BSL_LS_BCM_COSQ,
    867         (BSL_META_U(unit,
    868                     "_bcm_hx5_cosq_gport_add: unit=%d port=0x%x "
    869                     "numq=%d flags=0x%x\n"), unit, port, numq, flags));
    870 
    871     if (gport == NULL) {
    872         return BCM_E_PARAM;
    873     }
    874 
    875     if (_bcm_hx5_cosq_port_info[unit] == NULL) {
    876         return BCM_E_INIT;
    877     }
    878 
    879     if (_bcm_hx5_cosq_st_port_info[unit] == NULL) {
    880         return BCM_E_INIT;
    881     }
    882 
    883     if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) {
    884         return BCM_E_INIT;
    885     }
    886 
    887     BCM_IF_ERROR_RETURN
    888         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
    889 
    890     if (local_port < 0 || IS_LB_PORT(unit, local_port)) {
    891         return BCM_E_PORT;
    892     }
    893 
    894     phy_port = si->port_l2p_mapping[local_port];
    895     mmu_port = si->port_p2m_mapping[phy_port];
    896     _HX5_PORT_INDEX_GET(unit, mmu_port, index);
    897     if (IS_CPU_PORT(unit, local_port)) {
    898         cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit];
    899         num_uc = 0;
    900         num_mc = SOC_HX5_NUM_CPU_QUEUES;
    901         num_sc = SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT;
    902     } else if(_HX5_IS_ST_PORT(unit, mmu_port)) {
    903         stport_info = &_bcm_hx5_cosq_st_port_info[unit][index];
    904         num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT;
    905         num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT;
    906         num_sc = SOC_HX5_NUM_SCHEDULER_PER_ST_PORT;
    907     } else {
    908         port_info = &_bcm_hx5_cosq_port_info[unit][index];
    909         num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT;
    910         num_mc = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT;
    911         num_sc = SOC_HX5_NUM_SCHEDULER_PER_PORT;
    912     }
    913 
    914     switch (flags) {
    915         case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
    916             if (IS_CPU_PORT(unit, local_port)) {
    917                 return BCM_E_PARAM;
    918             }
    919             if (numq != 1) {
    920                 return BCM_E_PARAM;
    921             }
    922             for (id = 0; id < num_uc; id++) {
    923                 if(_HX5_IS_ST_PORT(unit, mmu_port)) {
    924                     if ((stport_info->ucast[id].numq == 0) ||
    925                         (stport_info->ucast[id].in_use == 0)) {
    926                          break;
    927                     }
    928                 } else {
    929                     if ((port_info->ucast[id].numq == 0) ||
    930                         (port_info->ucast[id].in_use == 0)) {
    931                          break;
    932                     }
    933                 }
    934             }
    935             if (id == num_uc) {
    936                 return BCM_E_RESOURCE;
    937             }
    938             BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
    939             if (_HX5_IS_ST_PORT(unit, mmu_port)){
    940                node = &stport_info->ucast[id];
    941             } else {
    942                node = &port_info->ucast[id];
    943             }
    944             node->level = SOC_HX5_NODE_LVL_L3;
    945             break;
    946         case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
    947             if (numq != 1) {
    948                 return BCM_E_PARAM;
    949             }
    950             if (IS_CPU_PORT(unit, local_port)) {
    951                 for (id = 0; id < SOC_HX5_NUM_CPU_QUEUES; id++) {
    952                     if ((cpu_port_info->mcast[id].numq == 0) ||
    953                         (cpu_port_info->mcast[id].in_use == 0)) {
    954                         break;
    955                     }
    956                 }
    957                 if (id == SOC_HX5_NUM_CPU_QUEUES) {
    958                     return BCM_E_RESOURCE;
    959                 }
    960             } else {
    961                 for (id = 0; id < num_mc; id++) {
    962                     if(_HX5_IS_ST_PORT(unit, mmu_port)) {
    963                         if ((stport_info->mcast[id].numq == 0) ||
    964                             (stport_info->mcast[id].in_use == 0)) {
    965                              break;
    966                         }
    967                      } else {
    968                         if ((port_info->mcast[id].numq == 0) ||
    969                             (port_info->mcast[id].in_use == 0)) {
    970                             break;
    971                         }
    972                     }
    973                 }
    974                 if (id == num_mc) {
    975                     return BCM_E_RESOURCE;
    976                 }
    977             }
    978             BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
    979             if (IS_CPU_PORT(unit, local_port)) {
    980                 node = &cpu_port_info->mcast[id];
    981             } else if ( _HX5_IS_ST_PORT(unit, mmu_port)){
    982                 node = &stport_info->mcast[id];
    983             } else {
    984                 node = &port_info->mcast[id];
    985             }
    986             node->level = SOC_HX5_NODE_LVL_L3;
    987             break;
    988         case BCM_COSQ_GPORT_SCHEDULER:
    989         case 0:
    990             if (numq <= 0) {
    991                 return BCM_E_PARAM;
    992             }
    993             if (IS_CPU_PORT(unit, local_port)) {
    994                 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; id++) {
    995                     if (cpu_port_info->sched[id].numq == 0) {
    996                         break;
    997                     }
    998                     if (id == num_sc) {
    999                         return BCM_E_RESOURCE;
   1000                     }
   1001                 }
   1002                 if (id == SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT) {
   1003                     return BCM_E_RESOURCE;
   1004                 }
   1005 
   1006                 sched_encap = (id << 16) | local_port;
   1007                 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   1008                 node = &cpu_port_info->sched[id];
   1009                 node->level = SOC_HX5_NODE_LVL_L0;
   1010             }
   1011 
   1012             if (_HX5_IS_ST_PORT(unit, mmu_port) && !IS_CPU_PORT(unit, local_port)){
   1013                 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; id++) {
   1014                     if (stport_info->sched[id].numq == 0) {
   1015                         break;
   1016                     }
   1017                 }
   1018                 if (id == SOC_HX5_NUM_SCHEDULER_PER_ST_PORT) {
   1019                     return BCM_E_RESOURCE;
   1020                 }
   1021                 sched_encap = (id << 16) | local_port;
   1022                 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   1023                 node = &stport_info->sched[id];
   1024                 node->level = SOC_HX5_NODE_LVL_L0;
   1025             } 
   1026 
   1027             if (!_HX5_IS_ST_PORT(unit, mmu_port) && !IS_CPU_PORT(unit, local_port)){
   1028                 for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_PORT; id++) {
   1029                     if (port_info->sched[id].numq == 0) {
   1030                         break;
   1031                     }
   1032                 }
   1033                 if (id == SOC_HX5_NUM_SCHEDULER_PER_PORT) {
   1034                     return BCM_E_RESOURCE;
   1035                }
   1036                 sched_encap = (id << 16) | local_port;
   1037                 BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   1038                 node = &port_info->sched[id];
   1039                 node->level = SOC_HX5_NODE_LVL_L0;
   1040              }
   1041             break;
   1042         default:
   1043             return BCM_E_PARAM;
   1044     }
   1045 
   1046     node->gport = *gport;
   1047     node->numq = numq;
   1048     node->in_use = 1;
   1049 
   1050     LOG_INFO(BSL_LS_BCM_COSQ,
   1051             (BSL_META_U(unit,"gport=0x%x\n"), *gport));
   1052 
   1053     return BCM_E_NONE;
   1054 }
   1055 
   1056 /*
   1057  * This function does two things:
   1058  * 1. Tests whether the corresponding COS_BMP bit is set or not.
   1059  * 2. Tests whether the queue corresponding to given cos is
   1060  *     mapped to correct L2 or not.
   1061  *
   1062  * L2.0 is associated with CMC0 CH1(Rx) (pci)
   1063  * L2.1 is associated with CMC0 CH2(Rx) (pci)
   1064  * L2.2 is associated with CMC0 CH3(Rx) (pci)
   1065  * L2.3 is associated with CMC0 CH4(Rx) (pci)
   1066  * L2.4 is associated with CMC0 CH5(Rx) (pci)
   1067  * L2.5 is associated with CMC0 CH6(Rx) (pci)
   1068  * L2.6 is associated with CMC0 CH7(Rx) (pci)
   1069  * L2.7 is associated with CMC1 CHx(Rx) (uc0)
   1070  * L2.8 is associated with CMC1 CHx(Rx) (uC1)
   1071  * L2.9 is reserved
   1072  */
   1073 int
   1074 bcm_hx5_rx_queue_channel_set_test(int unit, bcm_cos_queue_t queue_id,
   1075                                           bcm_rx_chan_t chan_id)
   1076 {
   1077 #if defined(BCM_CMICX_SUPPORT)
   1078     if (soc_feature(unit, soc_feature_cmicx)) {
   1079         int pci_cmc = SOC_PCI_CMC(unit);
   1080         uint32 reg_val;
   1081         uint32 bit;
   1082         uint32 max_rx_channels = 0;
   1083         int index;
   1084         _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
   1085         bcm_gport_t cpu_l2_gport = -1;
   1086         bcm_gport_t parent_gport = -1;
   1087 
   1088         soc_dma_max_rx_channels_get(unit, &max_rx_channels);
   1089 
   1090         if ((chan_id <= 0) || (chan_id >= max_rx_channels)) {
   1091             return BCM_E_PARAM;
   1092         }
   1093 
   1094         if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) {
   1095             return BCM_E_INIT;
   1096         }
   1097 
   1098         cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit];
   1099 
   1100         if ((chan_id > 0) && (chan_id < 8 ))  {
   1101             index = chan_id + 2;
   1102             cpu_l2_gport = cpu_port_info->sched[index - 1].gport;
   1103         }
   1104 
   1105         if (queue_id < 0) { /* All COS Queues */
   1106             for (queue_id = 0; queue_id < NUM_CPU_COSQ(unit); queue_id++) {
   1107                 soc_dma_cos_ctrl_queue_get(unit, pci_cmc, chan_id, queue_id,
   1108                         &reg_val);
   1109 
   1110                 bit = 1 << (queue_id % 32);
   1111                 if (reg_val & bit) {
   1112                     /* find the parent gport of this queue if parent gport is
   1113                      * not equal to l0 gport for this channel return error */
   1114                     parent_gport = cpu_port_info->mcast[queue_id].parent_gport;
   1115                     if (parent_gport != cpu_l2_gport) {
   1116                         return BCM_E_PARAM;
   1117                     }
   1118                 }
   1119             }
   1120         } else {
   1121             soc_dma_cos_ctrl_queue_get(unit, pci_cmc, chan_id, queue_id,
   1122                     &reg_val);
   1123             bit = 1 << (queue_id % 32);
   1124             if (reg_val & bit) {
   1125                 /* find the parent gport of this queue if parent gport is not
   1126                  * equal to l0 gport for this channel return error */
   1127                 parent_gport = cpu_port_info->mcast[queue_id].parent_gport;
   1128                 if (parent_gport != cpu_l2_gport) {
   1129                     return BCM_E_PARAM;
   1130                 }
   1131             } else {
   1132                 return BCM_E_PARAM;
   1133             }
   1134         }
   1135     }
   1136 #endif /* BCM_CMICX_SUPPORT */
   1137 
   1138     return BCM_E_NONE;
   1139 }
   1140 
   1141 /*
   1142  * Function:
   1143  *      _bcm_hx5_cpu_cosq_mapping_default_set
   1144  * Purpose:
   1145  *      Map 16 internal priorities to CPU COS queues using CPU_COS_MAPm
   1146  *      Default cpu_cos_maps should have lower priorities than user created
   1147  *      maps
   1148  * Parameters:
   1149  *      unit - (IN) Unit number.
   1150  *      numq - (IN) number of COS queues (0-7).
   1151  * Returns:
   1152  *      BCM_E_XXX
   1153  */
   1154 STATIC int
   1155 _bcm_hx5_cpu_cosq_mapping_default_set(int unit, int numq)
   1156 {
   1157     int cos = 0, prio = 0, index = 0, i = 0;
   1158     cpu_cos_map_entry_t cpu_cos_map_entry;
   1159 
   1160     /* Nothing to do on devices with no CPU_COS_MAP memory */
   1161     if (!SOC_MEM_IS_VALID(unit, CPU_COS_MAPm)) {
   1162         return BCM_E_NONE;
   1163     }
   1164 
   1165     /* Map internal priorities 0 ~ 7 to appropriate CPU CoS queue */
   1166     sal_memset(&cpu_cos_map_entry, 0, sizeof(cpu_cos_map_entry_t));
   1167     soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry, VALIDf, 3);
   1168     soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry,
   1169                         INT_PRI_MASKf, _BCM_HX5_INT_PRI_0_7_MASK);
   1170 
   1171    index = (soc_mem_index_count(unit, CPU_COS_MAPm) - _BCM_HX5_CPU_COS_MAPS_RSVD);
   1172     for (cos = 0; cos < numq; cos++) {
   1173         for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) {
   1174             soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry,
   1175                                 INT_PRI_KEYf, prio);
   1176             soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry, COSf, cos);
   1177             SOC_IF_ERROR_RETURN(WRITE_CPU_COS_MAPm(unit, MEM_BLOCK_ALL, index,
   1178                                                    &cpu_cos_map_entry));
   1179             prio++;
   1180             index++;
   1181         }
   1182     }
   1183 
   1184     /* Map internal priorities 8 ~ 15 to (numq - 1) CPU CoS queue */
   1185     soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry,
   1186                         INT_PRI_KEYf, 0x8);
   1187     soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry,
   1188                         INT_PRI_MASKf, _BCM_HX5_INT_PRI_8_15_MASK);
   1189     soc_mem_field32_set(unit, CPU_COS_MAPm, &cpu_cos_map_entry, COSf, numq - 1);
   1190     SOC_IF_ERROR_RETURN(WRITE_CPU_COS_MAPm(unit, MEM_BLOCK_ALL, index,
   1191                                            &cpu_cos_map_entry));
   1192 
   1193     return BCM_E_NONE;
   1194 }
   1195 
   1196 /*
   1197  * Function:
   1198  *    bcm_hx5_wireless_cos_map_update
   1199  * Purpose:
   1200  *     Set the number of classes of service supported
   1201  * Parameters:
   1202  *     unit - (IN) unit number
   1203  *     index - (IN) index of newly added profile 
   1204  * Returns:
   1205  *     BCM_E_XXX
   1206  */
   1207 int bcm_hx5_wireless_cos_map_update(int unit, int numq) 
   1208 {
   1209     uint32 *cos_map_entries;
   1210     soc_mem_t mem;
   1211     int rv = SOC_E_NONE, cos, prio = 0, index = 0;
   1212     uint32 uc_cos = 0, mc_cos = 0, hg_cos = 0;
   1213 
   1214     mem = PORT_COS_MAPm;
   1215     cos_map_entries = soc_cm_salloc(unit, (sizeof(port_cos_map_entry_t) * 16),
   1216                                     "HX5 Cos map update");
   1217     for (index = 0; index < 4; index++) {
   1218         prio = 0;
   1219         sal_memset(cos_map_entries, 0, (sizeof(port_cos_map_entry_t) * 16));
   1220         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index * _HX5_NUM_COS_MAP_ENTRY,
   1221                 (index * _HX5_NUM_COS_MAP_ENTRY) + (_HX5_NUM_COS_MAP_ENTRY - 1),
   1222                 (void *)cos_map_entries);
   1223         if (BCM_FAILURE(rv)) {
   1224             soc_cm_sfree(unit, cos_map_entries);
   1225             return rv;
   1226         }
   1227         for (cos = 0; cos < numq; cos++) {
   1228             uc_cos = mc_cos = hg_cos = 0;
   1229             uc_cos = soc_mem_field32_get(unit, mem, &cos_map_entries[prio], UC_COS1f);
   1230             mc_cos = soc_mem_field32_get(unit, mem, &cos_map_entries[prio], MC_COS1f);
   1231             hg_cos = soc_mem_field32_get(unit, mem, &cos_map_entries[prio], HG_COSf);
   1232             soc_mem_field32_set(unit, mem, &cos_map_entries[prio],  UC_COS1f, uc_cos + _BCM_HX5_COS_DEFAULT);
   1233             soc_mem_field32_set(unit, mem, &cos_map_entries[prio],  MC_COS1f, mc_cos + _BCM_HX5_COS_DEFAULT);
   1234             if(!hg_cos || (hg_cos < _BCM_HX5_COS_DEFAULT)) {
   1235                soc_mem_field32_set(unit, mem, &cos_map_entries[prio], HG_COSf, hg_cos + _HX5_NUM_COS_MAP_ENTRY);
   1236             }
   1237             prio++;
   1238         }
   1239 
   1240         for (prio = 8; prio < 16; prio++) {
   1241             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f,
   1242                     uc_cos + _BCM_HX5_COS_DEFAULT); 
   1243             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f,
   1244                     mc_cos + _BCM_HX5_COS_DEFAULT); 
   1245             if(!hg_cos || (hg_cos < _BCM_HX5_COS_DEFAULT)) {
   1246                 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], HG_COSf,
   1247                         hg_cos + _HX5_NUM_COS_MAP_ENTRY); 
   1248             }
   1249         }
   1250 
   1251         rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ANY, (index * _HX5_NUM_COS_MAP_ENTRY) +
   1252                 _HX5_WIRELESS_COS_MAP_BASE, (index * _HX5_NUM_COS_MAP_ENTRY) +
   1253                 (_HX5_WIRELESS_COS_MAP_BASE + _HX5_NUM_COS_MAP_ENTRY - 1),
   1254                 (void *)cos_map_entries);
   1255 
   1256     }
   1257     soc_cm_sfree(unit, cos_map_entries);
   1258     return rv;
   1259 
   1260 }
   1261 
   1262 /*
   1263  * Function:
   1264  *     bcm_hx5_cosq_config_set
   1265  * Purpose:
   1266  *     Set the number of classes of service supported
   1267  * Parameters:
   1268  *     unit - (IN) unit number
   1269  *     numq - (IN) number of classes of service
   1270  * Returns:
   1271  *     BCM_E_XXX
   1272  */
   1273 int
   1274 bcm_hx5_cosq_config_set(int unit, int numq)
   1275 {
   1276     port_cos_map_entry_t cos_map_entries[16];
   1277     void *entries[1];
   1278     uint32 index;
   1279     int count = 0;
   1280     bcm_port_t port;
   1281     int cos, prio = 0, ref_count = -1;
   1282     uint32 i;
   1283     soc_mem_t mem = PORT_COS_MAPm;
   1284 
   1285     if (numq < 1 || numq > _BCM_HX5_COS_DEFAULT) {
   1286         return BCM_E_PARAM;
   1287     }
   1288 
   1289     index = 0;
   1290     while (index < (soc_mem_index_count(unit, mem) / 2)) {
   1291         BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit,
   1292                                       _bcm_hx5_cos_map_profile[unit],
   1293                                       index, &ref_count));
   1294         if (ref_count > 0) {
   1295             while (ref_count) {
   1296                 if (!soc_profile_mem_delete(unit,
   1297                             _bcm_hx5_cos_map_profile[unit], index)) {
   1298                     ref_count -= 1;
   1299                 }
   1300             }
   1301         }
   1302         index += 16;
   1303     }
   1304 
   1305     /*
   1306      * Distribute first 8 internal priority levels into the specified number
   1307      * of cosq, map remaining internal priority levels to highest priority
   1308      * cosq
   1309      */
   1310     sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
   1311     entries[0] = &cos_map_entries;
   1312 
   1313     for (cos = 0; cos < numq; cos++) {
   1314         for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) {
   1315             soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
   1316                                 UC_COS1f, cos);
   1317             soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
   1318                                 MC_COS1f, cos);
   1319             soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
   1320                                 HG_COSf, _HX5_NUM_COS_MAP_ENTRY + cos);
   1321             prio++;
   1322         }
   1323     }
   1324     for (prio = 8; prio < 16; prio++) {
   1325          soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f,
   1326                                 numq - 1);
   1327          soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f,
   1328                                 numq - 1);
   1329          soc_mem_field32_set(unit, mem, &cos_map_entries[prio], HG_COSf,
   1330                                 _HX5_NUM_COS_MAP_ENTRY + (numq - 1));
   1331     }
   1332 
   1333     /* Map internal priority levels to CPU CoS queues */
   1334     BCM_IF_ERROR_RETURN(_bcm_hx5_cpu_cosq_mapping_default_set(unit, numq));
   1335 
   1336     SOC_IF_ERROR_RETURN
   1337         (soc_profile_mem_add(unit, _bcm_hx5_cos_map_profile[unit], entries, 16,
   1338                              &index));
   1339     BCM_IF_ERROR_RETURN(bcm_hx5_wireless_cos_map_update(unit, numq));
   1340     PBMP_ALL_ITER(unit, port) {
   1341         SOC_IF_ERROR_RETURN
   1342             (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   1343                                     index / 16));
   1344         count++;
   1345     }
   1346     if (SOC_INFO(unit).cpu_hg_index != -1) {
   1347         SOC_IF_ERROR_RETURN
   1348             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   1349                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   1350                                     index / 16));
   1351         count++;
   1352     }
   1353     for (i = 1; i < count; i++) {
   1354         soc_profile_mem_reference(unit, _bcm_hx5_cos_map_profile[unit], index, 0);
   1355     }
   1356 
   1357     _BCM_HX5_NUM_COS(unit) = numq;
   1358 
   1359     return BCM_E_NONE;
   1360 }
   1361 
   1362 int bcm_hx5_hgcos_mode_get(int unit, bcm_port_t port, int *mode)
   1363 {
   1364     uint32 regval = 0;
   1365     SOC_IF_ERROR_RETURN(READ_UC_HG_QUEUE_MODEr(unit, port, &regval));
   1366     *mode = soc_reg_field_get(unit, UC_HG_QUEUE_MODEr, regval, QUEUE_MODEf);
   1367 
   1368    return BCM_E_NONE;
   1369 }
   1370 
   1371 
   1372 /*
   1373  * Function:
   1374  *     bcm_hx5_cosq_config_get
   1375  * Purpose:
   1376  *     Get the number of Classes of Service
   1377  * Parameters:
   1378  *     unit - (IN) unit number
   1379  *     numq - (OUT) Number of Classes of Service
   1380  * Returns:
   1381  *     BCM_E_XXX
   1382  */
   1383 int
   1384 bcm_hx5_cosq_config_get(int unit, int *numq)
   1385 {
   1386     if (numq != NULL) {
   1387         *numq = _BCM_HX5_NUM_COS(unit);
   1388     }
   1389 
   1390     return BCM_E_NONE;
   1391 
   1392 }
   1393 
   1394 
   1395 /*
   1396  * CMIC CMC Channel to Queue mapping.
   1397  */
   1398     STATIC int
   1399 _bcm_hx5_cosq_rx_queue_channel_set(int unit, bcm_cos_queue_t parent_cos,
   1400         bcm_cos_queue_t queue_id, int enable)
   1401 {
   1402 #if defined(BCM_CMICX_SUPPORT)
   1403     if soc_feature(unit, soc_feature_cmicx) {
   1404         int pci_cmc = SOC_PCI_CMC(unit);
   1405         int chan_id = -1;
   1406         int start_chan_id = 0;
   1407         uint32 chan_off;
   1408         uint32 reg_addr, reg_val;
   1409         uint32 ix;
   1410         uint32 max_rx_channels = 0;
   1411 
   1412         if ((parent_cos >= 0) && (parent_cos <= 6)) {
   1413             chan_id = parent_cos + 1;
   1414         } else {
   1415             return BCM_E_PARAM;
   1416         }
   1417 
   1418         if (!SHR_BITGET(CPU_ARM_QUEUE_BITMAP(unit, pci_cmc), queue_id)) {
   1419             return BCM_E_PARAM;
   1420         }
   1421 
   1422         soc_dma_max_rx_channels_get(unit, &max_rx_channels);
   1423 
   1424         for (ix = start_chan_id; ix < (start_chan_id + max_rx_channels); ix++) {
   1425             chan_off = ix % max_rx_channels;
   1426             soc_dma_cos_ctrl_reg_addr_get(unit, pci_cmc, chan_off, queue_id,
   1427                     &reg_addr);
   1428             reg_val = soc_pci_read(unit, reg_addr);
   1429 
   1430             if (enable == 1) {
   1431                 if (ix == (uint32)chan_id) {
   1432                     reg_val |= ((uint32)1 << (queue_id % 32));
   1433                 } else {
   1434                     /* Clear all other channels */
   1435                     reg_val &= ~((uint32)1 << (queue_id % 32));
   1436                 }
   1437             } else {
   1438                 if (ix == (uint32)chan_id) {
   1439                     reg_val &= ~((uint32)1 << (queue_id % 32));
   1440                 }
   1441             }
   1442             /* Incoporate the reserved queues (if any on this device)
   1443              * into the CMIC programming,  */
   1444             reg_val |=
   1445                 CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc)[queue_id / 32];
   1446             soc_pci_write(unit, reg_addr, reg_val);
   1447         }
   1448     }
   1449 #endif /* BCM_CMICX_SUPPORT */
   1450 
   1451     return BCM_E_NONE;
   1452 }
   1453 
   1454 
   1455 
   1456 
   1457 /*
   1458  * Function:
   1459  *     _bcm_hx5_cosq_cpu_parent_set
   1460  * Purpose:
   1461  *     Set Parent(L2) for a given L3 queue of the CPU port.
   1462  *     Only child @ L3 level is supported. Because only L3 level queues can be
   1463  *     attached to different parent (L2.0-L2.9) of the CPU port.
   1464  * Parameters:
   1465  *     unit         - (IN) unit number
   1466  *     child_index  - (IN) Child node index
   1467  *     child_level  - (IN) Child node level
   1468  *     parent_index - (IN) Parent node index
   1469  * Returns:
   1470  *     BCM_E_XXX
   1471  */
   1472     STATIC int
   1473 _bcm_hx5_cosq_cpu_parent_set(int unit, int child_index, int child_level,
   1474         int parent_index)
   1475 {
   1476     soc_reg_t reg =  Q_SCHED_CPU_L3_MC_QUEUE_L2_MAPPINGr;
   1477     uint32 rval = 0;
   1478 
   1479     if (child_level != SOC_HX5_NODE_LVL_L3) {
   1480         return BCM_E_PARAM;
   1481     }
   1482 
   1483     /* Set the L3 queue's parent to the given L2 node */
   1484     SOC_IF_ERROR_RETURN
   1485         (soc_reg32_get(unit, reg, 0, child_index, &rval));
   1486     soc_reg_field_set(unit, reg, &rval, SELECTf, parent_index);
   1487     SOC_IF_ERROR_RETURN
   1488         (soc_reg32_set(unit, reg, 0, child_index, rval));
   1489 
   1490     return BCM_E_NONE;
   1491 }
   1492 
   1493 
   1494 /*
   1495  * Function:
   1496  *     _bcm_hx5_cosq_cpu_parent_get
   1497  * Purpose:
   1498  *     Get Parent(L2) for a given L3 queue of the CPU port.
   1499  *     Only child @ L3 level is supported. Because only L3 level queues can be
   1500  *     attached to different parent (L2.0-L2.9) of the CPU port.
   1501  * Parameters:
   1502  *     unit         - (IN)  unit number
   1503  *     child_index  - (IN)  Child node index
   1504  *     child_level  - (IN)  Child node level
   1505  *     parent_index - (OUT) Parent node index
   1506  * Returns:
   1507  *     BCM_E_XXX
   1508  */
   1509     STATIC int
   1510 _bcm_hx5_cosq_cpu_parent_get(int unit, int child_index, int child_level,
   1511         int *parent_index)
   1512 {
   1513     soc_reg_t reg = Q_SCHED_CPU_L3_MC_QUEUE_L2_MAPPINGr;
   1514     uint32 rval = 0;
   1515 
   1516     if (child_level != SOC_HX5_NODE_LVL_L3) {
   1517         return BCM_E_PARAM;
   1518     }
   1519 
   1520     /* Set the L3 queue's parent to the given L2 node */
   1521     SOC_IF_ERROR_RETURN
   1522         (soc_reg32_get(unit, reg, 0, child_index, &rval));
   1523     *parent_index = soc_reg_field_get(unit, reg, rval, SELECTf);
   1524 
   1525     return BCM_E_NONE;
   1526 }
   1527 
   1528 
   1529 /*
   1530  * Function:
   1531  *     _bcm_hx5_cosq_cpu_gport_attach
   1532  * Purpose:
   1533  *     Attach any of the L3 MC Queue to one of the L2 nodes
   1534  * Parameters:
   1535  *     unit         - (IN) unit number
   1536  *     input_gport  - (IN) GPORT id, that will attach to parent gport
   1537  *     parent_gport - (IN) Parent Gport to which current gport will be attached
   1538  *     cosq         - (IN) COS queue to attach to (-1 for first available cosq)
   1539  * Returns:
   1540  *     BCM_E_XXX
   1541  */
   1542 STATIC int
   1543 _bcm_hx5_cosq_cpu_gport_attach(int unit, bcm_gport_t input_gport,
   1544         bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   1545 {
   1546 
   1547     _bcm_hx5_cosq_node_t *input_node = NULL;
   1548     _bcm_hx5_cosq_node_t *parent_node = NULL;
   1549     bcm_port_t input_port, parent_port;
   1550     int parent_cos = 0;
   1551 
   1552     LOG_INFO(BSL_LS_BCM_COSQ,
   1553             (BSL_META_U(unit,
   1554                         "bcm_hx5_cosq_gport_attach: unit=%d parent_gport=0x%x "
   1555                         "input_gport=0x%x cosq=%d\n"), unit, parent_gport,
   1556              input_gport, cosq));
   1557 
   1558     if (_BCM_HX5_MMU_INFO(unit)->gport_tree_created == FALSE) {
   1559         if (((BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) &&
   1560                     (!BCM_GPORT_IS_SCHEDULER(parent_gport))) ||
   1561                 (!(BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) &&
   1562                  (!BCM_GPORT_IS_SCHEDULER(input_gport)))) {
   1563             return BCM_E_PARAM;
   1564         }
   1565     } else if ((!BCM_GPORT_IS_SCHEDULER(parent_gport)) ||
   1566             (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   1567         return BCM_E_PARAM;
   1568     }
   1569 
   1570     BCM_IF_ERROR_RETURN
   1571         (_bcm_hx5_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   1572                                 &input_node));
   1573 
   1574     if (!input_node) {
   1575         return BCM_E_PARAM;
   1576     }
   1577     if (input_port < 0) {
   1578         return BCM_E_PORT;
   1579     }
   1580 
   1581     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   1582         BCM_IF_ERROR_RETURN
   1583             (_bcm_hx5_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL,
   1584                                     &parent_node));
   1585     } else {
   1586         BCM_IF_ERROR_RETURN
   1587             (_bcm_hx5_cosq_localport_resolve(unit, parent_gport, &parent_port));
   1588         parent_node = NULL;
   1589     }
   1590 
   1591     if (!IS_CPU_PORT(unit, parent_port)) {
   1592         return BCM_E_PARAM;
   1593     }
   1594 
   1595     /* Return BCM_E_EXISTS when queue to be attached is
   1596      * already attached to the given gport
   1597      */
   1598     if ((_BCM_HX5_MMU_INFO(unit)->gport_tree_created == TRUE) &&
   1599             (input_node->parent_gport == parent_gport)) {
   1600         return BCM_E_EXISTS;
   1601     }
   1602 
   1603 
   1604     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) {
   1605         input_node->hw_index = SOC_HX5_CPU_MCQ_BASE + cosq;
   1606     } else {
   1607         input_node->level = HX5_CPU_SCHED_LEVEL_GET(unit, cosq);
   1608         switch(input_node->level) {
   1609             case SOC_HX5_NODE_LVL_L0:
   1610                 input_node->hw_index = _HX5_CPU_LO_NODE_BASE;
   1611                 break;
   1612             case SOC_HX5_NODE_LVL_L1:
   1613                 input_node->hw_index = _HX5_CPU_L1_NODE_BASE;
   1614                 break;
   1615             case SOC_HX5_NODE_LVL_L2:
   1616                 input_node->hw_index = _HX5_CPU_L2_NODE_BASE + (cosq - (_HX5_CPU_NUML0_NODES + _HX5_CPU_NUML1_NODES));
   1617                 break;
   1618             default:
   1619                 return BCM_E_PARAM;
   1620         }
   1621     }
   1622 
   1623     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   1624         if(parent_node->level == SOC_HX5_NODE_LVL_L2) {
   1625             parent_cos = parent_node->hw_index - _HX5_CPU_L2_NODE_BASE;
   1626             BCM_IF_ERROR_RETURN
   1627                 (_bcm_hx5_cosq_cpu_parent_set(unit, cosq, SOC_HX5_NODE_LVL_L3,
   1628                                               parent_cos));
   1629             /*
   1630              * L2.0 is associated with CMC0 CH1(Rx)
   1631              * L2.1 is associated with CMC0 CH2(Rx)
   1632              * L2.2 is associated with CMC0 CH3(Rx)
   1633              * L2.3 is associated with CMC0 CH4(Rx)
   1634              * L2.4 is associated with CMC0 CH5(Rx)
   1635              * L2.5 is associated with CMC0 CH6(Rx)
   1636              * L2.6 is associated with CMC0 CH7(Rx)
   1637              */
   1638             if ((parent_cos >= 0) && (parent_cos < 7)) {
   1639                 BCM_IF_ERROR_RETURN
   1640                     (_bcm_hx5_cosq_rx_queue_channel_set(unit, parent_cos, cosq, 1));
   1641             }
   1642         }
   1643     }
   1644 
   1645     if (BCM_GPORT_IS_SCHEDULER(input_gport)) {
   1646         if(input_node->level == SOC_HX5_NODE_LVL_L0) {
   1647             BCM_IF_ERROR_RETURN
   1648                 (bcm_esw_port_gport_get(unit, input_port,
   1649                                         &(input_node->parent_gport)));
   1650         } else {
   1651             input_node->parent_gport = parent_gport;
   1652         }
   1653     }else if(BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)){
   1654         input_node->parent_gport = parent_gport;
   1655     }
   1656 
   1657 
   1658     return BCM_E_NONE;
   1659 }
   1660 
   1661 
   1662 
   1663 /*
   1664  * Function:
   1665  *     _bcm_hx5_cosq_port_cos_resolve
   1666  * Purpose:
   1667  *     Find UC/MC queue gport for a given logical port
   1668  *     and cos value.
   1669  * Parameters:
   1670  *     unit      - (IN) unit number
   1671  *     port      - (IN) logical port
   1672  *     cos       - (IN) cos value
   1673  *     style     - (IN) index style
   1674  *                 (_BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE or
   1675  *                  _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE)
   1676  *     gport     - (OUT) Queue gport
   1677  * Returns:
   1678  *     BCM_E_XXX
   1679  */
   1680 int
   1681 _bcm_hx5_cosq_port_cos_resolve(int unit, bcm_port_t port, bcm_cos_t cos,
   1682                               _bcm_hx5_cosq_index_style_t style,
   1683                               bcm_gport_t *gport)
   1684 {
   1685     _bcm_hx5_cosq_port_info_t *port_info = NULL;
   1686     _bcm_hx5_cosq_st_port_info_t *stport_info = NULL;
   1687     _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
   1688     int phy_port, mmu_port, port_index;
   1689 
   1690     soc_info_t *si = &SOC_INFO(unit);
   1691 
   1692     if (gport == NULL) {
   1693         return BCM_E_PARAM;
   1694     }
   1695 
   1696     if (_bcm_hx5_cosq_port_info[unit] == NULL) {
   1697         return BCM_E_INIT;
   1698     }
   1699 
   1700     if (_bcm_hx5_cosq_st_port_info[unit] == NULL) {
   1701         return BCM_E_INIT;
   1702     }
   1703     if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) {
   1704         return BCM_E_INIT;
   1705     }
   1706 
   1707     if ((IS_CPU_PORT(unit, port)) &&
   1708         (style == _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE)) {
   1709         return BCM_E_PARAM;
   1710     }
   1711 
   1712     if (cos < 0) {
   1713         return BCM_E_PARAM;
   1714     }
   1715 
   1716     if (!SOC_PORT_VALID(unit, port)) {
   1717         return BCM_E_PORT;
   1718     }
   1719 
   1720     if (_BCM_HX5_MMU_INFO(unit)->gport_tree_created != TRUE) {
   1721         return BCM_E_INTERNAL;
   1722     }
   1723 
   1724      phy_port = si->port_l2p_mapping[port];
   1725      mmu_port = si->port_p2m_mapping[phy_port];
   1726      _HX5_PORT_INDEX_GET(unit, mmu_port, port_index);
   1727 
   1728 
   1729      if (IS_CPU_PORT(unit, port)) {
   1730          cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit];
   1731          if (style == _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE) {
   1732              if (cos >= SOC_HX5_NUM_CPU_QUEUES) {
   1733                  return BCM_E_PARAM;
   1734              }
   1735              *gport = cpu_port_info->mcast[cos].gport;
   1736          } else {
   1737              return BCM_E_INTERNAL;
   1738          }
   1739      } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
   1740          stport_info = &_bcm_hx5_cosq_st_port_info[unit][port_index];
   1741          if (style == _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE) {
   1742              if (cos >= SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT) {
   1743                  return BCM_E_PARAM;
   1744              }
   1745              *gport = stport_info->ucast[cos].gport;
   1746          } else if (style == _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE) {
   1747              if (cos >= SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT) {
   1748                  return BCM_E_PARAM;
   1749              }
   1750              *gport = stport_info->mcast[cos].gport;
   1751          } else {
   1752              return BCM_E_INTERNAL;
   1753          }
   1754      } else {
   1755          port_info = &_bcm_hx5_cosq_port_info[unit][port_index];
   1756          if (style == _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE) {
   1757              if (cos >= SOC_HX5_NUM_UCAST_QUEUE_PER_PORT) {
   1758                  return BCM_E_PARAM;
   1759              }
   1760              *gport = port_info->ucast[cos].gport;
   1761          } else if (style == _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE) {
   1762              if (cos >= SOC_HX5_NUM_MCAST_QUEUE_PER_PORT) {
   1763                  return BCM_E_PARAM;
   1764              }
   1765              *gport = port_info->mcast[cos].gport;
   1766          } else {
   1767              return BCM_E_INTERNAL;
   1768          }
   1769      }
   1770 
   1771     return BCM_E_NONE;
   1772 }
   1773 
   1774 /*
   1775  * Function:
   1776  *     bcm_hx5_cosq_gport_attach
   1777  * Purpose:
   1778  *     Attach sched_port to the specified index (cosq) of input_port
   1779  * Parameters:
   1780  *     unit          - (IN) unit number
   1781  *     input_port    - (IN) GPORT id, that will attach to parent gport
   1782  *     parent_gport  - (IN) Parent Gport to which current gport will be attached
   1783  *     cosq          - (IN) COS queue to attach to (-1 for first available cosq)
   1784  * Returns:
   1785  *     BCM_E_XXX
   1786  */
   1787 int
   1788 bcm_hx5_cosq_gport_attach(int unit, bcm_gport_t input_gport,
   1789                           bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   1790 {
   1791     _bcm_hx5_cosq_node_t *input_node = NULL;
   1792     _bcm_hx5_cosq_node_t *parent_node = NULL;
   1793     bcm_port_t input_port, parent_port;
   1794     int phy_port, mmu_port;
   1795     soc_info_t *si = &SOC_INFO(unit);
   1796 
   1797     LOG_INFO(BSL_LS_BCM_COSQ,
   1798         (BSL_META_U(unit,
   1799                     "bcm_hx5_cosq_gport_attach: unit=%d parent_gport=0x%x "
   1800                     "input_gport=0x%x cosq=%d\n"), unit, parent_gport,
   1801                     input_gport, cosq));
   1802 
   1803     if (!(BCM_GPORT_IS_SCHEDULER(input_gport) ||
   1804         BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) ||
   1805         BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   1806         return BCM_E_PARAM;
   1807     }
   1808 
   1809     BCM_IF_ERROR_RETURN
   1810         (_bcm_hx5_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   1811                                &input_node));
   1812 
   1813     if (!input_node) {
   1814         return BCM_E_PARAM;
   1815     }
   1816     if (input_port < 0) {
   1817         return BCM_E_PORT;
   1818     }
   1819 
   1820     if (IS_CPU_PORT(unit, input_port)) {
   1821         return _bcm_hx5_cosq_cpu_gport_attach(unit, input_gport, parent_gport,
   1822                 cosq);
   1823     } else if (_BCM_HX5_MMU_INFO(unit)->gport_tree_created == TRUE) {
   1824         return BCM_E_PARAM;
   1825     }
   1826 
   1827     phy_port = si->port_l2p_mapping[input_port];
   1828     mmu_port = si->port_p2m_mapping[phy_port];
   1829 
   1830     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   1831         BCM_IF_ERROR_RETURN
   1832             (_bcm_hx5_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL,
   1833                                    &parent_node));
   1834     } else {
   1835         BCM_IF_ERROR_RETURN
   1836             (_bcm_hx5_cosq_localport_resolve(unit, parent_gport, &parent_port));
   1837             parent_node = NULL;
   1838     }
   1839 
   1840     if (input_port != parent_port) {
   1841         return BCM_E_PARAM;
   1842     }
   1843 
   1844     phy_port = si->port_l2p_mapping[parent_port];
   1845     mmu_port = si->port_p2m_mapping[phy_port];
   1846 
   1847     if(_HX5_IS_ST_PORT(unit, mmu_port)) {
   1848         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) {
   1849             input_node->hw_index = (mmu_port * SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT) + cosq;
   1850         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) {
   1851             input_node->hw_index = (mmu_port * SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT) +  cosq;
   1852         } else {
   1853             input_node->level = HX5_ST_SCHED_LEVEL_GET(unit, cosq);
   1854             switch(input_node->level) {
   1855                 case SOC_HX5_NODE_LVL_L0:
   1856                      input_node->hw_index = (mmu_port * _HX5_ST_NUML0_NODES) + cosq;
   1857                      break;
   1858                 case SOC_HX5_NODE_LVL_L1:
   1859                      input_node->hw_index = (mmu_port * _HX5_ST_NUML1_NODES) + (cosq - _HX5_ST_NUML0_NODES);
   1860                      break;
   1861                 case SOC_HX5_NODE_LVL_L2:
   1862                      input_node->hw_index = (mmu_port * _HX5_ST_NUML2_NODES) +
   1863                                              (cosq - (_HX5_ST_NUML1_NODES + _HX5_ST_NUML0_NODES));
   1864                      break;
   1865                 default:
   1866                      return BCM_E_PARAM;
   1867             }
   1868         }
   1869     }else {
   1870         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) {
   1871             input_node->hw_index = _HX5_BASE_L3QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS)  *
   1872                                                        SOC_HX5_NUM_UCAST_QUEUE_PER_PORT) + cosq;
   1873         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) {
   1874             input_node->hw_index = _HX5_BASE_L3QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS)  *
   1875                                                        SOC_HX5_NUM_MCAST_QUEUE_PER_PORT) +  cosq;
   1876         } else {
   1877             input_node->level = HX5_SCHED_LEVEL_GET(unit, cosq);
   1878             switch(input_node->level) {
   1879                 case SOC_HX5_NODE_LVL_L0:
   1880                      input_node->hw_index = _HX5_BASE_L0QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS)  *
   1881                                                                  _HX5_NUML0_NODES) + cosq;
   1882                      break;
   1883                 case SOC_HX5_NODE_LVL_L1:
   1884                      input_node->hw_index = _HX5_BASE_L1QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) *
   1885                                              _HX5_NUML1_NODES) + (cosq - _HX5_NUML0_NODES);
   1886                      break;
   1887                 case SOC_HX5_NODE_LVL_L2:
   1888                      input_node->hw_index = _HX5_BASE_L2QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS)  *
   1889                                             _HX5_NUML2_NODES) + (cosq - (_HX5_NUML1_NODES + _HX5_NUML0_NODES));
   1890                      break;
   1891                 default:
   1892                      return BCM_E_PARAM;
   1893             }
   1894         }
   1895     }
   1896 
   1897     if (BCM_GPORT_IS_SCHEDULER(input_gport)) {
   1898         if(input_node->level == SOC_HX5_NODE_LVL_L0) {
   1899             BCM_IF_ERROR_RETURN
   1900                 (bcm_esw_port_gport_get(unit, input_port,
   1901                                         &(input_node->parent_gport)));
   1902         } else {
   1903             input_node->parent_gport = parent_gport;
   1904         }
   1905     } else if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) ||
   1906                 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   1907         input_node->parent_gport = parent_gport;
   1908     }
   1909 
   1910     return BCM_E_NONE;
   1911 }
   1912 
   1913 
   1914 /*
   1915  * Function:
   1916  *     _bcm_hx5_cosq_cpu_gport_detach
   1917  * Purpose:
   1918  *     Detach any of the L3 MC Queue from its parent L2 nodes.
   1919  *     Post detach, L3 MC queue is attached to Parent L2.9 node
   1920  * Parameters:
   1921  *     unit        - (IN) unit number
   1922  *     input_port  - (IN) scheduler GPORT identifier
   1923  *     parent_port - (IN) GPORT to detach from
   1924  *     cosq        - (IN) COS queue to detach from
   1925  * Returns:
   1926  *     BCM_E_XXX
   1927  */
   1928     STATIC int
   1929 _bcm_hx5_cosq_cpu_gport_detach(int unit, bcm_gport_t input_gport,
   1930         bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   1931 {
   1932     bcm_port_t parent_port, input_port;
   1933     _bcm_hx5_cosq_node_t *input_node = NULL, *parent_node = NULL;
   1934     int input_cos = 0, parent_cos = 0, config_cos = 0;
   1935     int index = 0;
   1936 
   1937     /* Post Default tree created, expected Input
   1938      * Gport is of MC Gport
   1939      * and expected Parent Gport is new L0
   1940      * Parent
   1941      */
   1942     if ((!BCM_GPORT_IS_SCHEDULER(parent_gport)) ||
   1943             (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   1944         return BCM_E_PARAM;
   1945     }
   1946 
   1947     BCM_IF_ERROR_RETURN
   1948         (_bcm_hx5_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   1949                                 &input_node));
   1950     BCM_IF_ERROR_RETURN
   1951         (_bcm_hx5_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL,
   1952                                 &parent_node));
   1953 
   1954     if (!IS_CPU_PORT(unit, parent_port)) {
   1955         return BCM_E_PARAM;
   1956     }
   1957 
   1958     /* Return BCM_E_PARAM when queue to be detached is
   1959        not attached to the given gport */
   1960     if (input_node->parent_gport != parent_gport) {
   1961         return BCM_E_PARAM;
   1962     }
   1963 
   1964     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   1965         switch(parent_node->level) {
   1966             case SOC_HX5_NODE_LVL_L0:
   1967                 parent_cos =  parent_node->hw_index -  _HX5_CPU_LO_NODE_BASE;
   1968                 break;
   1969             case SOC_HX5_NODE_LVL_L1:
   1970                 parent_cos =  parent_node->hw_index -  _HX5_CPU_L1_NODE_BASE;
   1971                 break;
   1972             case SOC_HX5_NODE_LVL_L2:
   1973                 parent_cos =  parent_node->hw_index -  _HX5_CPU_L2_NODE_BASE;
   1974                 break;
   1975             default:
   1976                 return BCM_E_PARAM;
   1977         }
   1978     }
   1979 
   1980     input_cos = cosq % SOC_HX5_NUM_CPU_QUEUES;
   1981 
   1982     if(parent_node->level == SOC_HX5_NODE_LVL_L2) {
   1983         BCM_IF_ERROR_RETURN
   1984             (_bcm_hx5_cosq_cpu_parent_get(unit, input_cos, SOC_HX5_NODE_LVL_L3,
   1985                                           &config_cos));
   1986         if (config_cos != parent_cos) {
   1987             /* Error when detaching from wrong Parent (L0 level) */
   1988             return BCM_E_PARAM;
   1989         }
   1990 
   1991         /*
   1992          * L2.0 is associated with CMC0 CH1(Rx)
   1993          * L2.1 is associated with CMC0 CH2(Rx)
   1994          * L2.2 is associated with CMC0 CH3(Rx)
   1995          * L2.3 is associated with CMC0 CH4(Rx)
   1996          * L2.4 is associated with CMC0 CH5(Rx)
   1997          * L2.5 is associated with CMC0 CH6(Rx)
   1998          * L2.6 is associated with CMC0 CH7(Rx)
   1999          */
   2000         if ((parent_cos >= 0) && (parent_cos < 7)) {
   2001             BCM_IF_ERROR_RETURN
   2002                 (_bcm_hx5_cosq_rx_queue_channel_set(unit, parent_cos, input_cos,
   2003                                                     0));
   2004         }
   2005 
   2006         /* Reset parent to L0.9 */
   2007         index = _HX5_CPU_NUML2_NODES;
   2008         BCM_IF_ERROR_RETURN
   2009             (_bcm_hx5_cosq_cpu_parent_set(unit, input_cos, SOC_HX5_NODE_LVL_L3, index - 1));
   2010         index += 2;
   2011         input_node->parent_gport = _BCM_HX5_MMU_INFO(unit)->_bcm_hx5_cpu_port_info->
   2012             sched[index - 1].gport;
   2013     }
   2014     return BCM_E_NONE;
   2015 }
   2016 
   2017 
   2018 
   2019 
   2020 
   2021 /*
   2022  * Function:
   2023  *     bcm_hx5_cosq_gport_detach
   2024  * Purpose:
   2025  *     Detach sched_port from the specified index (cosq) of input_port
   2026  * Parameters:
   2027  *     unit        - (IN) unit number
   2028  *     input_port  - (IN) scheduler GPORT identifier
   2029  *     parent_port - (IN) GPORT to detach from
   2030  *     cosq        - (IN) COS queue to detach from
   2031  * Returns:
   2032  *     BCM_E_XXX
   2033  */
   2034 int
   2035 bcm_hx5_cosq_gport_detach(int unit, bcm_gport_t input_gport,
   2036                           bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   2037 {
   2038     _bcm_hx5_cosq_node_t *input_node = NULL, *parent_node = NULL;
   2039     bcm_port_t input_port, parent_port;
   2040     int input_hw_index = -1, parent_hw_index = -1;
   2041     int num_uc, num_mc, num_sc;
   2042     int phy_port, mmu_port;
   2043 
   2044     soc_info_t *si = &SOC_INFO(unit);
   2045     LOG_INFO(BSL_LS_BCM_COSQ,
   2046         (BSL_META_U(unit,
   2047                     "bcm_hx5_cosq_gport_detach: unit=%d input_gport=0x%x "
   2048                     "parent_gport=0x%x cosq=%d\n"),
   2049                     unit, input_gport, parent_gport, cosq));
   2050 
   2051     if (!(BCM_GPORT_IS_SCHEDULER(input_gport) ||
   2052         BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) ||
   2053         BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   2054         return BCM_E_PARAM;
   2055     }
   2056 
   2057     BCM_IF_ERROR_RETURN
   2058         (_bcm_hx5_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   2059                                 &input_node));
   2060 
   2061     if (!input_node) {
   2062         return BCM_E_PARAM;
   2063     }
   2064 
   2065     if (_BCM_HX5_MMU_INFO(unit)->gport_tree_created == TRUE) {
   2066         if (IS_CPU_PORT(unit, input_port)) {
   2067             return _bcm_hx5_cosq_cpu_gport_detach(unit, input_gport, parent_gport, cosq);
   2068         } else {
   2069             return BCM_E_PARAM;
   2070         }
   2071     }
   2072 
   2073     phy_port = si->port_l2p_mapping[input_port];
   2074     mmu_port = si->port_p2m_mapping[phy_port];
   2075 
   2076     if(_HX5_IS_ST_PORT(unit, mmu_port)) {
   2077         num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT;
   2078         num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT;
   2079         num_sc = SOC_HX5_NUM_SCHEDULER_PER_ST_PORT;
   2080     }else {
   2081         num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT;
   2082         num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_PORT;
   2083         num_sc = SOC_HX5_NUM_SCHEDULER_PER_PORT;
   2084     }
   2085 
   2086     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   2087         BCM_IF_ERROR_RETURN
   2088             (_bcm_hx5_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL,
   2089                                     &parent_node));
   2090     } else {
   2091         BCM_IF_ERROR_RETURN
   2092             (_bcm_hx5_cosq_localport_resolve(unit, parent_gport, &parent_port));
   2093             parent_node = NULL;
   2094     }
   2095 
   2096     if (input_port != parent_port) {
   2097         return BCM_E_PARAM;
   2098     }
   2099 
   2100     /* HX5 scheduler heirarchy is fixed. Hence check for wrong config. */
   2101     if (parent_node) {
   2102         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport)) {
   2103             input_hw_index = input_node->hw_index % num_uc;
   2104         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) {
   2105             input_hw_index = input_node->hw_index % num_mc;
   2106         } else {
   2107             input_hw_index = input_node->hw_index % num_sc;
   2108         }
   2109 
   2110         if (parent_node->level == SOC_HX5_NODE_LVL_L2) {
   2111             parent_hw_index = parent_node->hw_index % num_sc;
   2112 
   2113             if (input_hw_index != parent_hw_index) {
   2114                 return BCM_E_PARAM;
   2115             }
   2116         }
   2117     }
   2118 
   2119     return BCM_E_NONE;
   2120 }
   2121 
   2122 /*
   2123  * Function:
   2124  *     bcm_hx5_cosq_gport_attach_get
   2125  * Purpose:
   2126  *     Get attached status of a scheduler port
   2127  * Parameters:
   2128  *     unit       - (IN) unit number
   2129  *     sched_port - (IN) scheduler GPORT identifier
   2130  *     input_port - (OUT) GPORT to attach to
   2131  *     cosq       - (OUT) COS queue to attached to
   2132  * Returns:
   2133  *     BCM_E_XXX
   2134  */
   2135 int
   2136 bcm_hx5_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport,
   2137         bcm_gport_t *input_gport, bcm_cos_queue_t *cosq)
   2138 {
   2139     _bcm_hx5_cosq_node_t *node = NULL;
   2140     bcm_port_t local_port = -1;
   2141     int phy_port, mmu_port;
   2142     int num_uc, num_mc;
   2143 
   2144     soc_info_t *si = &SOC_INFO(unit);
   2145 
   2146     if (!(BCM_GPORT_IS_SET(sched_gport) ||
   2147                 BCM_GPORT_IS_SCHEDULER(sched_gport) ||
   2148                 BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) ||
   2149                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport))) {
   2150         return BCM_E_PARAM;
   2151     }
   2152 
   2153     BCM_IF_ERROR_RETURN
   2154         (_bcm_hx5_cosq_node_get(unit, sched_gport, NULL, &local_port, NULL,
   2155                                 &node));
   2156 
   2157     if (node == NULL) {
   2158         return BCM_E_PARAM;
   2159     }
   2160 
   2161     if (local_port < 0) {
   2162         return BCM_E_PARAM;
   2163     }
   2164 
   2165     phy_port = si->port_l2p_mapping[local_port];
   2166     mmu_port = si->port_p2m_mapping[phy_port];
   2167 
   2168     if(IS_CPU_PORT(unit, local_port)){
   2169         num_uc = 0;
   2170         num_mc = SOC_HX5_NUM_CPU_QUEUES;
   2171     }else {
   2172         if(_HX5_IS_ST_PORT(unit, mmu_port)) {
   2173             num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT;
   2174             num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT;
   2175         }else {
   2176             num_uc = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT;
   2177             num_mc = SOC_HX5_NUM_MCAST_QUEUE_PER_PORT;
   2178         }
   2179     }
   2180 
   2181 
   2182     if (BCM_GPORT_IS_SCHEDULER(sched_gport)) {
   2183         switch(node->level) {
   2184             case SOC_HX5_NODE_LVL_L0:
   2185                 if(IS_CPU_PORT(unit, local_port)){
   2186                     *cosq = node->hw_index - _HX5_CPU_LO_NODE_BASE;
   2187                 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
   2188                     *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML0_NODES);
   2189                 } else {
   2190                     *cosq = node->hw_index - (_HX5_BASE_L0QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS)  * _HX5_NUML0_NODES));
   2191                 }
   2192                 break;
   2193             case SOC_HX5_NODE_LVL_L1:
   2194                 if(IS_CPU_PORT(unit, local_port)){
   2195                     *cosq = node->hw_index - _HX5_CPU_L1_NODE_BASE;
   2196                 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
   2197                     *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML1_NODES);
   2198                 } else {
   2199                     *cosq = node->hw_index - (_HX5_BASE_L1QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML1_NODES));
   2200                 }
   2201                 break;
   2202             case SOC_HX5_NODE_LVL_L2:
   2203                 if(IS_CPU_PORT(unit, local_port)){
   2204                     *cosq = node->hw_index - _HX5_CPU_L2_NODE_BASE;
   2205                 } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
   2206                     *cosq = node->hw_index - (mmu_port * _HX5_ST_NUML2_NODES);
   2207                 } else {
   2208                     *cosq = node->hw_index - (_HX5_BASE_L2QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML2_NODES));
   2209                 }
   2210                 break;
   2211             default:
   2212                 return BCM_E_PARAM;
   2213         }
   2214     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport)) {
   2215         if(_HX5_IS_ST_PORT(unit, mmu_port)){
   2216             *cosq = node->hw_index - (mmu_port * num_uc);
   2217         } else {
   2218             *cosq = node->hw_index - (_HX5_BASE_L3QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS)* num_uc));
   2219         }
   2220     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)) {
   2221         if(IS_CPU_PORT(unit, local_port)){
   2222             *cosq = node->hw_index - _HX5_CPU_L2_NODE_BASE;
   2223         } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
   2224             *cosq = node->hw_index - (mmu_port * num_mc);
   2225         } else {
   2226             *cosq = node->hw_index - (_HX5_BASE_L3QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * num_mc));
   2227         }
   2228     } else {
   2229         return BCM_E_PARAM;
   2230     }
   2231 
   2232     *input_gport = node->parent_gport;
   2233     return BCM_E_NONE;
   2234 }
   2235 
   2236 /*
   2237  * Function:
   2238  *     bcm_hx5_cosq_gport_traverse
   2239  * Purpose:
   2240  *     Walks through the valid COSQ GPORTs and calls
   2241  *     the user supplied callback function for each entry.
   2242  * Parameters:
   2243  *     unit       - (IN) unit number
   2244  *     trav_fn    - (IN) Callback function.
   2245  *     user_data  - (IN) User data to be passed to callback function
   2246  * Returns:
   2247  *     BCM_E_NONE - Success.
   2248  *     BCM_E_XXX
   2249  */
   2250 int
   2251 bcm_hx5_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb,
   2252         void *user_data)
   2253 {
   2254     _bcm_hx5_cosq_port_info_t *port_info = NULL;
   2255     _bcm_hx5_cosq_st_port_info_t *stport_info = NULL;
   2256     _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
   2257     bcm_module_t my_modid, modid_out;
   2258     bcm_port_t port, port_out, local_port;
   2259     bcm_gport_t gport;
   2260     int id, rv = SOC_E_NONE;
   2261     int phy_port, mmu_port, index;
   2262 
   2263     soc_info_t *si = &SOC_INFO(unit);
   2264 
   2265     if (_bcm_hx5_cosq_port_info[unit] == NULL) {
   2266         return BCM_E_INIT;
   2267     }
   2268     if (_bcm_hx5_cosq_st_port_info[unit] == NULL) {
   2269         return BCM_E_INIT;
   2270     }
   2271     if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) {
   2272         return BCM_E_INIT;
   2273     }
   2274 
   2275     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   2276     PBMP_ALL_ITER(unit, port) {
   2277         BCM_IF_ERROR_RETURN
   2278             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, my_modid,  port,
   2279                                      &modid_out, &port_out));
   2280         BCM_GPORT_MODPORT_SET(gport, modid_out, port_out);
   2281 
   2282         BCM_IF_ERROR_RETURN
   2283             (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
   2284 
   2285         phy_port = si->port_l2p_mapping[local_port];
   2286         mmu_port = si->port_p2m_mapping[phy_port];
   2287         _HX5_PORT_INDEX_GET(unit, mmu_port, index);
   2288         if (IS_CPU_PORT(unit, local_port)) {
   2289             cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit];
   2290         } else {
   2291             if(_HX5_IS_ST_PORT(unit, mmu_port)) {
   2292                 stport_info = &_bcm_hx5_cosq_st_port_info[unit][index];
   2293             }else {
   2294                 port_info = &_bcm_hx5_cosq_port_info[unit][index];
   2295             }
   2296         }
   2297 
   2298         if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) {
   2299             for (id = 0; id < SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; id++) {
   2300                 if (port_info->ucast[id].numq == 0) {
   2301                     continue;
   2302                 }
   2303                 rv = cb(unit, gport, port_info->ucast[id].numq,
   2304                         BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
   2305                         port_info->ucast[id].gport, user_data);
   2306             }
   2307 #ifdef BCM_CB_ABORT_ON_ERR
   2308             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2309                 return rv;
   2310             }
   2311 #else
   2312             rv = BCM_E_NONE;
   2313 #endif
   2314         }
   2315 
   2316         if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) {
   2317             for (id = 0; id < SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; id++) {
   2318                 if (stport_info->ucast[id].numq == 0) {
   2319                     continue;
   2320                 }
   2321                 rv = cb(unit, gport, stport_info->ucast[id].numq,
   2322                         BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
   2323                         stport_info->ucast[id].gport, user_data);
   2324             }
   2325 #ifdef BCM_CB_ABORT_ON_ERR
   2326             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2327                 return rv;
   2328             }
   2329 #else
   2330             rv = BCM_E_NONE;
   2331 #endif
   2332         }
   2333 
   2334         if (IS_CPU_PORT(unit, local_port)) {
   2335             for (id = 0; id < SOC_HX5_NUM_CPU_QUEUES; id++) {
   2336                 if (cpu_port_info->mcast[id].numq == 0) {
   2337                     continue;
   2338                 }
   2339                 rv = cb(unit, gport, cpu_port_info->mcast[id].numq,
   2340                         BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   2341                         cpu_port_info->mcast[id].gport, user_data);
   2342 #ifdef BCM_CB_ABORT_ON_ERR
   2343                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2344                     return rv;
   2345                 }
   2346 #else
   2347                 rv = BCM_E_NONE;
   2348 #endif
   2349             }
   2350         } 
   2351 
   2352         if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) {
   2353             for (id = 0; id < SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; id++) {
   2354                 if (port_info->mcast[id].numq == 0) {
   2355                     continue;
   2356                 }
   2357                 rv = cb(unit, gport, port_info->mcast[id].numq,
   2358                         BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   2359                         port_info->mcast[id].gport, user_data);
   2360             }
   2361 #ifdef BCM_CB_ABORT_ON_ERR
   2362             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2363                 return rv;
   2364             }
   2365 #else
   2366             rv = BCM_E_NONE;
   2367 #endif
   2368         }
   2369 
   2370 
   2371         if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) {
   2372             for (id = 0; id < SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; id++) {
   2373                 if (stport_info->mcast[id].numq == 0) {
   2374                     continue;
   2375                 }
   2376                 rv = cb(unit, gport, stport_info->mcast[id].numq,
   2377                         BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   2378                         stport_info->mcast[id].gport, user_data);
   2379             }
   2380 #ifdef BCM_CB_ABORT_ON_ERR
   2381             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2382                 return rv;
   2383             }
   2384 #else
   2385             rv = BCM_E_NONE;
   2386 #endif
   2387         }
   2388 
   2389 
   2390         if (IS_CPU_PORT(unit, local_port)) {
   2391             for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; id++) {
   2392                 if (cpu_port_info->sched[id].numq == 0) {
   2393                     continue;
   2394                 }
   2395                 rv = cb(unit, gport, cpu_port_info->sched[id].numq,
   2396                         BCM_COSQ_GPORT_SCHEDULER,
   2397                         cpu_port_info->sched[id].gport, user_data);
   2398 #ifdef BCM_CB_ABORT_ON_ERR
   2399                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2400                     return rv;
   2401                 }
   2402 #else
   2403                 rv = BCM_E_NONE;
   2404 #endif
   2405             }
   2406         }
   2407 
   2408         if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) {
   2409             for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_PORT; id++) {
   2410                 if (port_info->sched[id].numq == 0) {
   2411                     continue;
   2412                 }
   2413                 rv = cb(unit, gport, port_info->sched[id].numq,
   2414                         BCM_COSQ_GPORT_SCHEDULER,
   2415                         port_info->sched[id].gport, user_data);
   2416             }
   2417 #ifdef BCM_CB_ABORT_ON_ERR
   2418             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2419                 return rv;
   2420             }
   2421 #else
   2422             rv = BCM_E_NONE;
   2423 #endif
   2424         }
   2425 
   2426 
   2427         if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) {
   2428             for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; id++) {
   2429                 if (stport_info->sched[id].numq == 0) {
   2430                     continue;
   2431                 }
   2432                 rv = cb(unit, gport, stport_info->sched[id].numq,
   2433                         BCM_COSQ_GPORT_SCHEDULER,
   2434                         stport_info->sched[id].gport, user_data);
   2435             }
   2436 #ifdef BCM_CB_ABORT_ON_ERR
   2437             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2438                 return rv;
   2439             }
   2440 #else
   2441             rv = BCM_E_NONE;
   2442 #endif
   2443         }
   2444 
   2445    }
   2446     return rv;
   2447 }
   2448 
   2449 STATIC void 
   2450 _bcm_hx5_gport_numq_get(int unit, int id, int *numq)
   2451 {
   2452     switch(id) {
   2453     case 1:
   2454     case 2:
   2455         *numq = 1;
   2456         break;
   2457     case 3:
   2458     case 4:
   2459     case 5:
   2460         *numq = 8;
   2461         break;
   2462     default:
   2463     case 6:
   2464         *numq = 2;
   2465         break;
   2466     }
   2467 }
   2468 /*
   2469  * Function:
   2470  *      _bcm_hx5_cosq_st_gport_tree_create
   2471  * Purpose:
   2472  *      During cosq init create the default cosq gport tree.
   2473  *      Schedualar (L0) nodes are created and attach to physical ports.
   2474  *      UC and MC queues are added and attached to each L0 nodes.
   2475  * Parameters:
   2476  *      unit - (IN) unit number.
   2477  *      port - (IN) port number
   2478  * Returns:
   2479  *     BCM_E_XXX
   2480  */
   2481 STATIC int
   2482 _bcm_hx5_cosq_st_gport_tree_create(int unit, bcm_port_t port)
   2483 {
   2484     int id, sc_id;
   2485     bcm_gport_t sched_gport[SOC_HX5_NUM_SCHEDULER_PER_ST_PORT];
   2486     bcm_gport_t uc_gport[SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT];
   2487     bcm_gport_t mc_gport[SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT];
   2488     int numq = 1;
   2489 
   2490     /*Creating all L0,L1 and L2 scheduler nodes */
   2491     for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; id++) {
   2492         _bcm_hx5_gport_numq_get(unit, id, &numq);        
   2493         BCM_IF_ERROR_RETURN
   2494             (_bcm_hx5_cosq_gport_add(unit, port, numq, BCM_COSQ_GPORT_SCHEDULER,
   2495                                      &sched_gport[id]));
   2496     }
   2497 
   2498     /* Attaching L0 schedular node to front panel port */
   2499     for (sc_id = 0; sc_id < 3; sc_id++) {
   2500         BCM_IF_ERROR_RETURN
   2501             (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], port, sc_id));
   2502     }
   2503     /* Attaching L1 schedular nodes to l0 Schedular nodes */
   2504     for (sc_id = 3; sc_id < 7; sc_id++) {
   2505         if (sc_id == 3) {
   2506             BCM_IF_ERROR_RETURN
   2507                 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id],
   2508                                            sched_gport[0], sc_id));
   2509         } else if (sc_id > 3 && sc_id < 6) {
   2510             BCM_IF_ERROR_RETURN
   2511                 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id],
   2512                                            sched_gport[1], sc_id));
   2513         } else {
   2514             BCM_IF_ERROR_RETURN
   2515                 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id],
   2516                                            sched_gport[2], sc_id));
   2517         }
   2518     }
   2519 
   2520     /* Aattaching L2 schedular nodes to  l1 Schedular nodes */
   2521    for (sc_id = 7; sc_id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; sc_id++) {
   2522         if (sc_id < 15) {
   2523             BCM_IF_ERROR_RETURN
   2524                 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id],
   2525                                            sched_gport[3], sc_id));
   2526         } else if((sc_id >= 15) && (sc_id < 23)) {
   2527             BCM_IF_ERROR_RETURN
   2528                 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id],
   2529                                            sched_gport[4], sc_id));
   2530         } else if((sc_id >= 23 ) && (sc_id < 31)) {
   2531             BCM_IF_ERROR_RETURN
   2532                 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id],
   2533                                            sched_gport[5], sc_id));
   2534         } else {
   2535             BCM_IF_ERROR_RETURN
   2536                 (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id],
   2537                                            sched_gport[6], sc_id));
   2538         }
   2539     }
   2540     numq = 1;
   2541    /* Creating and attaching l3 uc and l2 mc queues to  l2 Schedular nodes */
   2542    for (id = 0, sc_id = 7; id < SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT &&
   2543            sc_id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; id++, sc_id++) {
   2544        BCM_IF_ERROR_RETURN
   2545            (_bcm_hx5_cosq_gport_add(unit, port, numq,
   2546                                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
   2547                                     &uc_gport[id]));
   2548        BCM_IF_ERROR_RETURN
   2549            (bcm_hx5_cosq_gport_attach(unit, uc_gport[id],
   2550                                       sched_gport[sc_id], id));
   2551 
   2552        BCM_IF_ERROR_RETURN
   2553            (_bcm_hx5_cosq_gport_add(unit, port, numq,
   2554                                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   2555                                     &mc_gport[id]));
   2556        BCM_IF_ERROR_RETURN
   2557            (bcm_hx5_cosq_gport_attach(unit, mc_gport[id],
   2558                                       sched_gport[sc_id], id));
   2559    }
   2560    return BCM_E_NONE;
   2561 }
   2562 
   2563 /*
   2564  * Function:
   2565  *     bcm_hx5_cosq_sched_weight_max_get
   2566  * Purpose:
   2567  *     Retrieve maximum weights for given COS policy
   2568  * Parameters:
   2569  *     unit       - (IN) unit number
   2570  *     mode       - (IN) Scheduling mode (BCM_COSQ_xxx)
   2571  *     weight_max - (OUT) Maximum weight for COS queue.
   2572  * Returns:
   2573  *     BCM_E_XXX
   2574  */
   2575     int
   2576 bcm_hx5_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   2577 {
   2578     switch (mode) {
   2579         case BCM_COSQ_STRICT:
   2580             *weight_max = BCM_COSQ_WEIGHT_STRICT;
   2581             break;
   2582         case BCM_COSQ_ROUND_ROBIN:
   2583         case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   2584         case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   2585             /* In hx5, weights can be [1, 127] */
   2586             *weight_max =
   2587                 (1 << soc_mem_field_length(unit, Q_SCHED_L0_WEIGHT_MEMm,
   2588                                            WEIGHTf)) - 1;
   2589             break;
   2590         default:
   2591             return BCM_E_PARAM;
   2592     }
   2593 
   2594     return BCM_E_NONE;
   2595 }
   2596 
   2597 
   2598 /*
   2599  * Function:
   2600  *     _bcm_hx5_sched_weight_setget
   2601  * Purpose:
   2602  *     Get/Set weights for given COS policy
   2603  * Parameters:
   2604  *     unit     - (IN)  unit number
   2605  *     port     - (IN)  port number
   2606  *     level    - (IN)  node level
   2607  *     index    - (IN)  COS queue number
   2608  *     weights  - (OUT) Weights for COS queue.
   2609  *     mc       - (IN)  Multicast queue group
   2610  *     setget   - (IN)  Set/get flag
   2611  * Returns:
   2612  *     BCM_E_XXX
   2613  */
   2614 STATIC int
   2615 _bcm_hx5_sched_weight_setget(int unit, int port, int level, int index,
   2616         int *weight, int mc, int setget)
   2617 {
   2618     soc_info_t *si;
   2619     soc_mem_t mem = INVALIDm;
   2620     uint32 entry[SOC_MAX_MEM_WORDS];
   2621     int pipe;
   2622     int phy_port, mmu_port;
   2623 
   2624     si = &SOC_INFO(unit);
   2625     pipe = si->port_pipe[port];
   2626     phy_port = si->port_l2p_mapping[port];
   2627     mmu_port = si->port_p2m_mapping[phy_port];
   2628 
   2629     switch(level) {
   2630         case SOC_HX5_NODE_LVL_L0:
   2631             mem = Q_SCHED_L0_WEIGHT_MEMm;
   2632             if(IS_CPU_PORT(unit, port)) {
   2633                 index = _HX5_CPU_LO_NODE_BASE;
   2634             } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
   2635                index += (mmu_port * _HX5_ST_NUML0_NODES);
   2636             } else {
   2637                index +=  _HX5_BASE_L0QUEUE +  ((mmu_port - _BCM_HX5_NUM_ST_PORTS)  * _HX5_NUML0_NODES);
   2638             }
   2639             break;
   2640 
   2641         case SOC_HX5_NODE_LVL_L1:
   2642             mem = Q_SCHED_L1_WEIGHT_MEMm;
   2643             if(IS_CPU_PORT(unit, port)) {
   2644                 index = _HX5_CPU_L1_NODE_BASE;
   2645             } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
   2646                index += (mmu_port * _HX5_ST_NUML1_NODES);
   2647             } else {
   2648                index += _HX5_BASE_L1QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML1_NODES);
   2649             }
   2650             break;
   2651 
   2652         case SOC_HX5_NODE_LVL_L2:
   2653             mem = Q_SCHED_L2_WEIGHT_MEMm;
   2654             if(IS_CPU_PORT(unit, port)) {
   2655                 index = _HX5_CPU_L2_NODE_BASE;
   2656             } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
   2657                index += (mmu_port * _HX5_ST_NUML2_NODES);
   2658             } else {
   2659                index += _HX5_BASE_L2QUEUE + ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * _HX5_NUML2_NODES);
   2660             }
   2661             break;
   2662 
   2663         case SOC_HX5_NODE_LVL_L3:
   2664             mem = Q_SCHED_L3_WEIGHT_MEMm;
   2665             if(IS_CPU_PORT(unit, port)) {
   2666                 index += _HX5_CPU_L2_NODE_BASE;
   2667             } else if(_HX5_IS_ST_PORT(unit, mmu_port)){
   2668                 index +=  (mmu_port * SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT);
   2669             } else {
   2670                 index +=  ((mmu_port - _BCM_HX5_NUM_ST_PORTS) * SOC_HX5_NUM_UCAST_QUEUE_PER_PORT);
   2671             }
   2672             if(mc == 1) {
   2673                 index += SOC_HX5_NUM_UC_QUEUES_PER_PIPE;
   2674             }
   2675             break;
   2676         default:
   2677         return BCM_E_PARAM;
   2678     }
   2679 
   2680     mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe];
   2681     SOC_IF_ERROR_RETURN
   2682         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry));
   2683 
   2684     if (setget == 1) {
   2685         soc_mem_field32_set(unit, mem, &entry, WEIGHTf, *weight);
   2686         SOC_IF_ERROR_RETURN
   2687             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry));
   2688     } else {
   2689         *weight = soc_mem_field32_get(unit, mem, &entry, WEIGHTf);
   2690     }
   2691 
   2692     return BCM_E_NONE;
   2693 }
   2694 
   2695 
   2696 
   2697 
   2698 /*
   2699  * Function:
   2700  *     _bcm_hx5_cosq_sched_mode_setget
   2701  * Purpose:
   2702  *     Get/Set scheduling mode
   2703  * Parameters:
   2704  *     unit     - (IN)  Unit number
   2705  *     port     - (IN)  Port number
   2706  *     level    - (IN)  Node level
   2707  *     index    - (IN)  COS queue number
   2708  *     mode     - (IN/OUT) Scheduling mode (BCM_COSQ_xxx)
   2709  *     weights  - (IN/OUT) Weights for COS queue.
   2710  *     mc       - (IN)  Multicast queue group
   2711  *     setget   - (IN)  Set/get flag
   2712  * Returns:
   2713  *     BCM_E_XXX
   2714  */
   2715 STATIC int
   2716 _bcm_hx5_cosq_sched_mode_setget(int unit, bcm_port_t port, int level, int index,
   2717         soc_hx5_sched_mode_e *mode, int *weight, int mc,
   2718         int setget)
   2719 {
   2720     soc_reg_t reg;
   2721     uint32 fval = 0, rval, wrr_mask;
   2722     uint64 rval64;
   2723     int parent_index = 0;
   2724     int mmu_port, phy_port;
   2725 
   2726     soc_info_t *si = &SOC_INFO(unit);
   2727     phy_port = si->port_l2p_mapping[port];
   2728     mmu_port = si->port_p2m_mapping[phy_port];
   2729 
   2730     if (setget == 1) {
   2731         LOG_INFO(BSL_LS_SOC_COSQ,
   2732                 (BSL_META_U(unit,
   2733                             "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"),
   2734                  port, (level == 0) ? "r" : "", level - 1, index, *mode,
   2735                  *weight));
   2736     }
   2737 
   2738 
   2739 
   2740     /* Selection between SP and WxRR is based on weight property. */
   2741     BCM_IF_ERROR_RETURN
   2742         (_bcm_hx5_sched_weight_setget(unit, port, level, index, weight, mc,
   2743                                       setget));
   2744 
   2745     if ((level == SOC_HX5_NODE_LVL_L1 || level == SOC_HX5_NODE_LVL_L2) && (IS_CPU_PORT(unit, port))) {
   2746             return BCM_E_NONE;
   2747     }
   2748 
   2749     switch(level) {
   2750         case SOC_HX5_NODE_LVL_L0:
   2751             reg = IS_CPU_PORT(unit, port) ? Q_SCHED_CPU_PORT_CONFIGr : Q_SCHED_PORT_CONFIGr;
   2752             index = 0;
   2753             break;
   2754 
   2755         case SOC_HX5_NODE_LVL_L1:
   2756             if(_HX5_IS_ST_PORT(unit, mmu_port)) {
   2757                 reg = Q_SCHED_L0_NODE_CONFIG_HIQr;
   2758                 index = (index == 0) ? 0 : (index > 0 && index < 3) ? 1 : 2;
   2759             } else {
   2760                 reg = Q_SCHED_L0_NODE_CONFIGr;
   2761                 index = 0;
   2762             }
   2763             break;
   2764 
   2765         case SOC_HX5_NODE_LVL_L2:
   2766             if(_HX5_IS_ST_PORT(unit, mmu_port)) {
   2767                 reg = Q_SCHED_L1_NODE_CONFIG_HIQr;
   2768                 if( index >= 0 && index < 8 ) {
   2769                     index = 0;
   2770                 } else if (index >= 8 && index < 16 ){
   2771                     index = 1;
   2772                 } else if (index >= 16 && index < 24 ){
   2773                     index = 2;
   2774                 } else {
   2775                     index = 3;
   2776                 }
   2777             } else {
   2778                 reg = Q_SCHED_L1_NODE_CONFIGr;
   2779                 index = (index >= 0 && index < 8) ? 0 : 1;
   2780             }
   2781             break;
   2782 
   2783         case SOC_HX5_NODE_LVL_L3:
   2784             if (IS_CPU_PORT(unit, port)) {
   2785                 reg = Q_SCHED_CPU_L2_NODE_CONFIGr;
   2786                 SOC_IF_ERROR_RETURN
   2787                     (_bcm_hx5_cosq_cpu_parent_get(unit, index, SOC_HX5_NODE_LVL_L3,
   2788                                                   &parent_index));
   2789                 index = parent_index;
   2790             } else if(_HX5_IS_ST_PORT(unit, mmu_port)) {
   2791                 reg = Q_SCHED_L2_NODE_CONFIG_HIQ_SPLIT0r;
   2792             } else {
   2793                 reg = Q_SCHED_L2_NODE_CONFIG_NORMQr;
   2794             }
   2795             break;
   2796         default:
   2797             return BCM_E_PARAM;
   2798 
   2799     }
   2800 
   2801     if (SOC_REG_IS_64(unit, reg)) {
   2802         SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64));
   2803         wrr_mask = soc_reg64_field32_get(unit, reg, rval64, ENABLE_WRRf);
   2804     } else {
   2805         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval));
   2806         wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf);
   2807     }
   2808 
   2809     if (setget == 1) {
   2810         if (*mode == SOC_HX5_SCHED_MODE_WRR) {
   2811             fval = 1;
   2812         } else if (*mode == SOC_HX5_SCHED_MODE_WERR) {
   2813             fval = 0;
   2814         } else {
   2815             return BCM_E_NONE;
   2816         }
   2817 
   2818         wrr_mask &= ~(1 << index);
   2819         wrr_mask |= (fval << index);
   2820         if (SOC_REG_IS_64(unit, reg)) {
   2821             soc_reg64_field32_set(unit, reg, &rval64, ENABLE_WRRf, wrr_mask);
   2822             SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64));
   2823         }else {
   2824             soc_reg_field_set(unit, reg, &rval, ENABLE_WRRf, wrr_mask);
   2825             SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval));
   2826         }
   2827     } else {
   2828         if (*weight == 0) {
   2829             *mode = SOC_HX5_SCHED_MODE_STRICT;
   2830         } else if (wrr_mask & (1 << index)) {
   2831             *mode = SOC_HX5_SCHED_MODE_WRR;
   2832         } else {
   2833             *mode = SOC_HX5_SCHED_MODE_WERR;
   2834         }
   2835     }
   2836 
   2837     return BCM_E_NONE;
   2838 }
   2839 
   2840 
   2841 /*
   2842  * Function:
   2843  *     _bcm_hx5_cosq_sched_get
   2844  * Purpose:
   2845  *     Get scheduling mode setting
   2846  * Parameters:
   2847  *     unit     - (IN) unit number
   2848  *     gport    - (IN) GPORT identifier
   2849  *     cosq     - (IN) COS queue number
   2850  *     mode     - (OUT) Scheduling mode (BCM_COSQ_xxx)
   2851  *     weights  - (OUT) Weights for COS queue.
   2852  * Returns:
   2853  *     BCM_E_XXX
   2854  */
   2855     STATIC int
   2856 _bcm_hx5_cosq_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   2857         int *mode, int *weight)
   2858 {
   2859     soc_hx5_sched_mode_e sched_mode;
   2860     bcm_port_t local_port;
   2861     _bcm_hx5_cosq_node_t *node = NULL;
   2862     int lvl = SOC_HX5_NODE_LVL_L2, mc = 0;
   2863 
   2864 
   2865     if (BCM_GPORT_IS_SET(gport)) {
   2866         BCM_IF_ERROR_RETURN
   2867             (_bcm_hx5_cosq_node_get(unit, gport, NULL, &local_port, NULL,
   2868                                     &node));
   2869         lvl = node->level;
   2870     }else {
   2871         BCM_IF_ERROR_RETURN
   2872             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   2873 
   2874     }
   2875 
   2876     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   2877             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2878         mc = BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1 : 0;
   2879     } else if (IS_CPU_PORT(unit, local_port)) {
   2880         mc = 1;
   2881         lvl = SOC_HX5_NODE_LVL_L3;
   2882     }
   2883 
   2884     BCM_IF_ERROR_RETURN
   2885         (_bcm_hx5_cosq_sched_mode_setget(unit, local_port, lvl, cosq,
   2886                                          &sched_mode, weight, mc, 0));
   2887 
   2888     switch(sched_mode) {
   2889         case SOC_HX5_SCHED_MODE_STRICT:
   2890             *mode = BCM_COSQ_STRICT;
   2891             break;
   2892 
   2893         case SOC_HX5_SCHED_MODE_WRR:
   2894             *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   2895             break;
   2896 
   2897         case SOC_HX5_SCHED_MODE_WERR:
   2898             *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   2899             break;
   2900 
   2901         default:
   2902             return BCM_E_INTERNAL;
   2903     }
   2904 
   2905     return BCM_E_NONE;
   2906 }
   2907 
   2908 /*
   2909  * Function:
   2910  *     bcm_hx5_cosq_gport_sched_get
   2911  * Purpose:
   2912  *     Get COS queue schedular setting
   2913  * Parameters:
   2914  *     unit     - (IN) unit number
   2915  *     gport    - (IN) GPORT identifier
   2916  *     cosq     - (IN) COS queue to get, -1 for any queue
   2917  *     mode     - (OUT) Scheduling mode (BCM_COSQ_xxx)
   2918  *     weights  - (OUT) Weights for COS queue.
   2919  * Returns:
   2920  *     BCM_E_XXX
   2921  */
   2922     int
   2923 bcm_hx5_cosq_gport_sched_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   2924         int *mode, int *weight)
   2925 {
   2926     int local_port = -1;
   2927     soc_info_t *si = &SOC_INFO(unit);
   2928 
   2929     if (BCM_GPORT_IS_SET(gport)) {
   2930         if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   2931                 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   2932                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2933 
   2934             BCM_IF_ERROR_RETURN
   2935                 (_bcm_hx5_cosq_node_hw_index_get(unit, gport, &cosq));
   2936 
   2937             BCM_IF_ERROR_RETURN
   2938                 (_bcm_hx5_cosq_sched_get(unit, gport, cosq, mode, weight));
   2939             return BCM_E_NONE;
   2940         } else {
   2941             BCM_IF_ERROR_RETURN
   2942                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   2943 
   2944             if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) {
   2945                 return BCM_E_PARAM;
   2946             }
   2947 
   2948             BCM_IF_ERROR_RETURN
   2949                 (_bcm_hx5_cosq_sched_get(unit, local_port, cosq, mode, weight));
   2950             return BCM_E_NONE;
   2951         }
   2952     } else {
   2953         return BCM_E_PORT;
   2954     }
   2955 
   2956     return BCM_E_NOT_FOUND;
   2957 }
   2958 
   2959 
   2960 /*
   2961  * Function:
   2962  *     bcm_hx5_cosq_port_sched_get
   2963  * Purpose:
   2964  *     Retrieve class-of-service policy and corresponding weights and delay
   2965  * Parameters:
   2966  *     unit     - (IN) unit number
   2967  *     pbm      - (IN) port bitmap
   2968  *     mode     - (OUT) Scheduling mode (BCM_COSQ_xxx)
   2969  *     weights  - (OUT) Weights for each COS queue.
   2970  *     delay    - This parameter is not used
   2971  * Returns:
   2972  *     BCM_E_XXX
   2973  */
   2974     int
   2975 bcm_hx5_cosq_port_sched_get(int unit, bcm_pbmp_t pbm, int *mode, int *weights,
   2976         int *delay)
   2977 {
   2978     bcm_port_t port;
   2979     int num_weights, i;
   2980 
   2981     BCM_PBMP_ITER(pbm, port) {
   2982         if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) {
   2983             continue;
   2984         }
   2985         num_weights = _BCM_HX5_NUM_COS(unit); 
   2986         for (i = 0; i < num_weights; i++) {
   2987             BCM_IF_ERROR_RETURN(
   2988                     _bcm_hx5_cosq_sched_get(unit, port, i, mode, &weights[i]));
   2989         }
   2990     }
   2991 
   2992     return BCM_E_NONE;
   2993 }
   2994 
   2995 
   2996 
   2997 
   2998 /*
   2999  * Function:
   3000  *     _bcm_hx5_cosq_sched_set
   3001  * Purpose:
   3002  *     Set scheduling mode
   3003  * Parameters:
   3004  *     unit     - (IN) unit number
   3005  *     gport    - (IN) GPORT identifier
   3006  *     cosq     - (IN) COS queue number
   3007  *     mode     - (IN) Scheduling mode (BCM_COSQ_xxx)
   3008  *     weights  - (IN) Weight for COS queue.
   3009  * Returns:
   3010  *     BCM_E_XXX
   3011  */
   3012     STATIC int
   3013 _bcm_hx5_cosq_sched_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   3014         int mode, int weight)
   3015 {
   3016     soc_hx5_sched_mode_e sched_mode;
   3017     _bcm_hx5_cosq_node_t *node = NULL;
   3018     bcm_port_t local_port;
   3019     int lwts = 1, child_index=0, lvl = SOC_HX5_NODE_LVL_L2, mc = 0;
   3020 
   3021     if (cosq < 0) {
   3022         if (cosq == -1) {
   3023             /* caller needs to resolve the wild card value (-1) */
   3024             return BCM_E_INTERNAL;
   3025         } else {
   3026             return BCM_E_PARAM;
   3027         }
   3028     }
   3029 
   3030     if ((weight < 0) || (weight > 127)) {
   3031         return BCM_E_PARAM;
   3032     }
   3033 
   3034     switch(mode) {
   3035         case BCM_COSQ_STRICT:
   3036             sched_mode = SOC_HX5_SCHED_MODE_STRICT;
   3037             lwts = 0;
   3038             break;
   3039         case BCM_COSQ_ROUND_ROBIN:
   3040             sched_mode = SOC_HX5_SCHED_MODE_WRR;
   3041             lwts = 1;
   3042             break;
   3043         case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   3044             sched_mode = SOC_HX5_SCHED_MODE_WRR;
   3045             lwts = weight;
   3046             break;
   3047         case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   3048             sched_mode = SOC_HX5_SCHED_MODE_WERR;
   3049             lwts = weight;
   3050             break;
   3051         default:
   3052             return BCM_E_PARAM;
   3053     }
   3054 
   3055     /* Weight = 0 corresponds to Strict Mode */
   3056     if (lwts == 0) {
   3057         sched_mode = SOC_HX5_SCHED_MODE_STRICT;
   3058     }
   3059 
   3060     if(BCM_GPORT_IS_SET(gport)) {
   3061         BCM_IF_ERROR_RETURN
   3062             (_bcm_hx5_cosq_node_get(unit, gport, NULL, &local_port, NULL,
   3063                                     &node));
   3064         lvl = node->level;
   3065     } else {
   3066         BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_localport_resolve(unit, gport,
   3067                     &local_port));
   3068 
   3069     }
   3070 
   3071     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   3072             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   3073         mc = BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1 : 0;
   3074     } else if (IS_CPU_PORT(unit, local_port)) {
   3075         mc = 1;
   3076         lvl = SOC_HX5_NODE_LVL_L3;
   3077     }
   3078 
   3079     child_index = cosq;
   3080     BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_sched_mode_setget(unit, local_port, lvl,
   3081                 child_index, &sched_mode, &lwts, mc, 1));
   3082 
   3083     return BCM_E_NONE;
   3084 }
   3085 
   3086 
   3087 
   3088 
   3089 
   3090 /*
   3091  * Function:
   3092  *     bcm_hx5_cosq_gport_sched_set
   3093  * Purpose:
   3094  *     Set up class-of-service policy and corresponding weights
   3095  * Parameters:
   3096  *     unit     - (IN) unit number
   3097  *     gport    - (IN) GPORT identifier
   3098  *     cosq     - (IN) COS queue to get
   3099  *     mode     - (IN) Scheduling mode (BCM_COSQ_xxx)
   3100  *     weight   - (IN) Weight for COS queue.
   3101  * Returns:
   3102  *     BCM_E_XXX
   3103  */
   3104 int
   3105 bcm_hx5_cosq_gport_sched_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   3106         int mode, int weight)
   3107 {
   3108     soc_info_t *si = &SOC_INFO(unit);
   3109     int local_port = -1;
   3110 
   3111     if (BCM_GPORT_IS_SET(gport)) {
   3112         if (BCM_GPORT_IS_SCHEDULER(gport) ||
   3113                 BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   3114                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   3115 
   3116             BCM_IF_ERROR_RETURN
   3117                 (_bcm_hx5_cosq_node_hw_index_get(unit, gport, &cosq));
   3118 
   3119             BCM_IF_ERROR_RETURN
   3120                 (_bcm_hx5_cosq_sched_set(unit, gport, cosq, mode, weight));
   3121             return BCM_E_NONE;
   3122 
   3123         } else {
   3124             BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_localport_resolve(unit, gport,
   3125                         &local_port));
   3126 
   3127             if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) {
   3128                 return BCM_E_PARAM;
   3129             }
   3130 
   3131             BCM_IF_ERROR_RETURN
   3132                 (_bcm_hx5_cosq_sched_set(unit, local_port, cosq, mode, weight));
   3133             return BCM_E_NONE;
   3134         }
   3135     } else {
   3136         return BCM_E_PORT;
   3137     }
   3138 
   3139     return BCM_E_NOT_FOUND;
   3140 }
   3141 
   3142 /*
   3143  * Function:
   3144  *     bcm_hx5_cosq_port_sched_set
   3145  * Purpose:
   3146  *     Set up class-of-service policy and corresponding weights and delay
   3147  * Parameters:
   3148  *     unit     - (IN) unit number
   3149  *     pbm      - (IN) port bitmap
   3150  *     mode     - (IN) Scheduling mode (BCM_COSQ_xxx)
   3151  *     weight   - (IN) Weight for each COS queue.
   3152  *     delay    - This parameter is not used
   3153  * Returns:
   3154  *     BCM_E_XXX
   3155  */
   3156 int
   3157 bcm_hx5_cosq_port_sched_set(int unit, bcm_pbmp_t pbm, int mode, const int
   3158         *weights, int delay)
   3159 {
   3160     bcm_port_t port; 
   3161     int num_weights, i = 0;
   3162     int phy_port, mmu_port;
   3163 
   3164     soc_info_t *si = &SOC_INFO(unit);
   3165 
   3166     BCM_PBMP_ITER(pbm, port) {
   3167         num_weights = _BCM_HX5_NUM_COS(unit); 
   3168         phy_port = si->port_l2p_mapping[port];
   3169         mmu_port = si->port_p2m_mapping[phy_port];
   3170         for (i = 0; i < num_weights; i++) {
   3171             BCM_IF_ERROR_RETURN
   3172                 (_bcm_hx5_cosq_sched_set(unit, port, i, mode, weights[i]));
   3173 
   3174             if(!IS_CPU_PORT(unit, port)) {
   3175                 BCM_IF_ERROR_RETURN
   3176                     (_bcm_hx5_cosq_sched_set(unit, port, i + 8, mode, weights[i]));
   3177 
   3178                 if (_HX5_IS_ST_PORT(unit, mmu_port)) {
   3179                     BCM_IF_ERROR_RETURN
   3180                         (_bcm_hx5_cosq_sched_set(unit, port, i + 16, mode, weights[i]));
   3181                 }
   3182             }
   3183         }
   3184     }
   3185 
   3186     return BCM_E_NONE;
   3187 }
   3188                        
   3189 
   3190 /*
   3191  * Function:
   3192  *      _bcm_hx5_cosq_sched_config_port
   3193  * Purpose:
   3194  *      Set scheduler Configuration for the specified port
   3195  * Parameters:
   3196  *      unit        - (IN) unit number.
   3197  *      port        - (IN) port number.
   3198  * Returns:
   3199  *     BCM_E_XXX
   3200  */
   3201 STATIC int
   3202 _bcm_hx5_cosq_sched_config_port(int unit, int port, int mode, int weight)
   3203 {
   3204     _bcm_hx5_cosq_port_info_t *port_info = NULL;
   3205     _bcm_hx5_cosq_st_port_info_t *stport_info = NULL;
   3206     int phy_port, mmu_port, i, index;
   3207 
   3208     soc_info_t *si = &SOC_INFO(unit);
   3209     phy_port = si->port_l2p_mapping[port];
   3210     mmu_port = si->port_p2m_mapping[phy_port];
   3211     _HX5_PORT_INDEX_GET(unit, mmu_port, index);
   3212 
   3213     if (_HX5_IS_ST_PORT(unit, mmu_port)) {
   3214         stport_info = &_bcm_hx5_cosq_st_port_info[unit][index];
   3215 
   3216         for (i = 0; i < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; i++) {
   3217             BCM_IF_ERROR_RETURN
   3218                 (bcm_hx5_cosq_gport_sched_set(unit, stport_info->sched[i].gport,
   3219                                               -1, mode, weight));
   3220         }
   3221         for (i = 0; i < SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; i++) {
   3222             BCM_IF_ERROR_RETURN
   3223                 (bcm_hx5_cosq_gport_sched_set(unit, stport_info->ucast[i].gport,
   3224                                               -1, mode, weight));
   3225         }
   3226         for (i = 0; i < SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; i++) {
   3227             BCM_IF_ERROR_RETURN
   3228                 (bcm_hx5_cosq_gport_sched_set(unit, stport_info->mcast[i].gport,
   3229                                               -1, mode, weight));
   3230         }
   3231     } else {
   3232         port_info = &_bcm_hx5_cosq_port_info[unit][index];
   3233 
   3234         for (i = 0; i < SOC_HX5_NUM_SCHEDULER_PER_PORT; i++) {
   3235             BCM_IF_ERROR_RETURN
   3236                 (bcm_hx5_cosq_gport_sched_set(unit, port_info->sched[i].gport,
   3237                                               -1, mode, weight));
   3238         }
   3239         for (i = 0; i < SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; i++) {
   3240             BCM_IF_ERROR_RETURN
   3241                 (bcm_hx5_cosq_gport_sched_set(unit, port_info->ucast[i].gport,
   3242                                               -1, mode, weight));
   3243         }
   3244         for (i = 0; i < SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; i++) {
   3245             BCM_IF_ERROR_RETURN
   3246                 (bcm_hx5_cosq_gport_sched_set(unit, port_info->mcast[i].gport,
   3247                                               -1, mode, weight));
   3248         }
   3249     }
   3250 
   3251     return BCM_E_NONE;
   3252 }
   3253 
   3254 /*
   3255  * Function:
   3256  *      _bcm_hx5_cosq_sched_default_config
   3257  * Purpose:
   3258  *      Set Default Scheduler Configuration for all the ports
   3259  * Parameters:
   3260  *      unit        - (IN) unit number.
   3261  * Returns:
   3262  *     BCM_E_XXX
   3263  */
   3264 STATIC int
   3265 _bcm_hx5_cosq_sched_default_config(int unit)
   3266 {
   3267     _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
   3268     bcm_port_t port;
   3269     int default_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN, default_weight = 1;
   3270     int i;
   3271 
   3272     port = 0;
   3273     cpu_port_info = &_bcm_hx5_cosq_cpu_port_info[unit][port];
   3274     for (i = 0; i < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; i++) {
   3275         BCM_IF_ERROR_RETURN
   3276             (bcm_hx5_cosq_gport_sched_set(unit, cpu_port_info->sched[i].gport,
   3277                                           -1, default_mode, default_weight));
   3278     }
   3279     for (i = 0; i < SOC_HX5_NUM_CPU_QUEUES; i++) {
   3280         BCM_IF_ERROR_RETURN
   3281             (bcm_hx5_cosq_gport_sched_set(unit, cpu_port_info->mcast[i].gport,
   3282                                           -1, default_mode, default_weight));
   3283     }
   3284 
   3285     PBMP_ALL_ITER(unit, port) {
   3286         if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || IS_FAE_PORT(unit, port)) {
   3287             continue;
   3288         }
   3289         BCM_IF_ERROR_RETURN
   3290             (_bcm_hx5_cosq_sched_config_port(unit, port, default_mode,
   3291                                              default_weight));
   3292     }
   3293 
   3294     return BCM_E_NONE;
   3295 }
   3296 
   3297 
   3298 
   3299 
   3300 
   3301 STATIC int
   3302 _bcm_hx5_cosq_gport_default_config(int unit)
   3303 {
   3304     BCM_IF_ERROR_RETURN
   3305         (_bcm_hx5_cosq_sched_default_config(unit));
   3306 
   3307     return BCM_E_NONE;
   3308 }
   3309 
   3310 
   3311 /****************
   3312  * BST Support
   3313  */
   3314 
   3315 
   3316 STATIC int
   3317 _bcm_hx5_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq, 
   3318         int *p_pool_start, int *p_pool_end)
   3319 {
   3320     int local_port;
   3321     int pool; 
   3322 
   3323     if (cosq == BCM_COS_INVALID) {
   3324         if (p_pool_start && p_pool_end) {
   3325             *p_pool_start = 0;
   3326             *p_pool_end = 3;
   3327             return BCM_E_NONE;
   3328         } else {
   3329             return BCM_E_PARAM;
   3330         }
   3331     }
   3332 
   3333     BCM_IF_ERROR_RETURN
   3334         (_bcm_hx5_cosq_index_resolve(unit, gport, cosq, 
   3335                                      _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL,
   3336                                      &local_port, &pool, NULL));
   3337 
   3338     if (p_pool_start) {
   3339         *p_pool_start = pool; 
   3340     }
   3341     if (p_pool_end) {
   3342         *p_pool_end = pool; 
   3343     }
   3344     return BCM_E_NONE;
   3345 }
   3346 /*
   3347  * Function:
   3348  *     _bcm_hx5_cosq_index_resolve
   3349  * Purpose:
   3350  *     Find hardware index for the given port/cosq
   3351  * Parameters:
   3352  *     unit       - (IN) unit number
   3353  *     port       - (IN) port number or GPORT identifier
   3354  *     cosq       - (IN) COS queue number
   3355  *     style      - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX)
   3356  *     local_port - (OUT) local port number
   3357  *     index      - (OUT) result index
   3358  *     count      - (OUT) number of index
   3359  * Returns:
   3360  *     BCM_E_XXX
   3361  */
   3362 int
   3363 _bcm_hx5_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   3364                            _bcm_hx5_cosq_index_style_t style,
   3365                            bcm_port_t *local_port, int *index, int *count)
   3366 {
   3367     bcm_port_t resolved_port;
   3368     soc_info_t *si;
   3369     int resolved_index = -1;
   3370     int id, startq, numq = 0;
   3371     int  pipe;
   3372     int uc_base = 0, mc_base = 0, cpu_mc_base; /* Q base number */
   3373     int mmu_port, phy_port;
   3374 
   3375     _bcm_hx5_cosq_node_t *node;
   3376     uint32 entry0[SOC_MAX_MEM_WORDS];
   3377     soc_mem_t mem;
   3378 
   3379     si = &SOC_INFO(unit);
   3380 
   3381     if (cosq < -1) {
   3382         return BCM_E_PARAM;
   3383     } else if (cosq == -1) {
   3384         startq = 0;
   3385         numq = NUM_COS(unit);
   3386     } else {
   3387         startq = cosq;
   3388         numq = 1;
   3389     }
   3390 
   3391 
   3392     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   3393         BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   3394         BCM_GPORT_IS_SCHEDULER(port)) {
   3395         BCM_IF_ERROR_RETURN
   3396             (_bcm_hx5_cosq_node_get(unit, port, NULL, &resolved_port, &id,
   3397                                    &node));
   3398         if (resolved_port < 0) {
   3399             return BCM_E_PORT;
   3400         }
   3401     } else {
   3402         BCM_IF_ERROR_RETURN
   3403             (_bcm_hx5_cosq_localport_resolve(unit, port, &resolved_port));
   3404         if (resolved_port < 0) {
   3405             return BCM_E_PORT;
   3406         }
   3407         node = NULL;
   3408         numq = (IS_CPU_PORT(unit, resolved_port)) ? NUM_CPU_COSQ(unit) : NUM_COS(unit);
   3409     }
   3410     phy_port = si->port_l2p_mapping[resolved_port];
   3411     mmu_port = si->port_p2m_mapping[phy_port];
   3412     mc_base = si->port_cosq_base[resolved_port];
   3413     uc_base = si->port_uc_cosq_base[resolved_port];
   3414 
   3415     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, resolved_port, &pipe));
   3416 
   3417     switch (style) {
   3418         case _BCM_HX5_COSQ_INDEX_STYLE_WRED_DEVICE:
   3419             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3420                 return BCM_E_PARAM;
   3421             }
   3422             if ((port == -1) || (cosq == -1)) {
   3423                 numq = _HX5_MMU_NUM_POOL; /* 4 Global Service Pools */
   3424                 resolved_index = _HX5_WRED_PER_PIPE_GLOBAL_SP_BASE;
   3425             } else {
   3426                 BCM_IF_ERROR_RETURN
   3427                     (_bcm_hx5_cosq_egress_sp_get(unit, port, cosq,
   3428                                                 &resolved_index,
   3429                                                 NULL));
   3430                 numq = 1;
   3431                 resolved_index += _HX5_WRED_PER_PIPE_GLOBAL_SP_BASE;
   3432             }
   3433             break;
   3434 
   3435         case _BCM_HX5_COSQ_INDEX_STYLE_WRED_PORT:
   3436             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3437                 return BCM_E_PARAM;
   3438             }
   3439             resolved_index = 0;
   3440             if (cosq != -1) {
   3441                 BCM_IF_ERROR_RETURN
   3442                     (_bcm_hx5_cosq_egress_sp_get(unit, port, cosq,
   3443                                                 &resolved_index,
   3444                                                 NULL));
   3445             }
   3446             resolved_index += _HX5_WRED_PER_PIPE_PORT_SP_BASE +
   3447                               (mmu_port * 4);
   3448             numq = (cosq == -1) ? 4: 1;
   3449             break;
   3450 
   3451         case _BCM_HX5_COSQ_INDEX_STYLE_WRED_QUEUE:
   3452             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3453                 return BCM_E_PARAM;
   3454             }
   3455             if (node) {
   3456                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   3457                      resolved_index = node->hw_index;
   3458                 } else {
   3459                     return BCM_E_PARAM;
   3460                 }
   3461             } else {
   3462                 resolved_index = uc_base;
   3463                 if (cosq != -1) {
   3464                     numq = si->port_num_cosq[resolved_port];
   3465                     if (cosq >= numq) {
   3466                         return BCM_E_PARAM;
   3467                     }
   3468                     resolved_index += cosq;
   3469                 }
   3470                 numq = (cosq == -1) ? NUM_COS(unit): 1;
   3471             }
   3472             break;
   3473 
   3474         case _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL:
   3475             if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) {
   3476                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   3477                     /* regular unicast queue */
   3478                     resolved_index = node->hw_index ;
   3479                     mem = MMU_THDU_Q_TO_QGRP_MAPm;
   3480                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3481                     resolved_index = node->hw_index ;
   3482                     mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   3483                 } else { /* scheduler */
   3484                     return BCM_E_PARAM;
   3485                 }
   3486             } else { /* node == NULL */
   3487                 /* PGA check this else  part for uc index based on port type 
   3488                    icaluclation */
   3489                 numq = si->port_num_cosq[resolved_port];
   3490                 if (startq >= numq) {
   3491                     return BCM_E_PARAM;
   3492                 }
   3493                 resolved_index = uc_base + startq;
   3494                 mem = MMU_THDU_Q_TO_QGRP_MAPm;
   3495             }
   3496             mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe];
   3497 
   3498             SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index,
   3499                                 entry0));
   3500             resolved_index = soc_mem_field32_get(unit, mem, entry0, Q_SPIDf);
   3501             break;
   3502 
   3503         case _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE:
   3504             /* Return hw_index for given unicast queue gport */
   3505             if (node) {
   3506                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   3507                      resolved_index = node->hw_index; 
   3508                 } else {
   3509                     return BCM_E_PARAM;
   3510                 }
   3511             } else {
   3512                 numq = si->port_num_cosq[resolved_port];
   3513                 if ((startq >= numq) || (IS_LB_PORT(unit, resolved_port))) {
   3514                     return BCM_E_PARAM;
   3515                 }
   3516                 resolved_index = uc_base + startq;
   3517             }
   3518             break;
   3519         case _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE:
   3520             /* Return hw_index for given multicast queue gport */
   3521             if (node) {
   3522                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3523                          resolved_index = node->hw_index; 
   3524                 } else {
   3525                     return BCM_E_PARAM;
   3526                 }
   3527             } else {
   3528                 if (startq >= numq) {
   3529                     return BCM_E_PARAM;
   3530                 }
   3531                 resolved_index = mc_base + startq;
   3532             }
   3533             break;
   3534         case _BCM_HX5_COSQ_INDEX_STYLE_COS:
   3535             if (node) {
   3536                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   3537                     resolved_index = node->hw_index;
   3538                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3539                     if (IS_CPU_PORT(unit, resolved_port)) {
   3540                         cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   3541                         resolved_index = (node->hw_index - cpu_mc_base) %
   3542                             NUM_CPU_COSQ(unit);
   3543                     } else {
   3544                         resolved_index = node->hw_index;
   3545                     }
   3546                 } else {
   3547                     resolved_index = node->hw_index;
   3548                 }
   3549             } else {
   3550                 resolved_index = startq;
   3551             }
   3552             break;
   3553         default:
   3554             return BCM_E_PARAM;
   3555     }
   3556 
   3557     if (index) {
   3558         *index = resolved_index;
   3559     }
   3560     if (local_port) {
   3561         *local_port = resolved_port;
   3562     }
   3563     if (count) {
   3564         *count = (cosq == -1) ? numq : 1;
   3565     }
   3566 
   3567     return BCM_E_NONE;
   3568 }
   3569 
   3570 STATIC int
   3571 _bcm_hx5_cosq_bst_map_resource_to_gport_cos(int unit,
   3572         bcm_bst_stat_id_t bid, int port, int index, bcm_gport_t *gport,
   3573         bcm_cos_t *cosq)
   3574 {
   3575     soc_info_t *si = &SOC_INFO(unit);
   3576     _bcm_bst_resource_info_t *pres = NULL;
   3577     int phy_port = 0;
   3578     int mmu_port = 0;
   3579     int stats_per_inst = 1;
   3580     int stats_per_pipe = 1;
   3581 
   3582     if (bid >= bcmBstStatIdMaxCount) {
   3583         LOG_INFO(BSL_LS_BCM_COSQ,
   3584                 (BSL_META_U(unit,
   3585                             "_bcm_th_cosq_bst_map_resource_to_gport_cos: unit=%d bid=0x%x\n"),
   3586                  unit, bid));
   3587         return BCM_E_NONE;
   3588     }
   3589 
   3590     pres = _BCM_BST_RESOURCE(unit, bid);
   3591     stats_per_inst = (pres->num_stat_pp) / (pres->num_instance);
   3592     index %= stats_per_inst;
   3593     if (pres->flags & _BCM_BST_CMN_RES_F_PIPED) {
   3594         stats_per_pipe = stats_per_inst / NUM_PIPE(unit);
   3595         index %= stats_per_pipe;
   3596     }
   3597 
   3598     switch (bid) {
   3599         case bcmBstStatIdDevice:
   3600             *gport = -1;
   3601             *cosq = BCM_COS_INVALID;
   3602             break;
   3603 
   3604         case bcmBstStatIdIngPool:
   3605         case bcmBstStatIdEgrPool:
   3606         case bcmBstStatIdEgrMCastPool:
   3607         case bcmBstStatIdRQEPool:
   3608             *gport = -1;
   3609             *cosq = index % _HX5_MMU_NUM_POOL;
   3610             break;
   3611 
   3612         case bcmBstStatIdRQEQueue:
   3613             *gport = -1;
   3614             *cosq = index % _HX5_MMU_NUM_RQE_QUEUES;
   3615             break;
   3616 
   3617         case bcmBstStatIdUCQueueGroup:
   3618             mmu_port = index;
   3619             phy_port = si->port_m2p_mapping[mmu_port];
   3620             *gport = si->port_p2l_mapping[phy_port];
   3621             *cosq =  -1;
   3622             break;
   3623 
   3624         case bcmBstStatIdPortPool:
   3625             mmu_port= index/_HX5_MMU_NUM_POOL;
   3626             phy_port = si->port_m2p_mapping[mmu_port];
   3627             *gport = si->port_p2l_mapping[phy_port];
   3628             *cosq = index % _HX5_MMU_NUM_POOL;
   3629             break;
   3630 
   3631         case bcmBstStatIdPriGroupHeadroom:
   3632         case bcmBstStatIdPriGroupShared:
   3633             mmu_port = index/_HX5_MMU_NUM_PG;
   3634             phy_port = si->port_m2p_mapping[mmu_port];
   3635             *gport = si->port_p2l_mapping[phy_port];
   3636             *cosq = index % _HX5_MMU_NUM_PG;
   3637             break;
   3638 
   3639         case bcmBstStatIdUcast:
   3640         case bcmBstStatIdMcast:
   3641             if (index <  SOC_HX5_DOWNLINK_PORTQ_BASE) {
   3642                mmu_port = index / 26;
   3643             } else {
   3644                mmu_port = ((index - SOC_HX5_DOWNLINK_PORTQ_BASE) / 16) + 16;
   3645             }
   3646             if ((bid == bcmBstStatIdMcast) &&
   3647                     (index >= si->port_cosq_base[CMIC_PORT(unit)])) {
   3648                 *gport = CMIC_PORT(unit);
   3649                 *cosq = index - si->port_cosq_base[CMIC_PORT(unit)];
   3650             } else {
   3651                 phy_port = si->port_m2p_mapping[mmu_port];
   3652                 *gport = si->port_p2l_mapping[phy_port];
   3653                 *cosq = index - si->port_uc_cosq_base[*gport];
   3654             }
   3655             break;
   3656         case bcmBstStatIdEgrPortPoolSharedUcast:
   3657         case bcmBstStatIdEgrPortPoolSharedMcast:
   3658             mmu_port = index/_HX5_MMU_NUM_POOL;
   3659             phy_port = si->port_m2p_mapping[mmu_port];
   3660             *gport = si->port_p2l_mapping[phy_port];
   3661             *cosq = index % _HX5_MMU_NUM_POOL;
   3662             break;
   3663         default:
   3664             break;
   3665     }
   3666 
   3667     return BCM_E_NONE;
   3668 }
   3669 
   3670 
   3671 int
   3672 _bcm_hx5_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *type,
   3673                                int *class)
   3674 {
   3675     switch (sctype) {
   3676         case bcmSwitchPFCClass7Queue:
   3677         case bcmSwitchPFCClass6Queue:
   3678         case bcmSwitchPFCClass5Queue:
   3679         case bcmSwitchPFCClass4Queue:
   3680         case bcmSwitchPFCClass3Queue:
   3681         case bcmSwitchPFCClass2Queue:
   3682         case bcmSwitchPFCClass1Queue:
   3683         case bcmSwitchPFCClass0Queue:
   3684             *type = _BCM_HX5_COSQ_TYPE_UCAST;
   3685             break;
   3686         case bcmSwitchPFCClass7McastQueue:
   3687         case bcmSwitchPFCClass6McastQueue:
   3688         case bcmSwitchPFCClass5McastQueue:
   3689         case bcmSwitchPFCClass4McastQueue:
   3690         case bcmSwitchPFCClass3McastQueue:
   3691         case bcmSwitchPFCClass2McastQueue:
   3692         case bcmSwitchPFCClass1McastQueue:
   3693         case bcmSwitchPFCClass0McastQueue:
   3694             *type = _BCM_HX5_COSQ_TYPE_MCAST;
   3695             break;
   3696         default:
   3697             /* Unsupported Switch Control types should return E_UNAVAIL */
   3698             return BCM_E_UNAVAIL;
   3699     }
   3700 
   3701     switch (sctype) {
   3702         case bcmSwitchPFCClass7Queue:
   3703         case bcmSwitchPFCClass7McastQueue:
   3704             *class = 7;
   3705             break;
   3706         case bcmSwitchPFCClass6Queue:
   3707         case bcmSwitchPFCClass6McastQueue:
   3708             *class = 6;
   3709             break;
   3710         case bcmSwitchPFCClass5Queue:
   3711         case bcmSwitchPFCClass5McastQueue:
   3712             *class = 5;
   3713             break;
   3714         case bcmSwitchPFCClass4Queue:
   3715         case bcmSwitchPFCClass4McastQueue:
   3716             *class = 4;
   3717             break;
   3718         case bcmSwitchPFCClass3Queue:
   3719         case bcmSwitchPFCClass3McastQueue:
   3720             *class = 3;
   3721             break;
   3722         case bcmSwitchPFCClass2Queue:
   3723         case bcmSwitchPFCClass2McastQueue:
   3724             *class = 2;
   3725             break;
   3726         case bcmSwitchPFCClass1Queue:
   3727         case bcmSwitchPFCClass1McastQueue:
   3728             *class = 1;
   3729             break;
   3730         case bcmSwitchPFCClass0Queue:
   3731         case bcmSwitchPFCClass0McastQueue:
   3732             *class = 0;
   3733             break;
   3734         /*
   3735          * COVERITY
   3736          *
   3737          * This default is unreachable but needed for some compiler.
   3738          */
   3739         /* coverity[dead_error_begin] */
   3740         default:
   3741             return BCM_E_INTERNAL;
   3742     }
   3743     return BCM_E_NONE;
   3744 }
   3745 
   3746 
   3747 
   3748 STATIC int
   3749 _bcm_hx5_cosq_ingress_pg_get(int unit, bcm_gport_t gport, bcm_cos_queue_t pri,
   3750                             int *p_pg_start, int *p_pg_end)
   3751 {
   3752     bcm_port_t local_port;
   3753     uint32  rval,pool;
   3754     soc_reg_t reg = INVALIDr;
   3755     static const soc_reg_t prigroup_reg[] = {
   3756         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   3757     };
   3758     static const soc_field_t prigroup_field[] = {
   3759         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   3760         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   3761         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   3762         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   3763     };
   3764 
   3765     if (pri == BCM_COS_INVALID) {
   3766         *p_pg_start = 0;
   3767         *p_pg_end = 7;
   3768         return BCM_E_NONE;
   3769     }
   3770 
   3771     BCM_IF_ERROR_RETURN
   3772             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   3773 
   3774     if (!SOC_PORT_VALID(unit, local_port)) {
   3775         return BCM_E_PORT;
   3776     }
   3777 
   3778     if (pri >= _HX5_MMU_NUM_INT_PRI) {
   3779         return BCM_E_PARAM;
   3780     }
   3781        /* get PG for port using Port+Cos */
   3782     if (pri < (_HX5_MMU_NUM_INT_PRI / 2)) {
   3783         reg = prigroup_reg[0];
   3784     } else {
   3785         reg = prigroup_reg[1];
   3786     }
   3787 
   3788     SOC_IF_ERROR_RETURN
   3789         (soc_reg32_get(unit, reg, local_port, 0, &rval));
   3790         pool = soc_reg_field_get(unit, reg, rval, prigroup_field[pri]);
   3791 
   3792     if (p_pg_start) {
   3793         *p_pg_start = pool;
   3794     }
   3795 
   3796     if (p_pg_end) {
   3797         *p_pg_end = pool;
   3798     }
   3799 
   3800     return BCM_E_NONE;
   3801 }
   3802 
   3803 
   3804 /*
   3805  * This function is used to get shared pool
   3806  * for given Ingress [Port, Priority]
   3807  */
   3808 STATIC int
   3809 _bcm_hx5_cosq_ingress_sp_get(int unit, bcm_gport_t gport, bcm_cos_t pri,
   3810                             int *p_pool_start, int *p_pool_end)
   3811 {
   3812     int local_port;
   3813     uint32 rval, pool;
   3814     int pri_grp;
   3815     static const soc_field_t prigroup_spid_field[] = {
   3816         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   3817         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   3818     };
   3819 
   3820     if (pri == BCM_COS_INVALID) {
   3821         if (p_pool_start && p_pool_end) {
   3822             *p_pool_start = 0;
   3823             *p_pool_end = 3;
   3824             return BCM_E_NONE;
   3825         } else {
   3826             return BCM_E_PARAM;
   3827         }
   3828     }
   3829 
   3830     if ((pri < 0) || (pri >= _HX5_MMU_NUM_INT_PRI)) {
   3831         /* Error. Input pri > Max Pri_Grp */
   3832         return BCM_E_PARAM;
   3833     }
   3834 
   3835     BCM_IF_ERROR_RETURN
   3836         (_bcm_hx5_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp));
   3837 
   3838     BCM_IF_ERROR_RETURN
   3839             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   3840 
   3841     if (!SOC_PORT_VALID(unit, local_port)) {
   3842         return BCM_E_PORT;
   3843     }
   3844 
   3845     if (pri_grp >= _HX5_MMU_NUM_PG) {
   3846         return BCM_E_PARAM;
   3847     }
   3848 
   3849     SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval));
   3850     pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval,
   3851                              prigroup_spid_field[pri_grp]);
   3852 
   3853     if (p_pool_start) {
   3854         *p_pool_start = pool;
   3855     }
   3856     if (p_pool_end) {
   3857         *p_pool_end = pool;
   3858     }
   3859     return BCM_E_NONE;
   3860 }
   3861 
   3862 /*
   3863  * This function is used to get shared pool
   3864  * for given Ingress [Port, Priority_group]
   3865  */
   3866 STATIC int
   3867 _bcm_hx5_cosq_ingress_sp_get_by_pg(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp,
   3868                             int *p_pool_start, int *p_pool_end)
   3869 {
   3870     int local_port;
   3871     uint32 rval, pool;
   3872     static const soc_field_t prigroup_spid_field[] = {
   3873         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   3874         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   3875     };
   3876 
   3877     if (pri_grp == BCM_COS_INVALID) {
   3878         if (p_pool_start && p_pool_end) {
   3879             *p_pool_start = 0;
   3880             *p_pool_end = 3;
   3881             return BCM_E_NONE;
   3882         } else {
   3883             return BCM_E_PARAM;
   3884         }
   3885     }
   3886 
   3887     BCM_IF_ERROR_RETURN
   3888             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   3889 
   3890     if (!SOC_PORT_VALID(unit, local_port)) {
   3891         return BCM_E_PORT;
   3892     }
   3893 
   3894     if (pri_grp >= _HX5_MMU_NUM_PG) {
   3895         return BCM_E_PARAM;
   3896     }
   3897 
   3898     SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval));
   3899     pool = soc_reg_field_get(unit, THDI_PORT_PG_SPIDr, rval,
   3900                              prigroup_spid_field[pri_grp]);
   3901 
   3902     if (p_pool_start) {
   3903         *p_pool_start = pool;
   3904     }
   3905     if (p_pool_end) {
   3906         *p_pool_end = pool;
   3907     }
   3908     return BCM_E_NONE;
   3909 }
   3910 
   3911 /*
   3912  * This function is used to get headroom pool
   3913  * for given Ingress [Port, Priority]
   3914  */
   3915 STATIC int
   3916 _bcm_hx5_cosq_ingress_hdrm_pool_get(int unit, bcm_gport_t gport,
   3917                                    bcm_cos_t pri,
   3918                                    int *p_hdrm_pool_start,
   3919                                    int *p_hdrm_pool_end)
   3920 {
   3921     int local_port;
   3922     uint32 rval, hdrm_pool;
   3923     int pri_grp;
   3924     static const soc_field_t prigroup_hpid_field[] = {
   3925         PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf,
   3926         PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf
   3927     };
   3928 
   3929     if (pri == BCM_COS_INVALID) {
   3930         if (p_hdrm_pool_start && p_hdrm_pool_end) {
   3931             *p_hdrm_pool_start = 0;
   3932             *p_hdrm_pool_end = 3;
   3933             return BCM_E_NONE;
   3934         } else {
   3935             return BCM_E_PARAM;
   3936         }
   3937     }
   3938 
   3939     if ((pri < 0) || (pri >= _HX5_MMU_NUM_INT_PRI)) {
   3940         /* Error. Input pri > Max Pri_Grp */
   3941         return BCM_E_PARAM;
   3942     }
   3943 
   3944     BCM_IF_ERROR_RETURN
   3945         (_bcm_hx5_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp));
   3946 
   3947     BCM_IF_ERROR_RETURN
   3948             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   3949 
   3950     if (!SOC_PORT_VALID(unit, local_port)) {
   3951         return BCM_E_PORT;
   3952     }
   3953 
   3954     if (pri_grp >= _HX5_MMU_NUM_PG) {
   3955         return BCM_E_PARAM;
   3956     }
   3957 
   3958     SOC_IF_ERROR_RETURN(READ_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, &rval));
   3959     hdrm_pool = soc_reg_field_get(unit, THDI_HDRM_PORT_PG_HPIDr, rval,
   3960                                   prigroup_hpid_field[pri_grp]);
   3961 
   3962     if (p_hdrm_pool_start) {
   3963         *p_hdrm_pool_start = hdrm_pool;
   3964     }
   3965     if (p_hdrm_pool_end) {
   3966         *p_hdrm_pool_end = hdrm_pool;
   3967     }
   3968 
   3969     return BCM_E_NONE;
   3970 }
   3971 
   3972 
   3973 /*
   3974  * This function is used to set headroom pool
   3975  * or shared pool for given Ingress [Port, Priority]
   3976  */
   3977 STATIC int
   3978 _bcm_hx5_cosq_ing_pool_set(int unit, bcm_gport_t gport, bcm_cos_t pri,
   3979                           bcm_cosq_control_t type, int arg)
   3980 {
   3981     int local_port;
   3982     uint32 rval;
   3983     int pri_grp;
   3984     static const soc_field_t prigroup_spid_field[] = {
   3985         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   3986         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   3987     };
   3988     static const soc_field_t prigroup_hpid_field[] = {
   3989         PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf,
   3990         PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf
   3991     };
   3992     pri = pri % 8;
   3993 
   3994     if((arg < 0) || (arg >= _HX5_MMU_NUM_POOL)) {
   3995             return BCM_E_PARAM;
   3996     }
   3997 
   3998     if ((pri < 0) || (pri >= _HX5_MMU_NUM_INT_PRI)) {
   3999         /* Error. Input pri > Max Pri_Grp */
   4000         return BCM_E_PARAM;
   4001     }
   4002 
   4003     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4004         BCM_GPORT_IS_SCHEDULER(gport) ||
   4005         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4006         return BCM_E_PARAM;
   4007     }
   4008 
   4009     BCM_IF_ERROR_RETURN
   4010             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   4011 
   4012     if (!SOC_PORT_VALID(unit, local_port)) {
   4013         return BCM_E_PORT;
   4014     }
   4015 
   4016     BCM_IF_ERROR_RETURN
   4017         (_bcm_hx5_cosq_ingress_pg_get(unit, gport, pri, &pri_grp, &pri_grp));
   4018 
   4019     /* coverity fix : pri_grp can take value from 0 to 7 */
   4020     if ((pri_grp < 0) || (pri_grp >= _HX5_MMU_NUM_PG)) {
   4021         return BCM_E_PARAM;
   4022     }
   4023 
   4024     if (type == bcmCosqControlIngressPool) {
   4025         SOC_IF_ERROR_RETURN(READ_THDI_PORT_PG_SPIDr(unit, local_port, &rval));
   4026         soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval,
   4027                           prigroup_spid_field[pri_grp],arg);
   4028         BCM_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, local_port, rval));
   4029     } else if (type == bcmCosqControlIngressHeadroomPool) {
   4030         SOC_IF_ERROR_RETURN(READ_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, &rval));
   4031         soc_reg_field_set(unit, THDI_HDRM_PORT_PG_HPIDr, &rval,
   4032                           prigroup_hpid_field[pri_grp], arg);
   4033         BCM_IF_ERROR_RETURN(WRITE_THDI_HDRM_PORT_PG_HPIDr(unit, local_port, rval));
   4034     } else {
   4035         return BCM_E_PARAM;
   4036     }
   4037     return BCM_E_NONE;
   4038 }
   4039 
   4040 STATIC int
   4041 _bcm_hx5_cosq_ing_pool_get(int unit, bcm_gport_t gport,
   4042                           bcm_cos_t pri,
   4043                           bcm_cosq_control_t type, int *arg)
   4044 {
   4045     int pool_start_idx = 0, pool_end_idx = 0;
   4046     pri = pri % 8;
   4047 
   4048     if (arg == NULL) {
   4049         return BCM_E_PARAM;
   4050     }
   4051 
   4052     if ((pri < 0) || (pri >= _HX5_MMU_NUM_INT_PRI)) {
   4053         /* Error. Input pri > Max Pri_Grp */
   4054         return BCM_E_PARAM;
   4055     }
   4056 
   4057     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4058         BCM_GPORT_IS_SCHEDULER(gport) ||
   4059         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4060         return BCM_E_PARAM;
   4061     }
   4062 
   4063     if (type == bcmCosqControlIngressPool) {
   4064         BCM_IF_ERROR_RETURN(
   4065             _bcm_hx5_cosq_ingress_sp_get(unit, gport, pri,
   4066                                         &pool_start_idx,
   4067                                         &pool_end_idx));
   4068     } else if (type == bcmCosqControlIngressHeadroomPool) {
   4069         BCM_IF_ERROR_RETURN(
   4070             _bcm_hx5_cosq_ingress_hdrm_pool_get(unit, gport, pri,
   4071                                                &pool_start_idx,
   4072                                                &pool_end_idx));
   4073     } else {
   4074         return BCM_E_PARAM;
   4075     }
   4076     *arg = pool_start_idx;
   4077     return BCM_E_NONE;
   4078 }
   4079 
   4080 
   4081 STATIC _bcm_bst_cb_ret_t
   4082 _bcm_hx5_bst_index_resolve(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   4083                           bcm_bst_stat_id_t bid, int *pipe, int *start_hw_index,
   4084                           int *end_hw_index, int *rcb_data, void **cb_data, int *bcm_rv)
   4085 {
   4086     int phy_port, mmu_port, local_port;
   4087     int mmu_port_base = 0;
   4088     int pool_idx = 0;
   4089     uint32 rval = 0;
   4090     _bcm_hx5_cosq_node_t *node = NULL;
   4091     soc_info_t *si;
   4092 
   4093     *bcm_rv = _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port);
   4094 
   4095     if (BCM_E_NONE != (*bcm_rv)) {
   4096         goto error;
   4097     }
   4098 
   4099     si = &SOC_INFO(unit);
   4100     phy_port = si->port_l2p_mapping[local_port];
   4101     mmu_port = si->port_p2m_mapping[phy_port];
   4102 
   4103     *pipe = mmu_port / SOC_HX5_MMU_PORT_STRIDE;
   4104 
   4105     if (bid == bcmBstStatIdDevice) {
   4106         *start_hw_index = *end_hw_index = 0;
   4107         *bcm_rv = BCM_E_NONE;
   4108         return _BCM_BST_RV_OK;
   4109     }
   4110 
   4111     if ((bid == bcmBstStatIdEgrPool) || (bid == bcmBstStatIdEgrMCastPool)) {
   4112         if(_bcm_hx5_cosq_egress_sp_get(unit, gport, cosq, start_hw_index,
   4113                     end_hw_index)) {
   4114             goto error;
   4115         }
   4116         return _BCM_BST_RV_OK;
   4117     } else if (bid == bcmBstStatIdHeadroomPool) {
   4118         cosq = cosq % 8;
   4119         /* ingress headroom pool */
   4120         if (_bcm_hx5_cosq_ingress_hdrm_pool_get(unit, gport, cosq,
   4121                     start_hw_index, end_hw_index)) {
   4122             goto error;
   4123         }
   4124         return _BCM_BST_RV_OK;
   4125     } else if (bid == bcmBstStatIdIngPool) {
   4126         cosq = cosq % 8;
   4127         /* ingress pool */
   4128         if (_bcm_hx5_cosq_ingress_sp_get(unit, gport, cosq,
   4129                     start_hw_index, end_hw_index)) {
   4130             goto error;
   4131         }
   4132         return _BCM_BST_RV_OK;
   4133     } else if (bid == bcmBstStatIdRQEPool) {
   4134         /* RQE pool */
   4135         if (cosq == BCM_COS_INVALID) {
   4136             *start_hw_index = 0;
   4137             *end_hw_index = _HX5_MMU_NUM_POOL - 1;
   4138         } else if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_POOL)) {
   4139             return BCM_E_PARAM;
   4140         } else {
   4141             SOC_IF_ERROR_RETURN
   4142                 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, cosq, &rval));
   4143 
   4144             pool_idx = soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval,
   4145                     SPIDf);
   4146             *start_hw_index = *end_hw_index = pool_idx;
   4147         }
   4148         return _BCM_BST_RV_OK;
   4149     } else if (bid == bcmBstStatIdRQEQueue) {
   4150         /* RQE queue */
   4151         if (cosq == BCM_COS_INVALID) {
   4152             *start_hw_index = 0;
   4153             *end_hw_index = _HX5_MMU_NUM_RQE_QUEUES - 1;
   4154         } else if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_RQE_QUEUES)) {
   4155             return BCM_E_PARAM;
   4156         } else {
   4157             *start_hw_index = *end_hw_index = cosq;
   4158         }
   4159         return _BCM_BST_RV_OK;
   4160     } else if (bid == bcmBstStatIdUCQueueGroup) {
   4161         /* unicast queue group */
   4162         mmu_port_base = SOC_HX5_MMU_PORT_STRIDE * (*pipe);
   4163         *start_hw_index = *end_hw_index = mmu_port - mmu_port_base;
   4164         return _BCM_BST_RV_OK;
   4165     }
   4166 
   4167 
   4168     if (bid == bcmBstStatIdPortPool) {
   4169         cosq = cosq % 8;
   4170         /* ingress pool */
   4171         if (_bcm_hx5_cosq_ingress_sp_get(unit, gport, cosq,
   4172                                         start_hw_index, end_hw_index)) {
   4173             goto error;
   4174         }
   4175         *start_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 4) +
   4176                           *start_hw_index;
   4177         *end_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 4) +
   4178                         *end_hw_index;
   4179     } else if ((bid == bcmBstStatIdPriGroupShared) ||
   4180                (bid == bcmBstStatIdPriGroupHeadroom)) {
   4181         cosq = cosq % 8;
   4182         /* ingress PG */
   4183         if (_bcm_hx5_cosq_ingress_pg_get(unit, gport, cosq,
   4184                                         start_hw_index, end_hw_index)) {
   4185             goto error;
   4186         }
   4187         *start_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 8) +
   4188                           *start_hw_index;
   4189         *end_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 8) +
   4190                         *end_hw_index;
   4191     } else if (bid == bcmBstStatIdEgrPortPoolSharedUcast ||
   4192                bid == bcmBstStatIdEgrPortPoolSharedMcast) {
   4193         /* egress pool */
   4194         if (_bcm_hx5_cosq_egress_sp_get(unit, gport, cosq,
   4195                                        start_hw_index, end_hw_index)) {
   4196             goto error;
   4197         }
   4198         *start_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 4) +
   4199                           *start_hw_index;
   4200         *end_hw_index = ((mmu_port & SOC_HX5_MMU_PORT_STRIDE) * 4) +
   4201                         *end_hw_index;
   4202     } else {
   4203         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4204             if (bid != bcmBstStatIdUcast) {
   4205                 goto error;
   4206             }
   4207             BCM_IF_ERROR_RETURN
   4208                 (_bcm_hx5_cosq_node_get(unit, gport, NULL,
   4209                                        &local_port, NULL, &node));
   4210             if (!node) {
   4211                 goto error;
   4212             }
   4213             *start_hw_index =  node->hw_index; 
   4214             *end_hw_index = *start_hw_index;
   4215         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4216             if (bid != bcmBstStatIdMcast) {
   4217                 goto error;
   4218             }
   4219             BCM_IF_ERROR_RETURN
   4220                 (_bcm_hx5_cosq_node_get(unit, gport, NULL,
   4221                                        &local_port, NULL, &node));
   4222             if (!node) {
   4223                 goto error;
   4224             }
   4225             if (IS_CPU_PORT(unit, local_port)) {
   4226                 *start_hw_index = si->port_cosq_base[CMIC_PORT(unit)] + cosq;
   4227             } else {
   4228                 *start_hw_index =  node->hw_index; 
   4229             }
   4230             *end_hw_index = *start_hw_index;
   4231         } else {
   4232             if (cosq < 0) {
   4233                 if (bid == bcmBstStatIdUcast) {
   4234                     if (IS_LB_PORT(unit, local_port)) {
   4235                         goto error;
   4236                     }
   4237                     *start_hw_index = si->port_uc_cosq_base[local_port]; 
   4238                     *end_hw_index = *start_hw_index +
   4239                                     si->port_num_uc_cosq[local_port] - 1;
   4240                 } else {
   4241                     if (IS_CPU_PORT(unit, local_port)) {
   4242                         *start_hw_index = si->port_cosq_base[CMIC_PORT(unit)];
   4243                         *end_hw_index = *start_hw_index +
   4244                                          SOC_HX5_NUM_CPU_QUEUES - 1;
   4245                     } else {
   4246                         *start_hw_index =  si->port_cosq_base[local_port]; 
   4247                         *end_hw_index = *start_hw_index +
   4248                             si->port_num_cosq[local_port] - 1;
   4249                     }
   4250                 }
   4251             } else {
   4252                 if (bid == bcmBstStatIdUcast) {
   4253                     if (IS_LB_PORT(unit, local_port)) {
   4254                         goto error;
   4255                     }
   4256                     *start_hw_index = si->port_num_uc_cosq[local_port] + cosq; 
   4257                     *end_hw_index = *start_hw_index;
   4258                 } else {
   4259                     if (IS_CPU_PORT(unit, local_port)) {
   4260                         *start_hw_index = si->port_cosq_base[CMIC_PORT(unit)] + cosq;
   4261                     } else {
   4262                         *start_hw_index = si->port_num_cosq[local_port] + cosq; 
   4263                     }
   4264                     *end_hw_index = *start_hw_index;
   4265                 }
   4266             }
   4267         }
   4268     }
   4269 
   4270     *bcm_rv = BCM_E_NONE;
   4271     return _BCM_BST_RV_OK;
   4272 
   4273 error:
   4274     *bcm_rv = BCM_E_PARAM;
   4275     return _BCM_BST_RV_ERROR;
   4276 }
   4277 
   4278 /*
   4279  * Function:
   4280  *     _bcm_hx5_cosq_bucket_get
   4281  * Purpose:
   4282  *     Get COS queue bandwidth control bucket setting
   4283  * Parameters:
   4284  *     unit          - (IN) unit number
   4285  *     gport         - (IN) port number or GPORT identifier
   4286  *     cosq          - (IN) COS queue number
   4287  *     min_quantum   - (OUT) kbps or packet/second
   4288  *     max_quantum   - (OUT) kbps or packet/second
   4289  *     burst_quantum - (OUT) kbps or packet/second
   4290  *     flags         - (IN) BCM_COSQ_BW_XXX
   4291  * Returns:
   4292  *     BCM_E_XXX
   4293  * Notes:
   4294  *     If port is any form of local port, cosq is the hardware queue index.
   4295  */
   4296 STATIC int
   4297 _bcm_hx5_cosq_bucket_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
   4298                         uint32 *min_quantum, uint32 *max_quantum,
   4299                         uint32 *kbits_burst_min, uint32 *kbits_burst_max,
   4300                         uint32 *flags)
   4301 {
   4302     _bcm_hx5_cosq_node_t *node = NULL;
   4303     bcm_port_t local_port;
   4304     uint32 rval;
   4305     uint32 refresh_rate, bucketsize, granularity, meter_flags;
   4306     int pipe = -1, phy_port, mmu_port, index = 0;
   4307 
   4308     soc_mem_t config_mem = INVALIDm;
   4309     uint32 entry[SOC_MAX_MEM_WORDS];
   4310     soc_info_t *si;
   4311 
   4312     if (cosq < 0) {
   4313         if (cosq == -1) {
   4314             /* caller needs to resolve the wild card value (-1) */
   4315             return BCM_E_INTERNAL;
   4316         } else { /* reject all other negative value */
   4317             return BCM_E_PARAM;
   4318         }
   4319     }
   4320 
   4321     BCM_IF_ERROR_RETURN
   4322         (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   4323 
   4324     si = &SOC_INFO(unit);
   4325     phy_port = si->port_l2p_mapping[local_port];
   4326     mmu_port = si->port_p2m_mapping[phy_port];
   4327     pipe = si->port_pipe[local_port];
   4328 
   4329     if (BCM_GPORT_IS_SET(gport) &&
   4330         ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   4331           BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4332           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) { 
   4333 
   4334         BCM_IF_ERROR_RETURN
   4335             (_bcm_hx5_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   4336     }
   4337 
   4338     if (node) {
   4339         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   4340             if (node->level == SOC_HX5_NODE_LVL_L0) {
   4341                 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L0_MEMm)[pipe];
   4342                 index = node->hw_index;
   4343             } else if(node->level == SOC_HX5_NODE_LVL_L1) {
   4344                 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L1_MEMm)[pipe];
   4345                 index = node->hw_index;
   4346             } else if(node->level == SOC_HX5_NODE_LVL_L2) {
   4347                 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L2_MEMm)[pipe];
   4348                 index = node->hw_index;
   4349             } else {
   4350                 return BCM_E_PARAM;
   4351             }
   4352         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4353                    BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4354             config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe];
   4355 
   4356             if (IS_CPU_PORT(unit, local_port)) {
   4357                 cosq = node->hw_index -  SOC_HX5_CPU_MCQ_BASE;
   4358                 /* For CPU port's MC queue starting index: 2570 */
   4359                 index =  _BCM_HX5_MMU_L3_MC_CPU_QBASE + cosq;
   4360             } else if (IS_LB_PORT(unit, local_port)) {
   4361                 cosq = node->hw_index - SOC_HX5_LB_MCQ_BASE;
   4362                 index = _BCM_HX5_MMU_L3_MC_LB_QBASE + cosq;
   4363             } else {
   4364                 index = node->hw_index;
   4365                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4366                      index =  node->hw_index + SOC_HX5_NUM_UC_QUEUES_PER_PIPE;
   4367                 }
   4368             }
   4369         } else {
   4370             return BCM_E_PARAM;
   4371         }
   4372     } else {
   4373         if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) {
   4374             return BCM_E_PARAM;
   4375         }
   4376         if (IS_CPU_PORT(unit, local_port)) {
   4377             /* For CPU port, refer L3 memory (logical queue, starting index 2570)
   4378              * directly */
   4379             config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe];
   4380             index = _BCM_HX5_MMU_L3_MC_CPU_QBASE + cosq;
   4381         } else if (IS_LB_PORT(unit, local_port)) {
   4382             config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe];
   4383             index = _BCM_HX5_MMU_L3_MC_LB_QBASE + cosq;
   4384         } else {
   4385             if (_HX5_IS_ST_PORT(unit, mmu_port)) {
   4386                 index = (mmu_port * SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT) + cosq;
   4387             } else {
   4388                 index = SOC_HX5_DOWNLINK_PORTQ_BASE + ((mmu_port - 16) * SOC_HX5_NUM_UCAST_QUEUE_PER_PORT) + cosq;
   4389             }
   4390             config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L2_MEMm)[pipe];
   4391         }
   4392     }
   4393 
   4394     /*
   4395      * COVERITY
   4396      *
   4397      * This checker will not be True.
   4398      * It is kept intentionally as a defensive case for future development.
   4399      */
   4400     /* coverity[dead_error_line] */
   4401     if (config_mem == INVALIDm) {
   4402         return BCM_E_PARAM;
   4403     }
   4404 
   4405     if (min_quantum == NULL || max_quantum == NULL ||
   4406         kbits_burst_max == NULL || kbits_burst_min == NULL) {
   4407         return BCM_E_PARAM;
   4408     }
   4409 
   4410     BCM_IF_ERROR_RETURN
   4411         (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry));
   4412 
   4413     meter_flags = 0;
   4414     *flags = 0;
   4415     BCM_IF_ERROR_RETURN(READ_MMU_SEDCFG_MISCCONFIGr(unit, &rval));
   4416     if (soc_reg_field_get(unit, MMU_SEDCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) {
   4417         meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   4418     }
   4419     if (soc_mem_field32_get(unit, config_mem, &entry, SHAPER_CONTROLf)) {
   4420         meter_flags |= _BCM_TD_METER_FLAG_PACKET_MODE;
   4421         *flags |= BCM_COSQ_BW_PACKET_MODE;
   4422     }
   4423 
   4424     granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf);
   4425     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf);
   4426     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf);
   4427     BCM_IF_ERROR_RETURN
   4428         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   4429                                            granularity, meter_flags,
   4430                                            max_quantum, kbits_burst_max));
   4431 
   4432     granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf);
   4433     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf);
   4434     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf);
   4435     BCM_IF_ERROR_RETURN
   4436         (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   4437                                            granularity, meter_flags,
   4438                                            min_quantum, kbits_burst_min));
   4439     return BCM_E_NONE;
   4440 }
   4441 
   4442 /*
   4443  * Function:
   4444  *     _bcm_hx5_cosq_bucket_set
   4445  * Purpose:
   4446  *     Configure COS queue bandwidth control bucket
   4447  * Parameters:
   4448  *     unit          - (IN) unit number
   4449  *     gport         - (IN) port number or GPORT identifier
   4450  *     cosq          - (IN) COS queue number
   4451  *     min_quantum   - (IN) kbps or packet/second
   4452  *     max_quantum   - (IN) kbps or packet/second
   4453  *     burst_quantum - (IN) kbps or packet/second
   4454  *     flags         - (IN) BCM_COSQ_BW_XXX
   4455  * Returns:
   4456  *     BCM_E_XXX
   4457  * Notes:
   4458  *     If port is any form of local port, cosq is the hardware queue index.
   4459  */
   4460 STATIC int
   4461 _bcm_hx5_cosq_bucket_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   4462                         uint32 min_quantum, uint32 max_quantum,
   4463                         uint32 kbits_burst_min, uint32 kbits_burst_max,
   4464                         uint32 flags)
   4465 {
   4466     _bcm_hx5_cosq_node_t *node = NULL;
   4467     bcm_port_t local_port;
   4468     uint32 rval, meter_flags;
   4469     uint32 bucketsize_max, bucketsize_min;
   4470     uint32 granularity_max, granularity_min;
   4471     uint32 refresh_rate_max, refresh_rate_min;
   4472     int refresh_bitsize = 0, bucket_bitsize = 0;
   4473     int pipe, phy_port, mmu_port, index = 0;
   4474     soc_mem_t config_mem = INVALIDm;
   4475     uint32 entry[SOC_MAX_MEM_WORDS];
   4476     soc_info_t *si;
   4477 
   4478     /* caller should resolve the cosq. */
   4479     if (cosq < 0) {
   4480         if (cosq == -1) {
   4481             /* caller needs to resolve the wild card value (-1) */
   4482             return BCM_E_INTERNAL;
   4483         } else { /* reject all other negative value */
   4484             return BCM_E_PARAM;
   4485         }
   4486     }
   4487 
   4488     BCM_IF_ERROR_RETURN
   4489         (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   4490 
   4491     si = &SOC_INFO(unit);
   4492     phy_port = si->port_l2p_mapping[local_port];
   4493     mmu_port = si->port_p2m_mapping[phy_port];
   4494     pipe = si->port_pipe[local_port];
   4495 
   4496     if (BCM_GPORT_IS_SET(gport) &&
   4497         ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   4498           BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4499           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) { 
   4500 
   4501         BCM_IF_ERROR_RETURN
   4502             (_bcm_hx5_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   4503     }
   4504 
   4505     if (node) {
   4506         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   4507             if (node->level == SOC_HX5_NODE_LVL_L0) {
   4508                 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L0_MEMm)[pipe];
   4509                 index = node->hw_index;
   4510             } else if(node->level == SOC_HX5_NODE_LVL_L1) {
   4511                 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L1_MEMm)[pipe];
   4512                 index = node->hw_index;
   4513             } else if(node->level == SOC_HX5_NODE_LVL_L2) {
   4514                 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L2_MEMm)[pipe];
   4515                 index = node->hw_index;
   4516             } else {
   4517                 return BCM_E_PARAM;
   4518             }
   4519         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4520                    BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4521             config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe];
   4522             if (IS_CPU_PORT(unit, local_port)) {
   4523                 /* For CPU port, refer L3 memory (logical queue, starting index 2570)
   4524                  * directly */
   4525                 index = _BCM_HX5_MMU_L3_MC_CPU_QBASE + cosq;
   4526             } else if (IS_LB_PORT(unit, local_port)) {
   4527                 index = _BCM_HX5_MMU_L3_MC_LB_QBASE + cosq;
   4528             } else {
   4529                 index = node->hw_index;
   4530                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4531                      index =  node->hw_index + SOC_HX5_NUM_UC_QUEUES_PER_PIPE;
   4532                 }
   4533             }
   4534        } else {
   4535             return BCM_E_PARAM;
   4536        }
   4537     } else {
   4538         if ((cosq < 0) || (cosq >= si->port_num_cosq[local_port])) {
   4539             return BCM_E_PARAM;
   4540         }
   4541         if (IS_CPU_PORT(unit, local_port)) {
   4542             /* For CPU port, refer L1 memory (logical queue, starting index 1300)
   4543              * directly */
   4544             config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe];
   4545             index = _BCM_HX5_MMU_L3_MC_CPU_QBASE + cosq;
   4546         } else if (IS_LB_PORT(unit, local_port)) {
   4547             config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L3_MEMm)[pipe];
   4548             index = _BCM_HX5_MMU_L3_MC_LB_QBASE + cosq;
   4549         } else {
   4550             if (_HX5_IS_ST_PORT(unit, mmu_port)) {
   4551                 index = (mmu_port * SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT) + cosq;
   4552             } else {
   4553                 index = SOC_HX5_DOWNLINK_PORTQ_BASE + ((mmu_port - 16) * SOC_HX5_NUM_UCAST_QUEUE_PER_PORT) + cosq;
   4554             }
   4555             config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L2_MEMm)[pipe];
   4556         }
   4557     }
   4558 
   4559     /*
   4560      * COVERITY
   4561      *
   4562      * This checker will not be True.
   4563      * It is kept intentionally as a defensive check for future development.
   4564      */
   4565     /* coverity[dead_error_line] */
   4566     if (config_mem == INVALIDm) {
   4567         return BCM_E_PARAM;
   4568     }
   4569 
   4570     meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ?
   4571                             _BCM_TD_METER_FLAG_PACKET_MODE : 0;
   4572     BCM_IF_ERROR_RETURN(READ_MMU_SEDCFG_MISCCONFIGr(unit, &rval));
   4573 
   4574     if (soc_reg_field_get(unit, MMU_SEDCFG_MISCCONFIGr, rval, ITU_MODE_SELf)) {
   4575         meter_flags |= _BCM_TD_METER_FLAG_NON_LINEAR;
   4576     }
   4577 
   4578     refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf);
   4579     bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf);
   4580 
   4581     BCM_IF_ERROR_RETURN
   4582         (_bcm_td_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max,
   4583                                            meter_flags, refresh_bitsize,
   4584                                            bucket_bitsize, &refresh_rate_max,
   4585                                            &bucketsize_max, &granularity_max));
   4586 
   4587     BCM_IF_ERROR_RETURN
   4588         (_bcm_td_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min,
   4589                                            meter_flags, refresh_bitsize,
   4590                                            bucket_bitsize, &refresh_rate_min,
   4591                                            &bucketsize_min, &granularity_min));
   4592 
   4593     sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   4594 
   4595     soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max);
   4596     soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max);
   4597     soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max);
   4598 
   4599     soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min);
   4600     soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min);
   4601     soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min);
   4602 
   4603     soc_mem_field32_set(unit, config_mem, &entry, SHAPER_CONTROLf,
   4604                         (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0);
   4605 
   4606     BCM_IF_ERROR_RETURN
   4607         (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry));
   4608 
   4609     return BCM_E_NONE;
   4610 }
   4611 
   4612 /*
   4613  * Function:
   4614  *     bcm_hx5_cosq_gport_bandwidth_burst_set
   4615  * Purpose:
   4616  *     Configure COS queue bandwidth burst setting
   4617  * Parameters:
   4618  *      unit        - (IN) unit number
   4619  *      gport       - (IN) GPORT identifier
   4620  *      cosq        - (IN) COS queue to configure, -1 for all COS queues
   4621  *      kbits_burst - (IN) maximum burst, kbits
   4622  * Returns:
   4623  *      BCM_E_XXX
   4624  */
   4625 int
   4626 bcm_hx5_cosq_gport_bandwidth_burst_set(int unit, 
   4627                                       bcm_gport_t gport,
   4628                                       bcm_cos_queue_t cosq,
   4629                                       uint32 kbits_burst_min,
   4630                                       uint32 kbits_burst_max)
   4631 {
   4632     int i, start_cos=0, end_cos=0;
   4633     uint32 kbits_sec_min, kbits_sec_max, kbits_sec_burst, flags;
   4634     bcm_port_t local_port;
   4635     int phy_port, mmu_port;
   4636 
   4637 
   4638     soc_info_t *si = &SOC_INFO(unit);
   4639 
   4640     BCM_IF_ERROR_RETURN
   4641         (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   4642 
   4643     phy_port = si->port_l2p_mapping[local_port];
   4644     mmu_port = si->port_p2m_mapping[phy_port];
   4645     start_cos = end_cos = cosq;
   4646 
   4647     if (cosq == BCM_COS_INVALID) {
   4648         start_cos = 0;
   4649         if (IS_CPU_PORT(unit, local_port)) {
   4650            end_cos =  NUM_CPU_COSQ(unit); 
   4651         } else if(_HX5_IS_ST_PORT(unit, mmu_port)) {
   4652            end_cos = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; 
   4653         } else {
   4654            end_cos = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; 
   4655         }
   4656     }
   4657 
   4658     if (BCM_GPORT_IS_SET(gport)) {
   4659         if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   4660              BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4661              BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4662             start_cos = end_cos = 0;
   4663         }
   4664     }
   4665 
   4666     for (i = start_cos; i <= end_cos; i++) {
   4667         BCM_IF_ERROR_RETURN
   4668             (_bcm_hx5_cosq_bucket_get(unit, gport, i, &kbits_sec_min,
   4669                                      &kbits_sec_max, &kbits_sec_burst,
   4670                                      &kbits_sec_burst, &flags));
   4671         BCM_IF_ERROR_RETURN
   4672             (_bcm_hx5_cosq_bucket_set(unit, gport, i, kbits_sec_min,
   4673                                      kbits_sec_max, kbits_burst_min,
   4674                                      kbits_burst_max, flags));
   4675     }
   4676     return BCM_E_NONE;
   4677 }
   4678 
   4679 /*
   4680  * Function:
   4681  *     bcm_hx5_cosq_gport_bandwidth_burst_get
   4682  * Purpose:
   4683  *     Get COS queue bandwidth burst setting
   4684  * Parameters:
   4685  *     unit        - (IN) unit number
   4686  *     gport       - (IN) GPORT identifier
   4687  *     cosq        - (IN) COS queue to get, -1 for Queue 0
   4688  *     kbits_burst - (OUT) maximum burst, kbits
   4689  * Returns:
   4690  *     BCM_E_XXX
   4691  */
   4692 int
   4693 bcm_hx5_cosq_gport_bandwidth_burst_get(int unit, 
   4694                                       bcm_gport_t gport,
   4695                                       bcm_cos_queue_t cosq,
   4696                                       uint32 *kbits_burst_min,
   4697                                       uint32 *kbits_burst_max)
   4698 {
   4699     uint32 kbits_sec_min, kbits_sec_max, flags;
   4700 
   4701     if (cosq < -1) {
   4702         return BCM_E_PARAM;
   4703     }
   4704 
   4705     BCM_IF_ERROR_RETURN
   4706         (_bcm_hx5_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
   4707                                  &kbits_sec_min, &kbits_sec_max, kbits_burst_min,
   4708                                  kbits_burst_max, &flags));
   4709 
   4710     return BCM_E_NONE;
   4711 }
   4712 
   4713 /*
   4714  *   Function:
   4715  *        _bcm_hx5_cosq_mapping_set
   4716  *   Purpose:
   4717  *       Set COS queue for the specified priority of an ingress port
   4718  *   Parameters:
   4719  *        unit     - (IN) unit number
   4720  *        ing_port - (IN) ingress port
   4721  *        priority - (IN) priority value to map
   4722  *        flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   4723  *        gport    - (IN) queue group GPORT identifier
   4724  *        cosq     - (IN) COS queue number
   4725  *   Returns:
   4726  *         BCM_E_XXX
   4727  */
   4728 STATIC int
   4729 _bcm_hx5_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   4730         uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq)
   4731 {
   4732     bcm_port_t local_port, out_port;
   4733     bcm_cos_queue_t hw_cosq;
   4734     int rv, idx, numq;
   4735     int port;
   4736     soc_field_t field[3] = {INVALIDf, INVALIDf, INVALIDf}; /* [0]:UC, [1]:MC cos */
   4737     int value[3] = {0, 0, 0};
   4738     void *entries[1];
   4739     cos_map_sel_entry_t cos_map_sel_entry;
   4740     port_cos_map_entry_t cos_map_entries[_HX5_MMU_NUM_INT_PRI];
   4741     uint32 old_index, new_index;
   4742     soc_info_t *si;
   4743 
   4744     BCM_IF_ERROR_RETURN
   4745         (_bcm_hx5_cosq_localport_resolve(unit, ing_port, &local_port));
   4746 
   4747      si = &SOC_INFO(unit);
   4748 
   4749     if (gport != -1) {
   4750         BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_localport_resolve(unit, gport,
   4751                     &out_port));
   4752     }
   4753 
   4754     switch(flags) {
   4755         case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   4756             if (gport == -1) {
   4757                 hw_cosq = cosq;
   4758             } else {
   4759                 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4760                     return BCM_E_PARAM;
   4761                 }
   4762                 BCM_IF_ERROR_RETURN
   4763                         (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   4764                                                      _BCM_HX5_COSQ_INDEX_STYLE_COS, &port, &hw_cosq, NULL));
   4765                 if (!IS_CPU_PORT(unit, port)) {
   4766                     hw_cosq = hw_cosq - si->port_uc_cosq_base[port];
   4767                 }
   4768             }
   4769             hw_cosq = hw_cosq % 8;
   4770             field[0] = UC_COS1f;
   4771             field[1] = HG_COSf;
   4772             value[0] = hw_cosq;
   4773             value[1] = hw_cosq + 8;
   4774             break;
   4775         case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   4776             if (gport == -1) {
   4777                 hw_cosq = cosq;
   4778             } else {
   4779                 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4780                     return BCM_E_PARAM;
   4781                 }
   4782                 BCM_IF_ERROR_RETURN
   4783                     (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   4784                                                  _BCM_HX5_COSQ_INDEX_STYLE_COS, &port, &hw_cosq, NULL));
   4785                 if (!IS_CPU_PORT(unit, port)) {
   4786                     hw_cosq = hw_cosq - si->port_cosq_base[port];
   4787                 }
   4788             }
   4789             hw_cosq = hw_cosq % 8;
   4790             field[0] = MC_COS1f;
   4791             field[1] = HG_COSf;
   4792             value[0] = hw_cosq;
   4793             value[1] = hw_cosq + 8;
   4794             break;
   4795             case (BCM_COSQ_GPORT_UCAST_QUEUE_GROUP |
   4796                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP):
   4797                 if (gport == -1) {
   4798                     hw_cosq = cosq;
   4799                 } else {
   4800                     return BCM_E_PARAM;
   4801                 }
   4802                 hw_cosq = hw_cosq % 8;
   4803                 field[0] = UC_COS1f;
   4804                 field[1] = MC_COS1f;
   4805                 field[2] = HG_COSf;
   4806                 value[0] = hw_cosq;
   4807                 value[1] = hw_cosq; 
   4808                 value[2] = hw_cosq + 8;
   4809             break;
   4810         default:
   4811             return BCM_E_PARAM;
   4812     }
   4813 
   4814     numq = _BCM_HX5_NUM_COS(unit);
   4815     entries[0] = &cos_map_entries;
   4816     BCM_IF_ERROR_RETURN
   4817         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   4818                            &cos_map_sel_entry));
   4819     old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   4820             SELECTf);
   4821     old_index *= _HX5_MMU_NUM_INT_PRI;
   4822 
   4823     BCM_IF_ERROR_RETURN
   4824         (soc_profile_mem_get(unit, _bcm_hx5_cos_map_profile[unit], old_index,
   4825                              _HX5_MMU_NUM_INT_PRI, entries));
   4826 
   4827     for (idx = 0; idx < 3; idx++) {
   4828         if (field[idx] != INVALIDf) {
   4829             soc_mem_field32_set(unit, PORT_COS_MAPm, &cos_map_entries[priority],
   4830                     field[idx], value[idx]);
   4831         }
   4832     }
   4833 
   4834     soc_mem_lock(unit, PORT_COS_MAPm);
   4835     rv = soc_profile_mem_delete(unit, _bcm_hx5_cos_map_profile[unit],
   4836             old_index);
   4837     if (BCM_FAILURE(rv)) {
   4838         soc_mem_unlock(unit, PORT_COS_MAPm);
   4839         return rv;
   4840     }
   4841 
   4842     rv = soc_profile_mem_add(unit, _bcm_hx5_cos_map_profile[unit], entries,
   4843             _HX5_MMU_NUM_INT_PRI, &new_index);
   4844 
   4845     if (BCM_FAILURE(rv)) {
   4846         soc_mem_unlock(unit, PORT_COS_MAPm);
   4847         return rv;
   4848     }
   4849 
   4850     soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf,
   4851             new_index / _HX5_MMU_NUM_INT_PRI);
   4852     BCM_IF_ERROR_RETURN
   4853         (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   4854                             &cos_map_sel_entry));
   4855 
   4856 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   4857     if (IS_CPU_PORT(unit, local_port)) {
   4858         BCM_IF_ERROR_RETURN
   4859             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   4860                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   4861                                     new_index / _HX5_MMU_NUM_INT_PRI));
   4862     }
   4863 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   4864 
   4865    /* update the wireless part of the cos_map table */
   4866     rv = bcm_hx5_wireless_cos_map_update(unit, numq);
   4867 
   4868     if (rv < 0) {
   4869         return rv;
   4870     }
   4871     return BCM_E_NONE;
   4872 }
   4873 
   4874 /*
   4875  *   Function:
   4876  *       _bcm_hx5_cosq_mapping_get
   4877  *   Purpose:
   4878  *      Determine which COS queue a given priority currently maps to.
   4879  *   Parameters:
   4880  *        unit     - (IN) unit number
   4881  *        ing_port - (IN) ingress port
   4882  *        priority - (IN) priority value to map
   4883  *        flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   4884  *        gport    - (IN) queue group GPORT identifier
   4885  *        cosq     - (OUT) COS queue number
   4886  *    Returns:
   4887  *       BCM_E_XXX
   4888  */
   4889 STATIC int
   4890 _bcm_hx5_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   4891         uint32 flags, bcm_gport_t *gport,
   4892         bcm_cos_queue_t *cosq)
   4893 {
   4894     bcm_port_t local_port;
   4895     cos_map_sel_entry_t cos_map_sel_entry;
   4896     _bcm_hx5_cosq_port_info_t *port_info = NULL;
   4897     _bcm_hx5_cosq_st_port_info_t *stport_info = NULL;
   4898     _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
   4899     _bcm_hx5_cosq_node_t *node;
   4900     int ii, index;
   4901     void *entry_p;
   4902     bcm_cos_queue_t hw_cosq = BCM_COS_INVALID, node_cosq = BCM_COS_INVALID;
   4903     int numq = -1;
   4904     int phy_port, mmu_port, port_index;
   4905 
   4906 
   4907     soc_info_t *si = &SOC_INFO(unit);
   4908 
   4909     if ((flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP) &&
   4910             (flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP)) {
   4911         return BCM_E_PARAM;
   4912     }
   4913 
   4914     BCM_IF_ERROR_RETURN
   4915         (_bcm_hx5_cosq_localport_resolve(unit, ing_port, &local_port));
   4916 
   4917     phy_port = si->port_l2p_mapping[local_port];
   4918     mmu_port = si->port_p2m_mapping[phy_port];
   4919 
   4920     if (gport) {
   4921         *gport = BCM_GPORT_INVALID;
   4922     }
   4923 
   4924     *cosq = BCM_COS_INVALID;
   4925 
   4926     BCM_IF_ERROR_RETURN
   4927         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   4928                            &cos_map_sel_entry));
   4929     index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   4930             SELECTf);
   4931     index *= _HX5_MMU_NUM_INT_PRI;
   4932 
   4933     entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_hx5_cos_map_profile[unit],
   4934             port_cos_map_entry_t *, index + priority);
   4935 
   4936     if (IS_CPU_PORT(unit, local_port)) {
   4937         cpu_port_info = &_bcm_hx5_cosq_cpu_port_info[unit][local_port];
   4938         numq = SOC_HX5_NUM_CPU_QUEUES;
   4939     } else {
   4940         _HX5_PORT_INDEX_GET(unit, mmu_port, port_index);
   4941         if (_HX5_IS_ST_PORT(unit, mmu_port)) {
   4942             stport_info = &_bcm_hx5_cosq_st_port_info[unit][port_index];
   4943             numq = SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT;
   4944         } else {
   4945             port_info = &_bcm_hx5_cosq_port_info[unit][port_index];
   4946             numq = SOC_HX5_NUM_UCAST_QUEUE_PER_PORT;
   4947         }
   4948     }
   4949 
   4950     switch (flags) {
   4951         case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   4952             hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p,
   4953                     UC_COS1f);
   4954             if ((IS_CPU_PORT(unit, local_port) == FALSE) && (gport)) {
   4955                 for (ii = 0; ii < numq; ii++) {
   4956                     if (_HX5_IS_ST_PORT(unit, mmu_port)) {
   4957                         node = &stport_info->ucast[ii];
   4958                     } else {
   4959                         node = &port_info->ucast[ii];
   4960                     }
   4961                     if (node == NULL) {
   4962                         return BCM_E_NOT_FOUND;
   4963                     }
   4964                     node_cosq = node->hw_index - si->port_uc_cosq_base[local_port];
   4965                     if (node && (node_cosq == hw_cosq)) {
   4966                         *gport = node->gport;
   4967                         *cosq = hw_cosq % 8;
   4968                         break;
   4969                     }
   4970                 }
   4971             } else {
   4972                 *cosq = hw_cosq;
   4973             }
   4974             break;
   4975         case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   4976             hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p,
   4977                     MC_COS1f);
   4978             if (gport) {
   4979                 for (ii = 0; ii < numq; ii++) {
   4980                     if (IS_CPU_PORT(unit, local_port)) {
   4981                         node = &cpu_port_info->mcast[ii];
   4982                     } else {
   4983                         if (_HX5_IS_ST_PORT(unit, mmu_port)) {
   4984                             node = &stport_info->mcast[ii];
   4985                         } else {
   4986                             node = &port_info->mcast[ii];
   4987                         }
   4988                     }
   4989                     if (!node) {
   4990                         return BCM_E_NOT_FOUND;
   4991                     }
   4992                     if (IS_CPU_PORT(unit, local_port)) {
   4993                         node_cosq = node->hw_index - _HX5_CPU_L2_NODE_BASE;
   4994                     } else {
   4995                         node_cosq = node->hw_index - si->port_cosq_base[local_port]; 
   4996                     }
   4997                     if (node_cosq == hw_cosq) {
   4998                         *gport = node->gport;
   4999                         *cosq = hw_cosq % 8;
   5000                         break;
   5001                     }
   5002                 }
   5003             } else {
   5004                 *cosq = hw_cosq;
   5005             }
   5006             break;
   5007             /*
   5008              * COVERITY
   5009              *
   5010              *This default is unreachable. It is kept intentionally
   5011              *as a defensive default for future development.
   5012              */
   5013             /* coverity[dead_error_begin] */
   5014         default:
   5015             return BCM_E_PARAM;
   5016     }
   5017 
   5018     if (((gport &&
   5019                     (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID))) ||
   5020             (*cosq == BCM_COS_INVALID)) {
   5021         return BCM_E_NOT_FOUND;
   5022     }
   5023 
   5024     return BCM_E_NONE;
   5025 }
   5026 
   5027 /*
   5028  *   Function:
   5029  *       bcm_hx5_cosq_mapping_set
   5030  *   Purpose:
   5031  *        Set which cosq a given priority should fall into
   5032  *   Parameters:
   5033  *        unit     - (IN) unit number
   5034  *        gport    - (IN) queue group GPORT identifier
   5035  *        priority - (IN) priority value to map
   5036  *        cosq     - (INT) COS queue number
   5037  *   Returns:
   5038  *        BCM_E_XXX
   5039  */
   5040 int
   5041 bcm_hx5_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority,
   5042         bcm_cos_queue_t cosq)
   5043 {
   5044     bcm_pbmp_t pbmp;
   5045     bcm_port_t local_port;
   5046     int rv = BCM_E_NONE, numq;
   5047 
   5048     BCM_PBMP_CLEAR(pbmp);
   5049 
   5050     if ((priority < 0) || (priority >= _HX5_MMU_NUM_INT_PRI)) {
   5051         return BCM_E_PARAM;
   5052     }
   5053 
   5054     if (cosq < 0) {
   5055         return BCM_E_PARAM;
   5056     }
   5057 
   5058     if (port == -1) {
   5059         /* port value of -1 will cause the cosq mapping set for
   5060          *          * all types of local ports except Loopback ports.
   5061          *                   * So we do the sanity check of cos value with Default Number
   5062          *                            * of COS
   5063  */
   5064         if (cosq >= _BCM_HX5_NUM_COS(unit)) {
   5065             return BCM_E_PARAM;
   5066         }
   5067         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   5068     } else {
   5069         if (BCM_GPORT_IS_SET(port)) {
   5070             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   5071                     BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   5072                     BCM_GPORT_IS_SCHEDULER(port)) {
   5073                 return BCM_E_PARAM;
   5074             } else if (BCM_GPORT_IS_LOCAL(port)) {
   5075                 local_port = BCM_GPORT_LOCAL_GET(port);
   5076             } else if (BCM_GPORT_IS_MODPORT(port)) {
   5077                 BCM_IF_ERROR_RETURN
   5078                     (bcm_esw_port_local_get(unit, port, &local_port));
   5079             } else {
   5080                 return BCM_E_PARAM;
   5081             }
   5082         } else {
   5083             local_port = port;
   5084         }
   5085 
   5086         if (!SOC_PORT_VALID(unit, local_port)) {
   5087             return BCM_E_PORT;
   5088         }
   5089 
   5090         BCM_PBMP_PORT_ADD(pbmp, local_port);
   5091         if (cosq >= _HX5_PORT_NUM_COS(unit, local_port)) {
   5092             return BCM_E_PARAM;
   5093         }
   5094     }
   5095 
   5096     numq = _BCM_HX5_NUM_COS(unit);
   5097     PBMP_ITER(pbmp, local_port) {
   5098         if (IS_LB_PORT(unit, local_port)) {
   5099             continue;
   5100         }
   5101 
   5102         /* If no ETS/gport, map the int prio symmetrically for ucast and
   5103          *          * mcast */
   5104         BCM_IF_ERROR_RETURN
   5105             (_bcm_hx5_cosq_mapping_set(unit, local_port, priority,
   5106                                        BCM_COSQ_GPORT_UCAST_QUEUE_GROUP |
   5107                                        BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   5108                                        -1, cosq));
   5109     }
   5110 
   5111     rv = bcm_hx5_wireless_cos_map_update(unit, numq);
   5112 
   5113     if (rv < 0) {
   5114         return rv;
   5115     }
   5116 
   5117     return BCM_E_NONE;
   5118 }
   5119 
   5120 /*
   5121  *   Function:
   5122  *       bcm_hx5_cosq_gport_mapping_set
   5123  *   Purpose:
   5124  *        Set COS queue for the specified priority of an ingress port
   5125  *   Parameters:
   5126  *        unit     - (IN) unit number
   5127  *        ing_port - (IN) ingress port
   5128  *        int_pri  - (IN) priority value to map
   5129  *        flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   5130  *        gport    - (IN) queue group GPORT identifier
   5131  *        cosq     - (IN) COS queue number
   5132  *    Returns:
   5133  *        BCM_E_XXX
   5134  */
   5135 int
   5136 bcm_hx5_cosq_gport_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t int_pri,
   5137         uint32 flags, bcm_gport_t gport,
   5138         bcm_cos_queue_t cosq)
   5139 {
   5140     bcm_port_t local_port;
   5141 
   5142     if ((int_pri < 0) || (int_pri >= _HX5_MMU_NUM_INT_PRI)) {
   5143         return BCM_E_PARAM;
   5144     }
   5145 
   5146     BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_localport_resolve(unit, ing_port,
   5147                 &local_port));
   5148 
   5149     if ((cosq < 0) || (cosq >= _HX5_PORT_NUM_COS(unit, local_port))) {
   5150         return BCM_E_PARAM;
   5151     }
   5152 
   5153     return _bcm_hx5_cosq_mapping_set(unit, ing_port, int_pri, flags, gport,
   5154             cosq);
   5155 }
   5156 
   5157 /*
   5158  *   Function:
   5159  *       bcm_hx5_cosq_mapping_get
   5160  *   Purpose:
   5161  *       Determine which COS queue a given priority currently maps to.
   5162  *   Parameters:
   5163  *       unit     - (IN) unit number
   5164  *       gport    - (IN) queue group GPORT identifier
   5165  *       priority - (IN) priority value to map
   5166  *       cosq     - (OUT) COS queue number
   5167  *   Returns:
   5168  *       BCM_E_XXX
   5169  */
   5170 int
   5171 bcm_hx5_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority,
   5172         bcm_cos_queue_t *cosq)
   5173 {
   5174     bcm_port_t local_port;
   5175     bcm_pbmp_t pbmp;
   5176 
   5177     BCM_PBMP_CLEAR(pbmp);
   5178 
   5179     if ((priority < 0) || (priority >= _HX5_MMU_NUM_INT_PRI)) {
   5180         return BCM_E_PARAM;
   5181     }
   5182 
   5183     if (port == -1) {
   5184         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   5185     } else {
   5186         if (BCM_GPORT_IS_SET(port)) {
   5187             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   5188                     BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   5189                     BCM_GPORT_IS_SCHEDULER(port)) {
   5190                 return BCM_E_PARAM;
   5191             } else if (BCM_GPORT_IS_LOCAL(port)) {
   5192                 local_port = BCM_GPORT_LOCAL_GET(port);
   5193             } else if (BCM_GPORT_IS_MODPORT(port)) {
   5194                 BCM_IF_ERROR_RETURN
   5195                     (bcm_esw_port_local_get(unit, port, &local_port));
   5196             } else {
   5197                 return BCM_E_PARAM;
   5198             }
   5199         } else {
   5200             local_port = port;
   5201         }
   5202 
   5203         if (!SOC_PORT_VALID(unit, local_port)) {
   5204             return BCM_E_PORT;
   5205         }
   5206 
   5207         BCM_PBMP_PORT_ADD(pbmp, local_port);
   5208     }
   5209 
   5210     PBMP_ITER(pbmp, local_port) {
   5211         if (IS_LB_PORT(unit, local_port)) {
   5212             continue;
   5213         }
   5214 
   5215         BCM_IF_ERROR_RETURN
   5216             (_bcm_hx5_cosq_mapping_get(unit, local_port, priority,
   5217                                        BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL,
   5218                                        cosq));
   5219         break;
   5220     }
   5221 
   5222     return BCM_E_NONE;
   5223 
   5224 }
   5225 
   5226 /*
   5227  *   Function:
   5228  *      _bcm_hx5_cosq_gport_mapping_get
   5229  *   Purpose:
   5230  *       Determine which COS queue a given priority currently maps to.
   5231  *   Parameters:
   5232  *       unit     - (IN) unit number
   5233  *       ing_port - (IN) ingress port
   5234  *       int_pri  - (IN) priority value to map
   5235  *       flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   5236  *       gport    - (IN) queue group GPORT identifier
   5237  *        cosq     - (OUT) COS queue number
   5238  *  Returns:
   5239  *       BCM_E_XXX
   5240  */
   5241 int
   5242 bcm_hx5_cosq_gport_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t int_pri,
   5243         uint32 flags, bcm_gport_t *gport,
   5244         bcm_cos_queue_t *cosq)
   5245 {
   5246     if (gport == NULL || cosq == NULL) {
   5247         return BCM_E_PARAM;
   5248     }
   5249 
   5250     if ((int_pri < 0) || (int_pri >= _HX5_MMU_NUM_INT_PRI)) {
   5251         return BCM_E_PARAM;
   5252     }
   5253 
   5254     return _bcm_hx5_cosq_mapping_get(unit, ing_port, int_pri, flags, gport,
   5255             cosq);
   5256 }
   5257 
   5258 
   5259 STATIC int
   5260 _bcm_hx5_cosq_egr_pool_set(int unit, bcm_gport_t gport, 
   5261                           bcm_cos_queue_t cosq, bcm_cosq_control_t type, int arg)
   5262 {
   5263     bcm_port_t local_port;
   5264     int startq, pool, midx;
   5265     uint32 max_val;
   5266     uint32 entry[SOC_MAX_MEM_WORDS];
   5267     uint32 entry2[SOC_MAX_MEM_WORDS];
   5268     soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm;
   5269     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
   5270     soc_field_t fld_limit = INVALIDf;
   5271     int granularity = 1, pipe;
   5272 
   5273     if (arg < 0) {
   5274         return BCM_E_PARAM;
   5275     }
   5276 
   5277     BCM_IF_ERROR_RETURN
   5278         (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5279                                      _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL,
   5280                                      &local_port, &pool, NULL));
   5281 
   5282     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5283 
   5284     base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   5285     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5286 
   5287     if (type == bcmCosqControlEgressPoolLimitEnable) {
   5288         midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   5289         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   5290                             midx, entry));
   5291 
   5292         soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, !!arg);
   5293 
   5294         return soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry);
   5295     }
   5296     if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool ||
   5297         type == bcmCosqControlMCEgressPool) {
   5298         if((arg < 0) || (arg >= _HX5_MMU_NUM_POOL)) {
   5299             return BCM_E_PARAM;
   5300         }
   5301         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5302             if (type != bcmCosqControlEgressPool) {
   5303                 return BCM_E_PARAM;
   5304             }
   5305             /* regular unicast queue */
   5306             BCM_IF_ERROR_RETURN
   5307                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5308                                      _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5309                                      &local_port, &startq, NULL));
   5310             base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   5311             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5312         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5313             if (type != bcmCosqControlEgressPool) {
   5314                 return BCM_E_PARAM;
   5315             }
   5316             BCM_IF_ERROR_RETURN
   5317                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5318                                      _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5319                                      &local_port, &startq, NULL));
   5320             base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   5321             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5322             base_mem2 = MMU_THDM_DB_QUEUE_CONFIGm;
   5323             mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
   5324         } else  { /* local port */
   5325             if (type == bcmCosqControlUCEgressPool) {
   5326                 BCM_IF_ERROR_RETURN
   5327                     (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5328                                          _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5329                                          &local_port, &startq, NULL));
   5330                 base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   5331                 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5332             } else {
   5333                 BCM_IF_ERROR_RETURN
   5334                     (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5335                                              _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5336                                              &local_port, &startq, NULL));
   5337                 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   5338                 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5339                 base_mem2 = MMU_THDM_DB_QUEUE_CONFIGm;
   5340                 mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
   5341             }
   5342         }
   5343 
   5344         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5345         soc_mem_field32_set(unit, mem, entry, Q_SPIDf, arg);
   5346 
   5347         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5348         if (mem2 != INVALIDm) {
   5349             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   5350             soc_mem_field32_set(unit, mem2, entry2, Q_SPIDf, arg);
   5351             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   5352         }
   5353         return BCM_E_NONE;
   5354     }
   5355 
   5356     arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL;
   5357 
   5358     /* per service pool settings */
   5359     if (type == bcmCosqControlEgressPoolSharedLimitBytes ||
   5360         type == bcmCosqControlEgressPoolResumeLimitBytes ||
   5361         type == bcmCosqControlEgressPoolYellowSharedLimitBytes ||
   5362         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
   5363         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
   5364         type == bcmCosqControlEgressPoolRedResumeLimitBytes) {
   5365                 uint32 rval;
   5366         soc_reg_t reg;
   5367         switch (type) {
   5368         case bcmCosqControlEgressPoolSharedLimitBytes:
   5369             reg = MMU_THDM_DB_POOL_SHARED_LIMITr;
   5370             fld_limit = SHARED_LIMITf;
   5371             granularity = 1;
   5372             break;
   5373         case bcmCosqControlEgressPoolResumeLimitBytes:
   5374             reg = MMU_THDM_DB_POOL_RESUME_LIMITr;
   5375             fld_limit = RESUME_LIMITf;
   5376             granularity = 8;
   5377             break;
   5378         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
   5379             reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;
   5380             fld_limit = YELLOW_SHARED_LIMITf;
   5381             granularity = 8;
   5382             break;
   5383         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
   5384             reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr;
   5385             fld_limit = YELLOW_RESUME_LIMITf;
   5386             granularity = 8;
   5387             break;
   5388         case bcmCosqControlEgressPoolRedSharedLimitBytes:
   5389             reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;
   5390             fld_limit = RED_SHARED_LIMITf;
   5391             granularity = 8;
   5392             break;
   5393         case bcmCosqControlEgressPoolRedResumeLimitBytes:
   5394             reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr;
   5395             fld_limit = RED_RESUME_LIMITf;
   5396             granularity = 8;
   5397             break;
   5398         /* coverity[dead_error_begin] */
   5399         default:
   5400             return BCM_E_UNAVAIL;
   5401         }
   5402 
   5403         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval));
   5404 
   5405         /* Check for min/max values */
   5406         max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1;
   5407         if ((arg < 0) || ((arg/granularity) > max_val)) {
   5408             return BCM_E_PARAM;
   5409         } else {
   5410             soc_reg_field_set(unit, reg, &rval, fld_limit, (arg/granularity));
   5411         }
   5412 
   5413         BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, pool, rval));
   5414 
   5415         return BCM_E_NONE;
   5416     }
   5417 
   5418     if (type == bcmCosqControlEgressPoolHighCongestionLimitBytes ||
   5419             type == bcmCosqControlEgressPoolLowCongestionLimitBytes) {
   5420         uint64 rval64;
   5421         soc_reg_t reg64;
   5422         soc_reg_t wred_cng_lmt[4] = {
   5423             WRED_POOL_INST_CONG_LIMIT_0r,
   5424             WRED_POOL_INST_CONG_LIMIT_1r,
   5425             WRED_POOL_INST_CONG_LIMIT_2r,
   5426             WRED_POOL_INST_CONG_LIMIT_3r,
   5427         };
   5428 
   5429         switch (type) {
   5430             case bcmCosqControlEgressPoolHighCongestionLimitBytes:
   5431                 reg64 = wred_cng_lmt[pool];
   5432                 fld_limit = POOL_HI_CONG_LIMITf;
   5433                 pool = -1;
   5434                 granularity = 1;
   5435                 break;
   5436             case bcmCosqControlEgressPoolLowCongestionLimitBytes:
   5437                 reg64 = wred_cng_lmt[pool];
   5438                 fld_limit = POOL_LOW_CONG_LIMITf;
   5439                 pool = -1;
   5440                 granularity = 1;
   5441                 break;
   5442                 /* coverity[dead_error_begin] */
   5443             default:
   5444                 return BCM_E_UNAVAIL;
   5445         }
   5446 
   5447         BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg64, REG_PORT_ANY, pool, &rval64));
   5448 
   5449         /* Check for min/max values */
   5450         max_val = (1 << soc_reg_field_length(unit, reg64, fld_limit)) - 1;
   5451         if ((arg < 0) || ((arg/granularity) > max_val)) {
   5452             return BCM_E_PARAM;
   5453         } else {
   5454             soc_reg64_field32_set(unit, reg64, &rval64, fld_limit, (arg/granularity));
   5455         }
   5456 
   5457         BCM_IF_ERROR_RETURN(soc_reg64_set(unit, reg64, REG_PORT_ANY, pool, rval64));
   5458 
   5459         return BCM_E_NONE;
   5460     }
   5461 
   5462     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5463         BCM_IF_ERROR_RETURN
   5464             (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5465                                          _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5466                                          &local_port, &startq, NULL));
   5467         base_mem = MMU_THDU_CONFIG_QUEUEm;
   5468         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5469         base_mem2 = MMU_THDU_Q_TO_QGRP_MAPm;
   5470         mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
   5471     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5472         BCM_IF_ERROR_RETURN
   5473             (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5474                                          _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5475                                          &local_port, &startq, NULL));
   5476         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
   5477         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5478     } else {
   5479         if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) {
   5480             /* Need to have the UC_MC_Combine config enabled */
   5481             return BCM_E_PARAM;
   5482         }
   5483         base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   5484         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5485         startq = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   5486     }
   5487 
   5488     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5489 
   5490     if (mem2 != INVALIDm) {
   5491         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   5492     }
   5493 
   5494     switch (type) {
   5495         case bcmCosqControlEgressPoolLimitBytes:
   5496             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5497                 fld_limit = Q_SHARED_LIMIT_CELLf;
   5498 
   5499                 if (mem2 != INVALIDm) {
   5500                     soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
   5501                 }
   5502             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5503                 fld_limit = Q_SHARED_LIMITf;
   5504                 soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1);
   5505             } else {
   5506                 fld_limit = SHARED_LIMITf;
   5507                 soc_mem_field32_set(unit, mem, entry, SHARED_LIMIT_ENABLEf, 1);
   5508             }
   5509             granularity = 1;
   5510             break;
   5511         case bcmCosqControlEgressPoolYellowLimitBytes:
   5512             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5513                 fld_limit = LIMIT_YELLOW_CELLf;
   5514             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5515                 fld_limit = YELLOW_SHARED_LIMITf;
   5516             } else {
   5517                 fld_limit = YELLOW_SHARED_LIMITf;
   5518             }
   5519             granularity = 8;
   5520             break;
   5521         case bcmCosqControlEgressPoolRedLimitBytes:
   5522             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5523                 fld_limit = LIMIT_RED_CELLf;
   5524             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5525                 fld_limit = RED_SHARED_LIMITf;
   5526             } else {
   5527                 fld_limit = RED_SHARED_LIMITf;
   5528             }
   5529             granularity = 8;
   5530             break;
   5531         default:
   5532             return BCM_E_UNAVAIL;
   5533     }
   5534 
   5535     /* Check for min/max values */
   5536     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   5537     if ((arg < 0) || ((arg/granularity) > max_val)) {
   5538         return BCM_E_PARAM;
   5539     } else {
   5540         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   5541     }
   5542     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5543 
   5544     if (mem2 != INVALIDm) {
   5545         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   5546     }
   5547     return BCM_E_NONE;
   5548 }
   5549 
   5550 STATIC int
   5551 _bcm_hx5_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   5552                           bcm_cosq_control_t type, int *arg)
   5553 {
   5554     bcm_port_t local_port;
   5555     int startq, pool, midx, pipe;
   5556     uint32 entry[SOC_MAX_MEM_WORDS];
   5557     soc_mem_t mem, base_mem;
   5558     int granularity = 1;
   5559 
   5560     if (!arg) {
   5561         return BCM_E_PARAM;
   5562     }
   5563 
   5564     BCM_IF_ERROR_RETURN
   5565         (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5566                                      _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL,
   5567                                      &local_port, &pool, NULL));
   5568 
   5569     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5570 
   5571     if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool ||
   5572         type == bcmCosqControlMCEgressPool) {
   5573         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5574             if (type != bcmCosqControlEgressPool) {
   5575                 return BCM_E_PARAM;
   5576             }
   5577             /* regular unicast queue */
   5578             BCM_IF_ERROR_RETURN
   5579                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5580                                      _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5581                                      &local_port, &startq, NULL));
   5582             base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   5583             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5584         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5585             if (type != bcmCosqControlEgressPool) {
   5586                 return BCM_E_PARAM;
   5587             }
   5588             BCM_IF_ERROR_RETURN
   5589                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5590                                      _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5591                                      &local_port, &startq, NULL));
   5592             base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   5593             mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5594         } else  { /* local port */
   5595             if (type == bcmCosqControlUCEgressPool) {
   5596                 BCM_IF_ERROR_RETURN
   5597                     (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5598                                          _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5599                                          &local_port, &startq, NULL));
   5600                 base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   5601                 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5602             } else {
   5603                 BCM_IF_ERROR_RETURN
   5604                     (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5605                                              _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5606                                              &local_port, &startq, NULL));
   5607                 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   5608                 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5609             }
   5610         }
   5611 
   5612         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5613         *arg = soc_mem_field32_get(unit, mem, entry, Q_SPIDf);
   5614         return BCM_E_NONE;
   5615     }
   5616 
   5617     /* per service pool settings */
   5618     if (type == bcmCosqControlEgressPoolSharedLimitBytes ||
   5619         type == bcmCosqControlEgressPoolResumeLimitBytes ||
   5620         type == bcmCosqControlEgressPoolYellowSharedLimitBytes ||
   5621         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
   5622         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
   5623         type == bcmCosqControlEgressPoolRedResumeLimitBytes) {
   5624         uint32 rval;
   5625         soc_reg_t reg;
   5626         soc_field_t fld_limit = INVALIDf;
   5627         switch (type) {
   5628         case bcmCosqControlEgressPoolSharedLimitBytes:
   5629             reg = MMU_THDM_DB_POOL_SHARED_LIMITr;
   5630             fld_limit = SHARED_LIMITf;
   5631             granularity = 1;
   5632             break;
   5633         case bcmCosqControlEgressPoolResumeLimitBytes:
   5634             reg = MMU_THDM_DB_POOL_RESUME_LIMITr;
   5635             fld_limit = RESUME_LIMITf;
   5636             granularity = 8;
   5637             break;
   5638         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
   5639             reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr;
   5640             fld_limit = YELLOW_SHARED_LIMITf;
   5641             granularity = 8;
   5642             break;
   5643         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
   5644             reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr;
   5645             fld_limit = YELLOW_RESUME_LIMITf;
   5646             granularity = 8;
   5647             break;
   5648         case bcmCosqControlEgressPoolRedSharedLimitBytes:
   5649             reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr;
   5650             fld_limit = RED_SHARED_LIMITf;
   5651             granularity = 8;
   5652             break;
   5653         case bcmCosqControlEgressPoolRedResumeLimitBytes:
   5654             reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr;
   5655             fld_limit = RED_RESUME_LIMITf;
   5656             granularity = 8;
   5657             break;
   5658         /* coverity[dead_error_begin] */
   5659         default:
   5660             return BCM_E_UNAVAIL;
   5661         }
   5662 
   5663         BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, pool, &rval));
   5664 
   5665         *arg = soc_reg_field_get(unit, reg, rval, fld_limit);
   5666         *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL;
   5667 
   5668         return BCM_E_NONE;
   5669     }
   5670 
   5671     if (type == bcmCosqControlEgressPoolHighCongestionLimitBytes ||
   5672         type == bcmCosqControlEgressPoolLowCongestionLimitBytes) {
   5673         uint64 rval64;
   5674         soc_reg_t reg64;
   5675         soc_reg_t wred_cng_lmt[4] = {
   5676             WRED_POOL_INST_CONG_LIMIT_0r,
   5677             WRED_POOL_INST_CONG_LIMIT_1r,
   5678             WRED_POOL_INST_CONG_LIMIT_2r,
   5679             WRED_POOL_INST_CONG_LIMIT_3r,
   5680         };
   5681         soc_field_t fld_limit = INVALIDf;
   5682 
   5683         switch (type) {
   5684         case bcmCosqControlEgressPoolHighCongestionLimitBytes:
   5685             reg64 = wred_cng_lmt[pool];
   5686             fld_limit = POOL_HI_CONG_LIMITf;
   5687             pool = -1;
   5688             granularity = 1;
   5689             break;
   5690         case bcmCosqControlEgressPoolLowCongestionLimitBytes:
   5691             reg64 = wred_cng_lmt[pool];
   5692             fld_limit = POOL_LOW_CONG_LIMITf;
   5693             pool = -1;
   5694             granularity = 1;
   5695             break;
   5696         /* coverity[dead_error_begin] */
   5697         default:
   5698             return BCM_E_UNAVAIL;
   5699         }
   5700 
   5701         BCM_IF_ERROR_RETURN(soc_reg64_get(unit, reg64, REG_PORT_ANY, pool, &rval64));
   5702 
   5703         *arg = soc_reg64_field32_get(unit, reg64, rval64, fld_limit);
   5704         *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL;
   5705 
   5706         return BCM_E_NONE;
   5707     }
   5708 
   5709     base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   5710     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5711 
   5712     if (type == bcmCosqControlEgressPoolLimitEnable) {
   5713         midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   5714         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   5715                                  midx, entry));
   5716 
   5717         *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMIT_ENABLEf);
   5718         return BCM_E_NONE;
   5719     }
   5720 
   5721     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5722         BCM_IF_ERROR_RETURN
   5723             (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5724                                         _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5725                                         &local_port, &startq, NULL));
   5726         base_mem = MMU_THDU_CONFIG_QUEUEm;
   5727         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5728     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5729         BCM_IF_ERROR_RETURN
   5730             (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5731                                         _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5732                                         &local_port, &startq, NULL));
   5733 
   5734         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
   5735         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5736     } else {
   5737         if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) {
   5738             /* Need to have the UC_MC_Combine config enabled */
   5739             return BCM_E_PARAM;
   5740         }
   5741         base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   5742         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   5743         startq = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   5744     }
   5745     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   5746                              startq, entry));
   5747 
   5748     switch (type) {
   5749         case bcmCosqControlEgressPoolLimitBytes:
   5750             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5751                 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf);
   5752             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5753                 *arg = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMITf);
   5754             } else {
   5755                 *arg = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf);
   5756             }
   5757             granularity = 1;
   5758             break;
   5759         case bcmCosqControlEgressPoolYellowLimitBytes:
   5760             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5761                 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_YELLOW_CELLf);
   5762             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5763                 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf);
   5764             } else {
   5765                 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_SHARED_LIMITf);
   5766             }
   5767             granularity = 8;
   5768             break;
   5769         case bcmCosqControlEgressPoolRedLimitBytes:
   5770             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5771                 *arg = soc_mem_field32_get(unit, mem, entry, LIMIT_RED_CELLf);
   5772             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5773                 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf);
   5774             } else {
   5775                 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf);
   5776             }
   5777             granularity = 8;
   5778             break;
   5779         default:
   5780             return BCM_E_UNAVAIL;
   5781     }
   5782     *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL;
   5783     return BCM_E_NONE;
   5784 }
   5785 
   5786 STATIC int
   5787 _bcm_hx5_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   5788                             bcm_cosq_control_t type, int arg)
   5789 {
   5790     bcm_port_t local_port;
   5791     int pipe, startq;
   5792     uint32 max_val, rval;
   5793     uint32 entry[SOC_MAX_MEM_WORDS];
   5794     uint32 entry2[SOC_MAX_MEM_WORDS];
   5795     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
   5796     soc_field_t fld_limit = INVALIDf;
   5797     int granularity = 1;
   5798     int from_cos, to_cos, ci;
   5799     int egr_db_shd_size, egr_qe_shd_size, cur_val, post_update;
   5800     int limit;
   5801     int disable_queuing = 0;
   5802     int uc_qlimit_enable = 0, mc_qlimit_enable = 0;
   5803 
   5804     if (arg < 0) {
   5805         return BCM_E_PARAM;
   5806     }
   5807 
   5808     arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL;
   5809 
   5810     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   5811         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
   5812         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5813             BCM_IF_ERROR_RETURN
   5814                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5815                                              _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5816                                              &local_port, &startq, NULL));
   5817             SOC_IF_ERROR_RETURN
   5818                 (soc_port_pipe_get(unit, local_port, &pipe));
   5819         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5820             return BCM_E_PARAM;
   5821         }
   5822         else {
   5823             if (cosq == BCM_COS_INVALID) {
   5824                 from_cos = to_cos = 0;
   5825             } else {
   5826                 from_cos = to_cos = cosq;
   5827             }
   5828 
   5829             BCM_IF_ERROR_RETURN
   5830                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   5831             if (local_port < 0) {
   5832                 return BCM_E_PORT;
   5833             }
   5834             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5835             for (ci = from_cos; ci <= to_cos; ci++) {
   5836                 BCM_IF_ERROR_RETURN
   5837                     (_bcm_hx5_cosq_index_resolve
   5838                      (unit, local_port, ci, _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5839                       NULL, &startq, NULL));
   5840             }
   5841         }
   5842         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe];
   5843         mem2 = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_Q_TO_QGRP_MAPm)[pipe];
   5844     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
   5845                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
   5846         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5847             return BCM_E_PARAM;
   5848         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5849             BCM_IF_ERROR_RETURN
   5850                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   5851                                              _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5852                                              &local_port, &startq, NULL));
   5853             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5854         }
   5855         else {
   5856             if (cosq == BCM_COS_INVALID) {
   5857                 from_cos = to_cos = 0;
   5858             } else {
   5859                 from_cos = to_cos = cosq;
   5860             }
   5861 
   5862             BCM_IF_ERROR_RETURN
   5863                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   5864             if (local_port < 0) {
   5865                 return BCM_E_PORT;
   5866             }
   5867             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5868             for (ci = from_cos; ci <= to_cos; ci++) {
   5869                 BCM_IF_ERROR_RETURN
   5870                     (_bcm_hx5_cosq_index_resolve
   5871                      (unit, local_port, ci, _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5872                       NULL, &startq, NULL));
   5873             }
   5874         }
   5875         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe];
   5876         mem2 = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_MCQE_QUEUE_CONFIGm)[pipe];
   5877     } else {
   5878         return BCM_E_PARAM;
   5879     }
   5880 
   5881     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5882     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   5883 
   5884     switch (type) {
   5885         case bcmCosqControlEgressUCQueueSharedLimitBytes:
   5886             fld_limit = Q_SHARED_LIMIT_CELLf;
   5887             uc_qlimit_enable = 1;
   5888 
   5889             /* Set MMU_THDU_XPIPE_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN
   5890              * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT
   5891              * is non-zero.
   5892              */
   5893             limit = soc_mem_field32_get(unit, mem, entry, Q_MIN_LIMIT_CELLf);
   5894             if (arg == 0 && limit == 0) {
   5895                 disable_queuing = 1;
   5896             } else if (arg != 0 || limit != 0) {
   5897                 disable_queuing = 0;
   5898             }
   5899             granularity = 1;
   5900             break;
   5901         case bcmCosqControlEgressMCQueueSharedLimitBytes:
   5902             fld_limit = Q_SHARED_LIMITf;
   5903             mc_qlimit_enable = 1;
   5904             granularity = 1;
   5905             break;
   5906         case bcmCosqControlEgressUCQueueMinLimitBytes:
   5907             fld_limit = Q_MIN_LIMIT_CELLf;
   5908 
   5909             /* Set MMU_THDU_Q_TO_QGRP_MAP.DISABLE_QUEUING to 1 when both MIN
   5910              * and SHARED LIMIT are 0. Set it to 0 when either MIN or
   5911              * SHARED LIMIT is non-zero
   5912              */
   5913             limit = soc_mem_field32_get(unit, mem, entry, Q_SHARED_LIMIT_CELLf);
   5914             if (arg == 0 && limit == 0) {
   5915                 disable_queuing = 1;
   5916             } else if (arg != 0 || limit != 0) {
   5917                 disable_queuing = 0;
   5918             }
   5919 
   5920             granularity = 1;
   5921             break;
   5922         case bcmCosqControlEgressMCQueueMinLimitBytes:
   5923             fld_limit = Q_MIN_LIMITf;
   5924             granularity = 1;
   5925             break;
   5926         default:
   5927             return BCM_E_UNAVAIL;
   5928     }
   5929 
   5930     /* Recalculate Shared Values if Min Changed */
   5931     /* THDO - DB */
   5932     rval = 0;
   5933     SOC_IF_ERROR_RETURN
   5934         (READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval));
   5935     egr_db_shd_size = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
   5936                                         rval, SHARED_LIMITf);
   5937 
   5938     /* THDO - QE */
   5939     rval = 0;
   5940     SOC_IF_ERROR_RETURN
   5941         (READ_MMU_THDM_MCQE_POOL_SHARED_LIMITr(unit, 0, &rval));
   5942     egr_qe_shd_size = soc_reg_field_get(unit, MMU_THDM_MCQE_POOL_SHARED_LIMITr,
   5943                                         rval, SHARED_LIMITf);	
   5944     cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit);
   5945 
   5946     if ((arg / granularity) > cur_val) {
   5947         /* New Min Val > Cur Min Val
   5948          * So reduce the Shared values first and then
   5949          * Increase the Min Value for given resource
   5950          */
   5951         post_update = 0;
   5952     } else if ((arg / granularity) < cur_val) {
   5953         /* New Min Val < Cur Min Val
   5954          * So reduce the Min values first and then
   5955          * Increase Shared values everywhere
   5956          */
   5957         post_update = 1;
   5958     } else {
   5959         return BCM_E_NONE;
   5960     }
   5961 
   5962     if (!post_update &&
   5963         ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   5964          (type == bcmCosqControlEgressMCQueueMinLimitBytes))) {
   5965         int delta = 0; /* In Cells */
   5966         delta = ((arg / granularity) - cur_val) * granularity;
   5967         if (delta > egr_db_shd_size) {
   5968             return BCM_E_PARAM;
   5969         }
   5970         SOC_IF_ERROR_RETURN(
   5971             soc_hx5_mmu_config_shared_buf_recalc(unit, 2 /* egr */, -1,
   5972                                                  egr_db_shd_size - delta,
   5973                                                  egr_qe_shd_size, 1));
   5974     }
   5975 
   5976 
   5977     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5978     if (mem2 != INVALIDm) {
   5979         BCM_IF_ERROR_RETURN
   5980             (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   5981     }
   5982     /* Check for min/max values */
   5983     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   5984     if ((arg < 0) || ((arg/granularity) > max_val)) {
   5985         return BCM_E_PARAM;
   5986     } else {
   5987         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   5988     }
   5989 
   5990     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   5991         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
   5992         soc_mem_field32_set(unit, mem2, entry2, DISABLE_QUEUINGf,
   5993                             disable_queuing);
   5994     }
   5995 
   5996     if (mc_qlimit_enable) {
   5997         soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, 1);
   5998         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
   5999     }
   6000 
   6001     if (uc_qlimit_enable) {
   6002         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_ENABLEf, 1);
   6003     }
   6004 
   6005     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6006     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq,
   6007                                       entry2));
   6008 
   6009     if (post_update &&
   6010         ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   6011          (type == bcmCosqControlEgressMCQueueMinLimitBytes))) {
   6012         int delta = 0;
   6013         delta = (cur_val - (arg / granularity)) * granularity;
   6014 
   6015         SOC_IF_ERROR_RETURN(
   6016             soc_hx5_mmu_config_shared_buf_recalc(unit, 2 /* egr */, -1,
   6017                                                  egr_db_shd_size + delta,
   6018                                                  egr_qe_shd_size, 0));
   6019     }
   6020 
   6021     return BCM_E_NONE;
   6022 }
   6023 
   6024 
   6025 STATIC int
   6026 _bcm_hx5_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   6027                             bcm_cosq_control_t type, int *arg)
   6028 {
   6029     bcm_port_t local_port;
   6030     int pipe, startq;
   6031     uint32 entry[SOC_MAX_MEM_WORDS];
   6032     soc_mem_t mem = INVALIDm;
   6033     soc_field_t fld_limit = INVALIDf;
   6034     int granularity = 1;
   6035     int from_cos, to_cos, ci;
   6036 
   6037     if (!arg) {
   6038         return BCM_E_PARAM;
   6039     }
   6040 
   6041     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   6042         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
   6043         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6044             BCM_IF_ERROR_RETURN
   6045                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   6046                                              _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6047                                              &local_port, &startq, NULL));
   6048             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6049         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6050             return BCM_E_PARAM;
   6051         }
   6052         else {
   6053             if (cosq == BCM_COS_INVALID) {
   6054                 from_cos = to_cos = 0;
   6055             } else {
   6056                 from_cos = to_cos = cosq;
   6057             }
   6058 
   6059             BCM_IF_ERROR_RETURN
   6060                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6061             if (local_port < 0) {
   6062                 return BCM_E_PORT;
   6063             }
   6064             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6065             for (ci = from_cos; ci <= to_cos; ci++) {
   6066                 BCM_IF_ERROR_RETURN
   6067                     (_bcm_hx5_cosq_index_resolve
   6068                      (unit, local_port, ci, _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6069                       NULL, &startq, NULL));
   6070             }
   6071         }
   6072         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDU_CONFIG_QUEUEm)[pipe];
   6073     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
   6074                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
   6075         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6076             return BCM_E_PARAM;
   6077         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6078             BCM_IF_ERROR_RETURN
   6079                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   6080                                              _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   6081                                              &local_port, &startq, NULL));
   6082             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6083         }
   6084         else {
   6085             if (cosq == BCM_COS_INVALID) {
   6086                 from_cos = to_cos = 0;
   6087             } else {
   6088                 from_cos = to_cos = cosq;
   6089             }
   6090 
   6091             BCM_IF_ERROR_RETURN
   6092                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6093             if (local_port < 0) {
   6094                 return BCM_E_PORT;
   6095             }
   6096             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6097             for (ci = from_cos; ci <= to_cos; ci++) {
   6098                 BCM_IF_ERROR_RETURN
   6099                     (_bcm_hx5_cosq_index_resolve
   6100                      (unit, local_port, ci, _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   6101                       NULL, &startq, NULL));
   6102             }
   6103         }
   6104         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDM_DB_QUEUE_CONFIGm)[pipe];
   6105     } else {
   6106         return BCM_E_PARAM;
   6107     }
   6108 
   6109     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   6110                              startq, entry));
   6111 
   6112     switch (type) {
   6113         case bcmCosqControlEgressUCQueueSharedLimitBytes:
   6114             fld_limit = Q_SHARED_LIMIT_CELLf;
   6115             granularity = 1;
   6116             break;
   6117         case bcmCosqControlEgressMCQueueSharedLimitBytes:
   6118             fld_limit = Q_SHARED_LIMITf;
   6119             granularity = 1;
   6120             break;
   6121         case bcmCosqControlEgressUCQueueMinLimitBytes:
   6122             fld_limit = Q_MIN_LIMIT_CELLf;
   6123             granularity = 1;
   6124             break;
   6125         case bcmCosqControlEgressMCQueueMinLimitBytes:
   6126             fld_limit = Q_MIN_LIMITf;
   6127             granularity = 1;
   6128             break;
   6129         default:
   6130             return BCM_E_UNAVAIL;
   6131     }
   6132     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
   6133     *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL;
   6134     return BCM_E_NONE;
   6135 }
   6136 
   6137 STATIC int
   6138 _bcm_hx5_cosq_egr_queue_limit_enable_set(int unit, bcm_gport_t gport,
   6139                                         bcm_cos_queue_t cosq,
   6140                                         bcm_cosq_control_t type,
   6141                                         int arg)
   6142 {
   6143     bcm_port_t local_port;
   6144     int startq, pipe;
   6145     uint32 entry[SOC_MAX_MEM_WORDS];
   6146     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   6147     int enable;
   6148 
   6149     if (arg < 0) {
   6150         return BCM_E_PARAM;
   6151     }
   6152 
   6153     arg = arg ? 1 : 0;
   6154 
   6155     if (type == bcmCosqControlEgressUCQueueLimitEnable) {
   6156         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6157             BCM_IF_ERROR_RETURN
   6158                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   6159                                             _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6160                                             &local_port, &startq, NULL));
   6161         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6162             return BCM_E_PARAM;
   6163         } else {
   6164             if (cosq < 0) {
   6165                 return BCM_E_PARAM;
   6166             }
   6167             BCM_IF_ERROR_RETURN
   6168                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6169             if (local_port < 0) {
   6170                 return BCM_E_PORT;
   6171             }
   6172             BCM_IF_ERROR_RETURN
   6173                 (_bcm_hx5_cosq_index_resolve
   6174                  (unit, local_port, cosq, _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6175                   NULL, &startq, NULL));
   6176         }
   6177 
   6178         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6179 
   6180         base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   6181         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6182         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6183         enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
   6184         if (enable != arg) {
   6185             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg);
   6186             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6187         }
   6188     } else if (type == bcmCosqControlEgressMCQueueLimitEnable) {
   6189         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6190             return BCM_E_PARAM;
   6191         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6192             BCM_IF_ERROR_RETURN
   6193                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   6194                                             _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   6195                                             &local_port, &startq, NULL));
   6196         } else {
   6197             if (cosq < 0) {
   6198                 return BCM_E_PARAM;
   6199             }
   6200             BCM_IF_ERROR_RETURN
   6201                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6202             if (local_port < 0) {
   6203                 return BCM_E_PORT;
   6204             }
   6205             BCM_IF_ERROR_RETURN
   6206                 (_bcm_hx5_cosq_index_resolve(unit, local_port, cosq,
   6207                                             _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   6208                                             NULL, &startq, NULL));
   6209         }
   6210 
   6211         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6212 
   6213         base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   6214         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6215         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6216         enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
   6217         if (enable != arg) {
   6218             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg);
   6219             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6220         }
   6221 
   6222         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
   6223         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6224         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6225         enable = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
   6226         if (enable != arg) {
   6227             soc_mem_field32_set(unit, mem, entry, Q_LIMIT_ENABLEf, arg);
   6228             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6229         }
   6230     } else {
   6231         return BCM_E_PARAM;
   6232     }
   6233 
   6234     return BCM_E_NONE;
   6235 }
   6236 
   6237 STATIC int
   6238 _bcm_hx5_cosq_egr_queue_limit_enable_get(int unit, bcm_gport_t gport,
   6239                                          bcm_cos_queue_t cosq,
   6240                                          bcm_cosq_control_t type,
   6241                                          int *arg)
   6242 {
   6243     bcm_port_t local_port;
   6244     int startq, pipe;
   6245     uint32 entry[SOC_MAX_MEM_WORDS];
   6246     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   6247 
   6248     if (type == bcmCosqControlEgressUCQueueLimitEnable) {
   6249         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6250             BCM_IF_ERROR_RETURN
   6251                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   6252                                           _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6253                                           &local_port, &startq, NULL));
   6254         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6255             return BCM_E_PARAM;
   6256         } else {
   6257             if (cosq < 0) {
   6258                 return BCM_E_PARAM;
   6259             }
   6260             BCM_IF_ERROR_RETURN
   6261                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6262             if (local_port < 0) {
   6263                 return BCM_E_PORT;
   6264             }
   6265             BCM_IF_ERROR_RETURN
   6266                 (_bcm_hx5_cosq_index_resolve
   6267                     (unit, local_port, cosq, _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6268                      NULL, &startq, NULL));
   6269         }
   6270 
   6271         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6272 
   6273         base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   6274         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6275         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6276         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
   6277     } else if (type == bcmCosqControlEgressMCQueueLimitEnable) {
   6278         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6279             return BCM_E_PARAM;
   6280         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6281             BCM_IF_ERROR_RETURN
   6282                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   6283                                      _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   6284                                      &local_port, &startq, NULL));
   6285         } else {
   6286             if (cosq < 0) {
   6287                 return BCM_E_PARAM;
   6288             }
   6289             BCM_IF_ERROR_RETURN
   6290                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6291             if (local_port < 0) {
   6292                 return BCM_E_PORT;
   6293             }
   6294             BCM_IF_ERROR_RETURN
   6295                 (_bcm_hx5_cosq_index_resolve(unit, local_port, cosq,
   6296                                     _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   6297                                      NULL, &startq, NULL));
   6298         }
   6299         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6300 
   6301         base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm;
   6302         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6303 
   6304         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6305         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_ENABLEf);
   6306     } else {
   6307         return BCM_E_PARAM;
   6308     }
   6309     return BCM_E_NONE;
   6310 }
   6311 
   6312 STATIC int
   6313 _bcm_hx5_cosq_egr_port_pool_set(int unit, bcm_gport_t gport,
   6314                                bcm_cos_queue_t cosq,
   6315                                bcm_cosq_control_t type, int arg)
   6316 {
   6317     bcm_port_t local_port;
   6318     uint32 max_val;
   6319     uint32 entry[SOC_MAX_MEM_WORDS];
   6320     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   6321     soc_field_t fld_limit = INVALIDf;
   6322     int granularity = 1;
   6323     int pool, midx, pipe;
   6324 
   6325     if (arg < 0) {
   6326         return BCM_E_PARAM;
   6327     }
   6328 
   6329     BCM_IF_ERROR_RETURN
   6330         (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   6331                                      _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL,
   6332                                      &local_port, &pool, NULL));
   6333 
   6334     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6335 
   6336     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) {
   6337         base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   6338     } else {
   6339         base_mem = MMU_THDU_CONFIG_PORTm;
   6340     }
   6341 
   6342     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6343     midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   6344     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   6345 
   6346     switch (type) {
   6347         case bcmCosqControlEgressPortPoolYellowLimitBytes:
   6348             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) {
   6349                 fld_limit = YELLOW_SHARED_LIMITf;
   6350             } else {
   6351                 fld_limit = YELLOW_LIMITf;
   6352             }
   6353             granularity = 8;
   6354             break;
   6355         case bcmCosqControlEgressPortPoolRedLimitBytes:
   6356             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) {
   6357                 fld_limit = RED_SHARED_LIMITf;
   6358             } else {
   6359                 fld_limit = RED_LIMITf;
   6360             }
   6361             granularity = 8;
   6362             break;
   6363         default:
   6364             return BCM_E_UNAVAIL;
   6365     }
   6366 
   6367     arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL;
   6368 
   6369     /* Check for min/max values */
   6370     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   6371     if ((arg < 0) || ((arg/granularity) > max_val)) {
   6372         return BCM_E_PARAM;
   6373     } else {
   6374         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   6375     }
   6376     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   6377 
   6378     return BCM_E_NONE;
   6379 }
   6380 
   6381 STATIC int
   6382 _bcm_hx5_cosq_egr_port_pool_get(int unit, bcm_gport_t gport,
   6383                                bcm_cos_queue_t cosq,
   6384                                bcm_cosq_control_t type, int *arg)
   6385 {
   6386     bcm_port_t local_port;
   6387     uint32 entry[SOC_MAX_MEM_WORDS];
   6388     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   6389     int granularity = 1;
   6390     int pool, midx, pipe;
   6391 
   6392     if (!arg) {
   6393         return BCM_E_PARAM;
   6394     }
   6395 
   6396     BCM_IF_ERROR_RETURN
   6397         (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   6398                                      _BCM_HX5_COSQ_INDEX_STYLE_EGR_POOL,
   6399                                      &local_port, &pool, NULL));
   6400 
   6401     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6402 
   6403     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) {
   6404         base_mem = MMU_THDM_DB_PORTSP_CONFIGm;
   6405     } else {
   6406         base_mem = MMU_THDU_CONFIG_PORTm;
   6407     }
   6408 
   6409     
   6410     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6411     midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   6412     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   6413 
   6414     switch (type) {
   6415         case bcmCosqControlEgressPortPoolYellowLimitBytes:
   6416             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) {
   6417                 *arg = soc_mem_field32_get(unit, mem, entry,
   6418                                            YELLOW_SHARED_LIMITf);
   6419             } else {
   6420                 *arg = soc_mem_field32_get(unit, mem, entry, YELLOW_LIMITf);
   6421             }
   6422             granularity = 8;
   6423             break;
   6424         case bcmCosqControlEgressPortPoolRedLimitBytes:
   6425             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) || IS_CPU_PORT(unit, local_port)) {
   6426                 *arg = soc_mem_field32_get(unit, mem, entry, RED_SHARED_LIMITf);
   6427             } else {
   6428                 *arg = soc_mem_field32_get(unit, mem, entry, RED_LIMITf);
   6429             }
   6430             granularity = 8;
   6431             break;
   6432         default:
   6433             return BCM_E_UNAVAIL;
   6434     }
   6435 
   6436     *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL;
   6437     return BCM_E_NONE;
   6438 }
   6439 
   6440 /*
   6441  * This function is used to get the
   6442  * Min and Max value of ingress PG or SP
   6443  */
   6444 STATIC int
   6445 _bcm_hx5_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   6446                           bcm_cosq_control_t type, int *arg)
   6447 {
   6448     bcm_port_t local_port;
   6449     int midx;
   6450     uint32 entry[SOC_MAX_MEM_WORDS];
   6451     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   6452     soc_field_t fld_limit = INVALIDf;
   6453     int pipe, port_pg;
   6454     int pool, granularity = 1;
   6455 
   6456     if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) {
   6457         /* Error. Input pri > Max Pri_Grp */
   6458         return BCM_E_PARAM;
   6459     }
   6460 
   6461     if (arg == NULL) {
   6462         return BCM_E_PARAM;
   6463     }
   6464 
   6465     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6466         BCM_GPORT_IS_SCHEDULER(gport) ||
   6467         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6468         return BCM_E_PARAM;
   6469     }
   6470 
   6471     BCM_IF_ERROR_RETURN
   6472         (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6473     if (local_port < 0) {
   6474         return BCM_E_PORT;
   6475     }
   6476 
   6477     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6478     BCM_IF_ERROR_RETURN
   6479         (_bcm_hx5_cosq_ingress_pg_get(unit, gport, cosq, &port_pg, NULL));
   6480     BCM_IF_ERROR_RETURN
   6481         (_bcm_hx5_cosq_ingress_sp_get(unit, gport, cosq, &pool, NULL));
   6482 
   6483     if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) ||
   6484         (type == bcmCosqControlIngressPortPGMinLimitBytes) ||
   6485         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) ||
   6486         (type == bcmCosqControlIngressPortPGResetFloorBytes)) {
   6487         base_mem = THDI_PORT_PG_CONFIGm;
   6488         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6489         /* get index for Port-PG */
   6490         midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   6491     } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) ||
   6492                (type == bcmCosqControlIngressPortPoolMinLimitBytes)) {
   6493         base_mem = THDI_PORT_SP_CONFIGm;
   6494         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6495         /* get index for Port-SP */
   6496         midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   6497     } else {
   6498         return BCM_E_UNAVAIL;
   6499     }
   6500 
   6501     if (midx < 0) {
   6502         return BCM_E_PARAM;
   6503     }
   6504 
   6505     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   6506 
   6507     switch (type) {
   6508         case bcmCosqControlIngressPortPGSharedLimitBytes:
   6509             fld_limit = PG_SHARED_LIMITf;
   6510             granularity = 1;
   6511             break;
   6512         case bcmCosqControlIngressPortPoolMaxLimitBytes:
   6513             fld_limit = PORT_SP_MAX_LIMITf;
   6514             granularity = 1;
   6515             break;
   6516         case bcmCosqControlIngressPortPGMinLimitBytes:
   6517             fld_limit = PG_MIN_LIMITf;
   6518             granularity = 1;
   6519             break;
   6520         case bcmCosqControlIngressPortPoolMinLimitBytes:
   6521             fld_limit = PORT_SP_MIN_LIMITf;
   6522             granularity = 1;
   6523             break;
   6524         case bcmCosqControlIngressPortPGHeadroomLimitBytes:
   6525             fld_limit = PG_HDRM_LIMITf;
   6526             granularity = 1;
   6527             break;
   6528         case bcmCosqControlIngressPortPGResetFloorBytes:
   6529             fld_limit = PG_RESET_FLOORf;
   6530             granularity = 1;
   6531             break;
   6532         /* coverity[dead_error_begin] */
   6533         default:
   6534             return BCM_E_UNAVAIL;
   6535     }
   6536 
   6537     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
   6538     *arg = (*arg) * granularity * _HX5_MMU_BYTES_PER_CELL;
   6539 
   6540     return BCM_E_NONE;
   6541 }
   6542 
   6543 STATIC int
   6544 _bcm_hx5_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   6545                           bcm_cosq_control_t type, int arg)
   6546 {
   6547     bcm_port_t local_port;
   6548     int midx;
   6549     uint32 max_val;
   6550     uint32 entry[SOC_MAX_MEM_WORDS];
   6551     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   6552     soc_field_t fld_limit = INVALIDf;
   6553     int pipe, port_pg;
   6554     int pool, granularity = 1;
   6555     int  ing_shd_size, cur_val;
   6556 
   6557     if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) {
   6558         /* Error. Input pri > Max Pri_Grp */
   6559         return BCM_E_PARAM;
   6560     }
   6561 
   6562     if (arg < 0) {
   6563         return BCM_E_PARAM;
   6564     }
   6565 
   6566     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6567         BCM_GPORT_IS_SCHEDULER(gport) ||
   6568         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6569         return BCM_E_PARAM;
   6570     }
   6571 
   6572     arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL;
   6573     BCM_IF_ERROR_RETURN
   6574         (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6575     if (local_port < 0) {
   6576         return BCM_E_PORT;
   6577     }
   6578 
   6579     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6580     BCM_IF_ERROR_RETURN
   6581         (_bcm_hx5_cosq_ingress_pg_get(unit, gport, cosq, &port_pg, NULL));
   6582     BCM_IF_ERROR_RETURN
   6583         (_bcm_hx5_cosq_ingress_sp_get(unit, gport, cosq, &pool, NULL));
   6584 
   6585     if ((type == bcmCosqControlIngressPortPGSharedLimitBytes) ||
   6586         (type == bcmCosqControlIngressPortPGMinLimitBytes) ||
   6587         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) ||
   6588         (type == bcmCosqControlIngressPortPGResetFloorBytes)) {
   6589         base_mem = THDI_PORT_PG_CONFIGm;
   6590         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6591         /* get index for Port-PG */
   6592         midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   6593     } else if ((type == bcmCosqControlIngressPortPoolMaxLimitBytes) ||
   6594                (type == bcmCosqControlIngressPortPoolMinLimitBytes)) {
   6595         base_mem = THDI_PORT_SP_CONFIGm;
   6596         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6597         /* get index for Port-SP */
   6598         midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, pool);
   6599     } else {
   6600         return BCM_E_UNAVAIL;
   6601     }
   6602 
   6603     if (midx < 0) {
   6604         return BCM_E_PARAM;
   6605     }
   6606 
   6607     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   6608 
   6609     switch (type) {
   6610         case bcmCosqControlIngressPortPGSharedLimitBytes:
   6611             fld_limit = PG_SHARED_LIMITf;
   6612             granularity = 1;
   6613             break;
   6614         case bcmCosqControlIngressPortPoolMaxLimitBytes:
   6615             fld_limit = PORT_SP_MAX_LIMITf;
   6616             granularity = 1;
   6617             break;
   6618         case bcmCosqControlIngressPortPGMinLimitBytes:
   6619             fld_limit = PG_MIN_LIMITf;
   6620             granularity = 1;
   6621             break;
   6622         case bcmCosqControlIngressPortPoolMinLimitBytes:
   6623             fld_limit = PORT_SP_MIN_LIMITf;
   6624             granularity = 1;
   6625             break;
   6626         case bcmCosqControlIngressPortPGHeadroomLimitBytes:
   6627             fld_limit = PG_HDRM_LIMITf;
   6628             granularity = 1;
   6629             break;
   6630         case bcmCosqControlIngressPortPGResetFloorBytes:
   6631             fld_limit = PG_RESET_FLOORf;
   6632             granularity = 1;
   6633             break;
   6634         /* coverity[dead_error_begin] */
   6635         default:
   6636             return BCM_E_UNAVAIL;
   6637     }
   6638 
   6639     /* Recalculate Shared Values if Min Changed */
   6640     cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit);
   6641 
   6642     if((arg / granularity) == cur_val) {
   6643         return BCM_E_NONE;
   6644     }
   6645 
   6646     if (type == bcmCosqControlIngressPortPGMinLimitBytes) {
   6647         int delta = 0; /* In Cells */
   6648         uint32 rval = 0;
   6649         /* Read THDI shared size from Service pool 0 */
   6650         SOC_IF_ERROR_RETURN
   6651             (READ_THDI_BUFFER_CELL_LIMIT_SPr(unit, 0, &rval));
   6652         ing_shd_size = soc_reg_field_get(unit, THDI_BUFFER_CELL_LIMIT_SPr,
   6653                                          rval, LIMITf);
   6654         if ((arg / granularity) > cur_val) {
   6655            /* New Min Val > Cur Min Val
   6656             * So reduce the Shared values first and then
   6657             * Increase the Min Value for given resource */             
   6658             delta = ((arg / granularity) - cur_val) * granularity;	
   6659             if (delta > ing_shd_size) {
   6660                 return BCM_E_PARAM;
   6661             }
   6662 
   6663             SOC_IF_ERROR_RETURN(
   6664                 soc_hx5_mmu_config_shared_buf_recalc(unit, 1 /* ing */,
   6665                                                      ing_shd_size - delta,
   6666                                                      -1, -1, 1));
   6667 
   6668             /* the value may be changed by soc_hx5_mmu_config_res_limits_update
   6669              * so read the register again in order to keep consistent  */
   6670             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   6671         }
   6672 
   6673         /* Check for min/max values */
   6674         max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   6675         if ((arg < 0) || ((arg/granularity) > max_val)) {
   6676             return BCM_E_PARAM;
   6677         }
   6678 
   6679         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   6680         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   6681 
   6682         if ((arg / granularity) < cur_val) {
   6683            /* New Min Val < Cur Min Val
   6684             * So reduce the Min values first and then
   6685             * Increase Shared values everywhere */
   6686             delta = (cur_val - (arg / granularity)) * granularity;
   6687             if (delta > ing_shd_size) {
   6688                 return BCM_E_PARAM;
   6689             }
   6690             SOC_IF_ERROR_RETURN(
   6691                 soc_hx5_mmu_config_shared_buf_recalc(unit, 1 /* ing */,
   6692                                                      ing_shd_size + delta,
   6693                                                      -1, -1,  0));
   6694         }
   6695     } else {
   6696         /* Check for min/max values */
   6697         max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   6698         if ((arg < 0) || ((arg/granularity) > max_val)) {
   6699             return BCM_E_PARAM;
   6700         }
   6701         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   6702         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   6703     }
   6704 
   6705 	return BCM_E_NONE;
   6706 }
   6707 
   6708 /*
   6709  * This function is used to get ingress pool
   6710  * limit given Ingress [Port, Priority]
   6711  */
   6712 STATIC int
   6713 _bcm_hx5_cosq_ing_res_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq,
   6714                                bcm_cosq_control_t type, int *arg)
   6715 {
   6716     uint32 rval = 0x0;
   6717     int pool;
   6718     int local_port;
   6719     soc_reg_t reg = INVALIDr;
   6720 
   6721     if (arg == NULL) {
   6722         return BCM_E_PARAM;
   6723     }
   6724 
   6725     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6726         BCM_GPORT_IS_SCHEDULER(gport) ||
   6727         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6728         return BCM_E_PARAM;
   6729     }
   6730 
   6731     BCM_IF_ERROR_RETURN
   6732             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6733 
   6734     if (!SOC_PORT_VALID(unit, local_port)) {
   6735         return BCM_E_PORT;
   6736     }
   6737 
   6738     if (type == bcmCosqControlIngressPoolLimitBytes) {
   6739         BCM_IF_ERROR_RETURN
   6740             (_bcm_hx5_cosq_ing_pool_get(unit, gport, cosq,
   6741                                        bcmCosqControlIngressPool,
   6742                                        &pool));
   6743         reg = THDI_BUFFER_CELL_LIMIT_SPr;
   6744     } else if (type == bcmCosqControlIngressHeadroomPoolLimitBytes) {
   6745         BCM_IF_ERROR_RETURN
   6746             (_bcm_hx5_cosq_ing_pool_get(unit, gport, cosq,
   6747                                         bcmCosqControlIngressHeadroomPool,
   6748                                         &pool));
   6749         reg = THDI_HDRM_BUFFER_CELL_LIMIT_HPr;
   6750     } else {
   6751         return BCM_E_PARAM;
   6752     }
   6753 
   6754     SOC_IF_ERROR_RETURN(
   6755         soc_trident3_xpe_reg32_get(unit,reg,
   6756                                    -1, 0, pool, &rval));
   6757     *arg = soc_reg_field_get(unit, reg, rval, LIMITf);
   6758 
   6759     *arg *= _HX5_MMU_BYTES_PER_CELL;
   6760 
   6761     return BCM_E_NONE;
   6762 }
   6763 
   6764 /*
   6765  * This function is used to set ingress pool
   6766  * limit given Ingress [Port, Priority]
   6767  */
   6768 STATIC int
   6769 _bcm_hx5_cosq_ing_res_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq,
   6770                                bcm_cosq_control_t type, int arg)
   6771 {
   6772     uint32 rval = 0x0;
   6773     int pool;
   6774     int local_port;
   6775     soc_reg_t reg = INVALIDr;
   6776 
   6777     if (arg < 0) {
   6778         return BCM_E_PARAM;
   6779     }
   6780 
   6781     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6782         BCM_GPORT_IS_SCHEDULER(gport) ||
   6783         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6784         return BCM_E_PARAM;
   6785     }
   6786     BCM_IF_ERROR_RETURN
   6787             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6788 
   6789     if (!SOC_PORT_VALID(unit, local_port)) {
   6790         return BCM_E_PORT;
   6791     }
   6792 
   6793     arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL;
   6794 
   6795     if (type == bcmCosqControlIngressPoolLimitBytes) {
   6796         BCM_IF_ERROR_RETURN
   6797             (_bcm_hx5_cosq_ing_pool_get(unit, gport, cosq,
   6798                                        bcmCosqControlIngressPool,
   6799                                        &pool));
   6800         reg = THDI_BUFFER_CELL_LIMIT_SPr;
   6801     } else if (type == bcmCosqControlIngressHeadroomPoolLimitBytes) {
   6802         BCM_IF_ERROR_RETURN
   6803             (_bcm_hx5_cosq_ing_pool_get(unit, gport, cosq,
   6804                                        bcmCosqControlIngressHeadroomPool,
   6805                                        &pool));
   6806         reg = THDI_HDRM_BUFFER_CELL_LIMIT_HPr;
   6807     } else {
   6808         return BCM_E_PARAM;
   6809     }
   6810 
   6811     soc_reg_field_set(unit, reg, &rval, LIMITf, arg);
   6812     SOC_IF_ERROR_RETURN(
   6813         soc_trident3_xpe_reg32_set(unit, reg,
   6814                                    -1, 0, pool, rval));
   6815 
   6816     return BCM_E_NONE;
   6817 }
   6818 
   6819 STATIC int
   6820 _bcm_hx5_cosq_dynamic_thresh_enable_set(int unit,
   6821                         bcm_gport_t gport, bcm_cos_queue_t cosq,
   6822                         bcm_cosq_control_t type, int arg)
   6823 {
   6824     bcm_port_t local_port;
   6825     int startq, pipe;
   6826     int from_cos, to_cos, ci;
   6827     int midx;
   6828     uint32 rval;
   6829     uint32 entry[SOC_MAX_MEM_WORDS];
   6830     uint32 entry2[SOC_MAX_MEM_WORDS];
   6831     soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm;
   6832     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
   6833     soc_reg_t reg = INVALIDr;
   6834     int port_pg;
   6835     static const soc_reg_t prigroup_reg[] = {
   6836         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   6837     };
   6838     static const soc_field_t prigroup_field[] = {
   6839         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   6840         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   6841         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   6842         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   6843     };
   6844 
   6845     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
   6846         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6847             BCM_GPORT_IS_SCHEDULER(gport) ||
   6848             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6849             return BCM_E_PARAM;
   6850         }
   6851         BCM_IF_ERROR_RETURN
   6852             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6853         if (local_port < 0) {
   6854             return BCM_E_PORT;
   6855         }
   6856         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6857 
   6858         if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) {
   6859             /* Error. Input pri > Max Pri_Grp */
   6860             return BCM_E_PARAM;
   6861         }
   6862 
   6863         /* get PG for port using Port+Cos */
   6864         if (cosq < _HX5_MMU_NUM_PG) {
   6865             reg = prigroup_reg[0];
   6866         } else {
   6867             reg = prigroup_reg[1];
   6868         }
   6869 
   6870         SOC_IF_ERROR_RETURN
   6871             (soc_reg32_get(unit, reg, local_port, 0, &rval));
   6872         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
   6873         base_mem = THDI_PORT_PG_CONFIGm;
   6874         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6875         /* get index for Port-PG */
   6876         midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   6877         BCM_IF_ERROR_RETURN
   6878             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   6879         soc_mem_field32_set(unit, mem, entry,
   6880                             PG_SHARED_DYNAMICf, arg ? 1 : 0);
   6881         /* Set default alpha value*/
   6882         if (arg) {
   6883             soc_mem_field32_set(unit, mem, entry, PG_SHARED_LIMITf,
   6884                                 SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128);
   6885         }
   6886         SOC_IF_ERROR_RETURN
   6887             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   6888     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
   6889         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6890             BCM_IF_ERROR_RETURN
   6891                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   6892                                            _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6893                                            &local_port, &startq, NULL));
   6894         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6895             return BCM_E_PARAM;
   6896         } else {
   6897             if (cosq == BCM_COS_INVALID) {
   6898                 from_cos = to_cos = 0;
   6899             } else {
   6900                 from_cos = to_cos = cosq;
   6901             }
   6902 
   6903             BCM_IF_ERROR_RETURN
   6904                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6905             if (local_port < 0) {
   6906                 return BCM_E_PORT;
   6907             }
   6908             for (ci = from_cos; ci <= to_cos; ci++) {
   6909                 BCM_IF_ERROR_RETURN
   6910                     (_bcm_hx5_cosq_index_resolve(unit, local_port, ci,
   6911                                          _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   6912                                          NULL, &startq, NULL));
   6913 
   6914             }
   6915         }
   6916         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6917         base_mem = MMU_THDU_CONFIG_QUEUEm;
   6918         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6919 
   6920         BCM_IF_ERROR_RETURN
   6921             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6922         soc_mem_field32_set(unit, mem, entry,
   6923                             Q_LIMIT_DYNAMIC_CELLf, arg ? 1 : 0);
   6924         /* Set default alpha value*/
   6925         if (arg) {
   6926             soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHA_CELLf,
   6927                                 SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128);
   6928         }
   6929         SOC_IF_ERROR_RETURN
   6930             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6931     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
   6932         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6933             return BCM_E_PARAM;
   6934         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6935             BCM_IF_ERROR_RETURN
   6936                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   6937                                       _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   6938                                       &local_port, &startq, NULL));
   6939         }
   6940         else {
   6941             if (cosq == BCM_COS_INVALID) {
   6942                 from_cos = to_cos = 0;
   6943             } else {
   6944                 from_cos = to_cos = cosq;
   6945             }
   6946 
   6947             BCM_IF_ERROR_RETURN
   6948                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   6949             if (local_port < 0) {
   6950                 return BCM_E_PORT;
   6951             }
   6952             for (ci = from_cos; ci <= to_cos; ci++) {
   6953                 BCM_IF_ERROR_RETURN
   6954                     (_bcm_hx5_cosq_index_resolve(unit, local_port, ci,
   6955                                          _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   6956                                          NULL, &startq, NULL));
   6957 
   6958             }
   6959         }
   6960 
   6961         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6962         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
   6963         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   6964 
   6965         base_mem2 = MMU_THDM_MCQE_QUEUE_CONFIGm;
   6966         mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
   6967 
   6968         BCM_IF_ERROR_RETURN
   6969             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6970         soc_mem_field32_set(unit, mem, entry, Q_LIMIT_DYNAMICf, arg ? 1 : 0);
   6971         /* Set default alpha value*/
   6972         if (arg) {
   6973             soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf,
   6974                                 SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128);
   6975         }
   6976         SOC_IF_ERROR_RETURN
   6977             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   6978 
   6979         BCM_IF_ERROR_RETURN
   6980             (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   6981         soc_mem_field32_set(unit, mem2, entry2, Q_LIMIT_DYNAMICf, arg ? 1 : 0);
   6982         /* Set default alpha value*/
   6983         if (arg) {
   6984             soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf,
   6985                                 SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128);
   6986         }
   6987         SOC_IF_ERROR_RETURN
   6988             (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   6989 
   6990     } else {
   6991         return BCM_E_PARAM;
   6992     }
   6993 
   6994     return BCM_E_NONE;
   6995 }
   6996 
   6997 STATIC int
   6998 _bcm_hx5_cosq_dynamic_thresh_enable_get(int unit,
   6999                         bcm_gport_t gport, bcm_cos_queue_t cosq,
   7000                         bcm_cosq_control_t type, int *arg)
   7001 {
   7002     bcm_port_t local_port;
   7003     int startq, pipe, from_cos, to_cos, ci, midx, port_pg;
   7004     uint32 rval;
   7005     uint32 entry[SOC_MAX_MEM_WORDS];
   7006     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   7007     soc_reg_t reg = INVALIDr;
   7008     static const soc_reg_t prigroup_reg[] = {
   7009         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   7010     };
   7011     static const soc_field_t prigroup_field[] = {
   7012         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   7013         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   7014         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   7015         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   7016     };
   7017 
   7018     if (!arg) {
   7019         return BCM_E_PARAM;
   7020     }
   7021 
   7022     if (type == bcmCosqControlIngressPortPGSharedDynamicEnable) {
   7023         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   7024             BCM_GPORT_IS_SCHEDULER(gport) ||
   7025             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7026             return BCM_E_PARAM;
   7027         }
   7028         BCM_IF_ERROR_RETURN
   7029             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   7030         if (local_port < 0) {
   7031             return BCM_E_PORT;
   7032         }
   7033         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7034 
   7035         if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) {
   7036             /* Error. Input pri > Max Pri_Grp */
   7037             return BCM_E_PARAM;
   7038         }
   7039         /* get PG for port using Port+Cos */
   7040         if (cosq < _HX5_MMU_NUM_PG) {
   7041             reg = prigroup_reg[0];
   7042         } else {
   7043             reg = prigroup_reg[1];
   7044         }
   7045 
   7046         SOC_IF_ERROR_RETURN
   7047             (soc_reg32_get(unit, reg, local_port, 0, &rval));
   7048         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
   7049         base_mem = THDI_PORT_PG_CONFIGm;
   7050         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   7051         /* get index for Port-PG */
   7052         midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   7053 
   7054         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   7055                                  midx, entry));
   7056         *arg = soc_mem_field32_get(unit, mem, entry, PG_SHARED_DYNAMICf);
   7057 
   7058     } else if (type == bcmCosqControlEgressUCSharedDynamicEnable) {
   7059         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7060             BCM_IF_ERROR_RETURN
   7061                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   7062                                          _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7063                                          &local_port, &startq, NULL));
   7064         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7065             return BCM_E_PARAM;
   7066         } else {
   7067             if (cosq == BCM_COS_INVALID) {
   7068                 from_cos = to_cos = 0;
   7069             } else {
   7070                 from_cos = to_cos = cosq;
   7071             }
   7072 
   7073             BCM_IF_ERROR_RETURN
   7074                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   7075             if (local_port < 0) {
   7076                 return BCM_E_PORT;
   7077             }
   7078             for (ci = from_cos; ci <= to_cos; ci++) {
   7079                 BCM_IF_ERROR_RETURN
   7080                     (_bcm_hx5_cosq_index_resolve(unit, local_port, ci,
   7081                           _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7082                           NULL, &startq, NULL));
   7083             }
   7084         }
   7085         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7086         base_mem = MMU_THDU_CONFIG_QUEUEm;
   7087         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   7088 
   7089         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   7090                                  startq, entry));
   7091         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMIC_CELLf);
   7092     } else if (type == bcmCosqControlEgressMCSharedDynamicEnable) {
   7093         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7094             return BCM_E_PARAM;
   7095         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7096             BCM_IF_ERROR_RETURN
   7097                 (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   7098                                          _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   7099                                          &local_port, &startq, NULL));
   7100         }
   7101         else {
   7102             if (cosq == BCM_COS_INVALID) {
   7103                 from_cos = to_cos = 0;
   7104             } else {
   7105                 from_cos = to_cos = cosq;
   7106             }
   7107 
   7108             BCM_IF_ERROR_RETURN
   7109                 (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   7110             if (local_port < 0) {
   7111                 return BCM_E_PORT;
   7112             }
   7113             for (ci = from_cos; ci <= to_cos; ci++) {
   7114                 BCM_IF_ERROR_RETURN
   7115                     (_bcm_hx5_cosq_index_resolve(unit, local_port, ci,
   7116                                          _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   7117                                          NULL, &startq, NULL));
   7118             }
   7119         }
   7120         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7121         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
   7122         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   7123 
   7124         BCM_IF_ERROR_RETURN
   7125             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7126         *arg = soc_mem_field32_get(unit, mem, entry, Q_LIMIT_DYNAMICf);
   7127     } else {
   7128         return BCM_E_PARAM;
   7129     }
   7130 
   7131     return BCM_E_NONE;
   7132 }
   7133 
   7134 STATIC int
   7135 _bcm_hx5_cosq_alpha_set(int unit,
   7136                        bcm_gport_t gport, bcm_cos_queue_t cosq,
   7137                        bcm_cosq_control_drop_limit_alpha_value_t arg)
   7138 {
   7139     bcm_port_t local_port;
   7140     int startq, midx, pipe;
   7141     uint32 rval;
   7142     uint32 entry[SOC_MAX_MEM_WORDS];
   7143     uint32 entry2[SOC_MAX_MEM_WORDS];
   7144     soc_mem_t base_mem = INVALIDm, base_mem2 = INVALIDm;
   7145     soc_mem_t mem = INVALIDm, mem2 = INVALIDm;
   7146     int alpha, dynamic_thresh_mode, port_pg;
   7147     soc_reg_t reg = INVALIDr;
   7148     static const soc_reg_t prigroup_reg[] = {
   7149         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   7150     };
   7151     static const soc_field_t prigroup_field[] = {
   7152         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   7153         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   7154         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   7155         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   7156     };
   7157 
   7158     switch(arg) {
   7159     case bcmCosqControlDropLimitAlpha_1_128:
   7160         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128;
   7161         break;
   7162     case bcmCosqControlDropLimitAlpha_1_64:
   7163         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_64;
   7164         break;
   7165     case bcmCosqControlDropLimitAlpha_1_32:
   7166         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_32;
   7167         break;
   7168     case bcmCosqControlDropLimitAlpha_1_16:
   7169         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_16;
   7170         break;
   7171     case bcmCosqControlDropLimitAlpha_1_8:
   7172         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_8;
   7173         break;
   7174     case bcmCosqControlDropLimitAlpha_1_4:
   7175         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_4;
   7176         break;
   7177     case bcmCosqControlDropLimitAlpha_1_2:
   7178         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_2;
   7179         break;
   7180     case bcmCosqControlDropLimitAlpha_1:
   7181         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1;
   7182         break;
   7183     case bcmCosqControlDropLimitAlpha_2:
   7184         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_2;
   7185         break;
   7186     case bcmCosqControlDropLimitAlpha_4:
   7187         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_4;
   7188         break;
   7189     case bcmCosqControlDropLimitAlpha_8:
   7190         alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_8;
   7191         break;
   7192     default:
   7193         return BCM_E_PARAM;
   7194     }
   7195 
   7196     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7197         BCM_IF_ERROR_RETURN
   7198                 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
   7199                                    bcmCosqControlEgressUCSharedDynamicEnable,
   7200                                    &dynamic_thresh_mode));
   7201         if (!dynamic_thresh_mode){
   7202             return BCM_E_CONFIG;
   7203         }
   7204 
   7205         BCM_IF_ERROR_RETURN
   7206             (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   7207                                      _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7208                                      &local_port, &startq, NULL));
   7209         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7210 
   7211         base_mem = MMU_THDU_CONFIG_QUEUEm;
   7212         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   7213 
   7214         BCM_IF_ERROR_RETURN
   7215             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7216         soc_mem_field32_set(unit, mem, entry,
   7217                             Q_SHARED_ALPHA_CELLf, alpha);
   7218         SOC_IF_ERROR_RETURN
   7219             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7220     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7221         BCM_IF_ERROR_RETURN
   7222                 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
   7223                                    bcmCosqControlEgressMCSharedDynamicEnable,
   7224                                    &dynamic_thresh_mode));
   7225         if (!dynamic_thresh_mode){
   7226             return BCM_E_CONFIG;
   7227         }
   7228 
   7229         BCM_IF_ERROR_RETURN
   7230             (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   7231                                      _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   7232                                      &local_port, &startq, NULL));
   7233         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7234 
   7235         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
   7236         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   7237 
   7238         base_mem2 = MMU_THDM_MCQE_QUEUE_CONFIGm;
   7239         mem2 = SOC_MEM_UNIQUE_ACC(unit, base_mem2)[pipe];
   7240 
   7241         BCM_IF_ERROR_RETURN
   7242             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7243         soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHAf, alpha);
   7244         SOC_IF_ERROR_RETURN
   7245             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7246 
   7247         BCM_IF_ERROR_RETURN
   7248             (soc_mem_read(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   7249         soc_mem_field32_set(unit, mem2, entry2, Q_SHARED_ALPHAf, alpha);
   7250         SOC_IF_ERROR_RETURN
   7251             (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, startq, entry2));
   7252     } else {
   7253         BCM_IF_ERROR_RETURN
   7254                 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
   7255                                    bcmCosqControlIngressPortPGSharedDynamicEnable,
   7256                                    &dynamic_thresh_mode));
   7257         if (!dynamic_thresh_mode){
   7258             return BCM_E_CONFIG;
   7259         }
   7260 
   7261         BCM_IF_ERROR_RETURN
   7262             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   7263         if (local_port < 0) {
   7264             return BCM_E_PORT;
   7265         }
   7266         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7267 
   7268         if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) {
   7269             /* Error. Input pri > Max Pri_Grp */
   7270             return BCM_E_PARAM;
   7271         }
   7272         /* get PG for port using Port+Cos */
   7273         if (cosq < _HX5_MMU_NUM_PG) {
   7274             reg = prigroup_reg[0];
   7275         } else {
   7276             reg = prigroup_reg[1];
   7277         }
   7278 
   7279         SOC_IF_ERROR_RETURN
   7280             (soc_reg32_get(unit, reg, local_port, 0, &rval));
   7281         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
   7282         base_mem = THDI_PORT_PG_CONFIGm;
   7283         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   7284         /* get index for Port-PG */
   7285         midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   7286         BCM_IF_ERROR_RETURN
   7287             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   7288         soc_mem_field32_set(unit, mem, entry, PG_SHARED_LIMITf, alpha);
   7289         SOC_IF_ERROR_RETURN
   7290             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   7291     }
   7292 
   7293     return BCM_E_NONE;
   7294 }
   7295 
   7296 
   7297 STATIC int
   7298 _bcm_hx5_cosq_alpha_get(int unit,
   7299                         bcm_gport_t gport, bcm_cos_queue_t cosq,
   7300                         bcm_cosq_control_drop_limit_alpha_value_t *arg)
   7301 {
   7302     bcm_port_t local_port;
   7303     int startq, midx, pipe;
   7304     uint32 rval;
   7305     uint32 entry[SOC_MAX_MEM_WORDS];
   7306     soc_mem_t mem = INVALIDm, base_mem = INVALIDm;
   7307     int alpha, dynamic_thresh_mode, port_pg;
   7308     soc_reg_t reg = INVALIDr;
   7309     static const soc_reg_t prigroup_reg[] = {
   7310         THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r
   7311     };
   7312     static const soc_field_t prigroup_field[] = {
   7313         PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf,
   7314         PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf,
   7315         PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf,
   7316         PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf
   7317     };
   7318 
   7319     if (!arg) {
   7320         return BCM_E_PARAM;
   7321     }
   7322 
   7323     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7324         BCM_IF_ERROR_RETURN
   7325                 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
   7326                                    bcmCosqControlEgressUCSharedDynamicEnable,
   7327                                    &dynamic_thresh_mode));
   7328         if (!dynamic_thresh_mode){
   7329             return BCM_E_CONFIG;
   7330         }
   7331 
   7332         BCM_IF_ERROR_RETURN
   7333             (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   7334                                      _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
   7335                                      &local_port, &startq, NULL));
   7336         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7337 
   7338         base_mem = MMU_THDU_CONFIG_QUEUEm;
   7339         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   7340 
   7341         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   7342                                  startq, entry));
   7343         alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf);
   7344 
   7345     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7346         BCM_IF_ERROR_RETURN
   7347                 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
   7348                                    bcmCosqControlEgressMCSharedDynamicEnable,
   7349                                    &dynamic_thresh_mode));
   7350         if (!dynamic_thresh_mode){
   7351             return BCM_E_CONFIG;
   7352         }
   7353 
   7354         BCM_IF_ERROR_RETURN
   7355             (_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   7356                                      _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
   7357                                      &local_port, &startq, NULL));
   7358         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7359 
   7360         base_mem = MMU_THDM_DB_QUEUE_CONFIGm;
   7361         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   7362         BCM_IF_ERROR_RETURN
   7363             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   7364         alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHAf);
   7365 
   7366     } else {
   7367         BCM_IF_ERROR_RETURN
   7368                 (_bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
   7369                                    bcmCosqControlIngressPortPGSharedDynamicEnable,
   7370                                    &dynamic_thresh_mode));
   7371         if (!dynamic_thresh_mode){
   7372             return BCM_E_CONFIG;
   7373         }
   7374 
   7375         BCM_IF_ERROR_RETURN
   7376             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   7377         if (local_port < 0) {
   7378             return BCM_E_PORT;
   7379         }
   7380 
   7381         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7382 
   7383         if ((cosq < 0) || (cosq >= _HX5_MMU_NUM_INT_PRI)) {
   7384             /* Error. Input pri > Max Pri_Grp */
   7385             return BCM_E_PARAM;
   7386         }
   7387         /* get PG for port using Port+Cos */
   7388         if (cosq < _HX5_MMU_NUM_PG) {
   7389             reg = prigroup_reg[0];
   7390         } else {
   7391             reg = prigroup_reg[1];
   7392         }
   7393 
   7394         SOC_IF_ERROR_RETURN
   7395             (soc_reg32_get(unit, reg, local_port, 0, &rval));
   7396         port_pg = soc_reg_field_get(unit, reg, rval, prigroup_field[cosq]);
   7397 
   7398         base_mem = THDI_PORT_PG_CONFIGm;
   7399         mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   7400         /* get index for Port-PG */
   7401         midx = SOC_TD3_MMU_PIPED_MEM_INDEX(unit, local_port, base_mem, port_pg);
   7402 
   7403         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   7404                                  midx, entry));
   7405         alpha = soc_mem_field32_get(unit, mem, entry, PG_SHARED_LIMITf);
   7406 
   7407     }
   7408 
   7409     switch(alpha) {
   7410     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128:
   7411         *arg = bcmCosqControlDropLimitAlpha_1_128;
   7412         break;
   7413     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_64:
   7414         *arg = bcmCosqControlDropLimitAlpha_1_64;
   7415         break;
   7416     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_32:
   7417         *arg = bcmCosqControlDropLimitAlpha_1_32;
   7418         break;
   7419     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_16:
   7420         *arg = bcmCosqControlDropLimitAlpha_1_16;
   7421         break;
   7422     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_8:
   7423         *arg = bcmCosqControlDropLimitAlpha_1_8;
   7424         break;
   7425     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_4:
   7426         *arg = bcmCosqControlDropLimitAlpha_1_4;
   7427         break;
   7428     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_2:
   7429         *arg = bcmCosqControlDropLimitAlpha_1_2;
   7430         break;
   7431     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1:
   7432         *arg = bcmCosqControlDropLimitAlpha_1;
   7433         break;
   7434     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_2:
   7435         *arg = bcmCosqControlDropLimitAlpha_2;
   7436         break;
   7437     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_4:
   7438         *arg = bcmCosqControlDropLimitAlpha_4;
   7439         break;
   7440     case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_8:
   7441         *arg = bcmCosqControlDropLimitAlpha_8;
   7442         break;
   7443     default:
   7444         return BCM_E_PARAM;
   7445     }
   7446 
   7447     return BCM_E_NONE;
   7448 }
   7449 
   7450 STATIC int
   7451 _bcm_hx5_cosq_time_domain_get(int unit, int time_id, int *time_value)
   7452 {
   7453     uint32 time_domain_val;
   7454     soc_reg_t time_domain_reg = TIME_DOMAINr;
   7455 
   7456     if (time_id < 0 || time_id > _BCM_HX5_NUM_TIME_DOMAIN - 1) {
   7457         return SOC_E_PARAM;
   7458     }
   7459 
   7460     if (time_value == NULL) {
   7461         return SOC_E_PARAM;
   7462     }
   7463 
   7464     BCM_IF_ERROR_RETURN(
   7465         soc_reg32_get(unit, time_domain_reg, REG_PORT_ANY, time_id, &time_domain_val));
   7466     *time_value = soc_reg_field_get(unit, time_domain_reg,
   7467                                    time_domain_val, TIME_DOMAIN_FIELDf);
   7468     return SOC_E_NONE;
   7469 }
   7470 
   7471 STATIC int
   7472 _bcm_hx5_cosq_time_domain_set(int unit, int time_value, int *time_id)
   7473 {
   7474     int id;
   7475     uint32 time_domain_val;
   7476     soc_reg_t time_domain_reg = TIME_DOMAINr;
   7477 
   7478     if (time_value < 0 || time_value > 63) {
   7479         return SOC_E_PARAM;
   7480     }
   7481 
   7482     for (id = 0; id < _BCM_HX5_NUM_TIME_DOMAIN; id++) {
   7483         BCM_IF_ERROR_RETURN(
   7484             soc_reg32_get(unit, time_domain_reg, REG_PORT_ANY, id, &time_domain_val));
   7485         if (!hx5_time_domain_info[unit][id].ref_count) {
   7486             soc_reg_field_set(unit, time_domain_reg, &time_domain_val,
   7487                               TIME_DOMAIN_FIELDf, time_value);
   7488             hx5_time_domain_info[unit][id].ref_count++;
   7489             break;
   7490         }
   7491     }
   7492 
   7493     if (id == _BCM_HX5_NUM_TIME_DOMAIN) {
   7494         return BCM_E_RESOURCE;
   7495     }
   7496 
   7497     if (time_id) {
   7498         *time_id = id;
   7499     }
   7500     SOC_IF_ERROR_RETURN(
   7501         soc_reg32_set(unit, time_domain_reg, REG_PORT_ANY, id, time_domain_val));
   7502     return SOC_E_NONE;
   7503 }
   7504 
   7505 /*
   7506  * Function:
   7507  *     bcm_hx5_cosq_wred_resolution_entry_create
   7508  * Purpose:
   7509  *     Assign a unused entry. Default drop rules are WRED drop.
   7510  * Parameters:
   7511  *     unit                - (IN) unit number
   7512  *     index               - (OUT) entry index
   7513  * Returns:
   7514  *     BCM_E_XXX
   7515  */
   7516 int
   7517 bcm_hx5_cosq_wred_resolution_entry_create(int unit, int *index)
   7518 {
   7519     uint32 i, rval = 0;
   7520     soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   7521 
   7522     for (i = 0; i < _BCM_HX5_NUM_WRED_RESOLUTION_TABLE; i++) {
   7523         if (_bcm_hx5_wred_resolution_tbl[i] == 0) {
   7524             /* hw reset value */
   7525             soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, 0xAAA);
   7526             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, i, rval));
   7527             _bcm_hx5_wred_resolution_tbl[i]++;
   7528             *index = i;
   7529             return BCM_E_NONE;
   7530         }
   7531     }
   7532 
   7533     return BCM_E_RESOURCE;
   7534 }
   7535 
   7536 /*
   7537  * Function:
   7538  *     bcm_hx5_cosq_wred_resolution_entry_destroy
   7539  * Purpose:
   7540  *     Callback an entry and set its drop rules to WRED drop.
   7541  * Parameters:
   7542  *     unit                - (IN) unit number
   7543  *     index               - (IN) entry index
   7544  * Returns:
   7545  *     BCM_E_XXX
   7546  */
   7547 int
   7548 bcm_hx5_cosq_wred_resolution_entry_destroy(int unit, int index)
   7549 {
   7550     uint32 rval = 0;
   7551     soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   7552 
   7553     if ((index < 0) || (index >= _BCM_HX5_NUM_WRED_RESOLUTION_TABLE)) {
   7554         return BCM_E_PARAM;
   7555     }
   7556 
   7557     if (_bcm_hx5_wred_resolution_tbl[index] == 0) {
   7558         return BCM_E_NOT_FOUND;
   7559     }
   7560 
   7561     /* hw reset value */
   7562     soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, 0xAAA);
   7563     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval));
   7564     _bcm_hx5_wred_resolution_tbl[index] = 0;
   7565 
   7566     return BCM_E_NONE;
   7567 }
   7568 
   7569 /*
   7570  * Function:
   7571  *     bcm_hx5_cosq_wred_resolution_set
   7572  * Purpose:
   7573  *     Set one rule of a resolution table entry
   7574  * Parameters:
   7575  *     unit                - (IN) unit number
   7576  *     index               - (IN) entry index
   7577  *     rule                - (IN) drop rule
   7578  * Returns:
   7579  *     BCM_E_XXX
   7580  * Notes:
   7581  *     One entry has 12 bits, equals to 6 rules
   7582  */
   7583 int
   7584 bcm_hx5_cosq_wred_resolution_set(int unit, int index, bcm_cosq_discard_rule_t *rule)
   7585 {
   7586     uint32 offset, sp, qmin;
   7587     uint32 rval, fval, drop;
   7588     soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   7589 
   7590     if ((index < 0) || (index >= _BCM_HX5_NUM_WRED_RESOLUTION_TABLE)) {
   7591         return BCM_E_PARAM;
   7592     }
   7593 
   7594     if (_bcm_hx5_wred_resolution_tbl[index] == 0) {
   7595         return BCM_E_NOT_FOUND;
   7596     }
   7597 
   7598     switch (rule->egress_pool_congestion_state) {
   7599         case BCM_COSQ_DISCARD_CONGESTION_LOW:
   7600             sp = 0;
   7601             break;
   7602         case BCM_COSQ_DISCARD_CONGESTION_MEDIUM:
   7603             sp = 1;
   7604             break;
   7605         case BCM_COSQ_DISCARD_CONGESTION_HIGH:
   7606             sp = 2;
   7607             break;
   7608         default:
   7609             return BCM_E_PARAM;
   7610     }
   7611 
   7612     switch (rule->queue_min_congestion_state) {
   7613         case BCM_COSQ_DISCARD_CONGESTION_LOW:
   7614             qmin = 0;
   7615             break;
   7616         case BCM_COSQ_DISCARD_CONGESTION_HIGH:
   7617             qmin = 1;
   7618             break;
   7619         default:
   7620             return BCM_E_PARAM;
   7621     }
   7622 
   7623     switch (rule->action) {
   7624         case BCM_COSQ_DISCARD_ACTION_WRED_DROP:
   7625             drop = 0x2;
   7626             break;
   7627         case BCM_COSQ_DISCARD_ACTION_FORCE_DROP:
   7628             drop = 0x3;
   7629             break;
   7630         case BCM_COSQ_DISCARD_ACTION_FORCE_NO_DROP:
   7631             drop = 0x0;
   7632             break;
   7633         default:
   7634             return BCM_E_PARAM;
   7635     }
   7636 
   7637     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval));
   7638     fval = soc_reg_field_get(unit, reg, rval, MMU_CONGESTION_EXPERIENCEf);
   7639 
   7640     offset = (sp * 2 + qmin) * 2;       /* 2 bits per rule */
   7641     fval = (fval & (~(0x3 << offset))) | (drop << offset);
   7642 
   7643     soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, fval);
   7644     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval));
   7645 
   7646     return BCM_E_NONE;
   7647 }
   7648 
   7649 /*
   7650  * Function:
   7651  *     bcm_hx5_cosq_wred_resolution_get
   7652  * Purpose:
   7653  *     Get all rules of a resolution table entry
   7654  * Parameters:
   7655  *     unit                - (IN) unit number
   7656  *     index               - (IN) entry index
   7657  *     max                 - (IN) rule array size
   7658  *     rule                - (OUT) rule array
   7659  *     count               - (OUT) actual rules count
   7660  * Returns:
   7661  *     BCM_E_XXX
   7662  * Notes:
   7663  *     One entry has 12 bits, equals to 6 rules
   7664  */
   7665 int
   7666 bcm_hx5_cosq_wred_resolution_get(int unit, int index, int max,
   7667                                  bcm_cosq_discard_rule_t *rule, int *count)
   7668 {
   7669     uint32 offset, sp, qmin, i = 0;
   7670     uint32 rval, fval, action;
   7671     soc_reg_t reg = WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   7672     uint32 sp_map[3] = {
   7673         BCM_COSQ_DISCARD_CONGESTION_LOW,
   7674         BCM_COSQ_DISCARD_CONGESTION_MEDIUM,
   7675         BCM_COSQ_DISCARD_CONGESTION_HIGH,
   7676     };
   7677     uint32 qmin_map[2] = {
   7678         BCM_COSQ_DISCARD_CONGESTION_LOW,
   7679         BCM_COSQ_DISCARD_CONGESTION_HIGH,
   7680     };
   7681     uint32 action_map[4] = {
   7682         BCM_COSQ_DISCARD_ACTION_FORCE_NO_DROP,
   7683         -1,
   7684         BCM_COSQ_DISCARD_ACTION_WRED_DROP,
   7685         BCM_COSQ_DISCARD_ACTION_FORCE_DROP,
   7686     };
   7687 
   7688     if ((!count) ||
   7689         (index < 0) || (index >= _BCM_HX5_NUM_WRED_RESOLUTION_TABLE)) {
   7690         return BCM_E_PARAM;
   7691     }
   7692 
   7693     *count = 3 * 2;
   7694 
   7695     if (!rule) {
   7696         return BCM_E_NONE;
   7697     }
   7698 
   7699     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval));
   7700     fval = soc_reg_field_get(unit, reg, rval, MMU_CONGESTION_EXPERIENCEf);
   7701 
   7702     for (sp = 0; sp < 3; sp ++) {
   7703         for (qmin = 0; qmin < 2; qmin++) {
   7704             offset = (sp * 2 + qmin) * 2;       /* 2 bits per rule */
   7705             action = (fval >> offset) & 0x3;
   7706             if (i < max) {
   7707                 rule[i].egress_pool_congestion_state = sp_map[sp];
   7708                 rule[i].queue_min_congestion_state = qmin_map[qmin];
   7709                 rule[i].action = action_map[action];
   7710                 i++;
   7711             }
   7712         }
   7713     }
   7714 
   7715     return BCM_E_NONE;
   7716 }
   7717 
   7718 STATIC int
   7719 _bcm_hx5_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   7720                       uint32 flags, uint32 min_thresh, uint32 max_thresh,
   7721                       int drop_probability, int gain, int ignore_enable_flags,
   7722                       uint32 lflags,  int refresh_time, uint32 resolution_id,
   7723                       uint32 use_queue_group)
   7724 {
   7725     /* Local Variables */
   7726     soc_mem_t wred_config_mem = INVALIDm;
   7727     bcm_port_t local_port = -1;
   7728     int index, i, start_index, end_index, count = 0;
   7729     int end_offset, need_profile = 0, pipe;
   7730     uint32 profile_index, old_profile_index;
   7731     uint32 wred_flags = 0;
   7732     void *entries[9];
   7733     soc_mem_t mems[9];
   7734     static soc_mem_t wred_mems[9] = {
   7735         MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m,
   7736         MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m,
   7737         MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m,
   7738         MMU_WRED_DROP_CURVE_PROFILE_6m, MMU_WRED_DROP_CURVE_PROFILE_7m,
   7739         MMU_WRED_DROP_CURVE_PROFILE_8m
   7740     };
   7741     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   7742     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   7743     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   7744     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   7745     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   7746     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   7747     mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green;
   7748     mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow;
   7749     mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red;
   7750     mmu_wred_config_entry_t entry;
   7751     int rate = 0;
   7752     int from_pipe, to_pipe;
   7753     int time_id,time,old_time,current_time_sel;
   7754     int rv = SOC_E_NONE, exists = 0;
   7755 
   7756     wred_flags = flags | lflags;
   7757     end_offset = 0;
   7758 
   7759     /* Check Flags for WRED res level - Device-SP/Port-SP/Queues */
   7760     if ((wred_flags & BCM_COSQ_DISCARD_DEVICE) && (port == BCM_GPORT_INVALID)) {
   7761         /* (Port == -1) For all Global SPs */
   7762         index = _HX5_WRED_PER_PIPE_GLOBAL_SP_BASE;
   7763         count = _HX5_MMU_NUM_POOL;
   7764         /*For all pipe*/
   7765         from_pipe = 0;
   7766         to_pipe = NUM_PIPE(unit) - 1;
   7767 
   7768     } else {
   7769         BCM_IF_ERROR_RETURN
   7770             (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
   7771         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7772         from_pipe = to_pipe = pipe;
   7773 
   7774         if (wred_flags & BCM_COSQ_DISCARD_DEVICE) {
   7775             BCM_IF_ERROR_RETURN
   7776                 (_bcm_hx5_cosq_index_resolve(unit, port, cosq,
   7777                                             _BCM_HX5_COSQ_INDEX_STYLE_WRED_DEVICE,
   7778                                             NULL, &index, &count));
   7779             /* (cosq == -1) For all Global SPs */
   7780         } else if (wred_flags & BCM_COSQ_DISCARD_PORT) {
   7781             /* Port SP - Given or all SPs of the port */
   7782             BCM_IF_ERROR_RETURN
   7783                 (_bcm_hx5_cosq_index_resolve(unit, port, cosq,
   7784                                             _BCM_HX5_COSQ_INDEX_STYLE_WRED_PORT,
   7785                                             NULL, &index, &count));
   7786             /* (cosq == -1) For all SPs of the given port */
   7787         } else {
   7788             /* Per Queue WRED settings */
   7789             BCM_IF_ERROR_RETURN
   7790                 (_bcm_hx5_cosq_index_resolve(unit, port, cosq,
   7791                                             _BCM_HX5_COSQ_INDEX_STYLE_WRED_QUEUE,
   7792                                             NULL, &index, &count));
   7793             /* (cosq == -1) For all Queues of the given port */
   7794         }
   7795     }
   7796 
   7797 
   7798     end_offset = (count > 0) ? (count - 1) : 0;
   7799 
   7800     if (index < 0) {
   7801         return BCM_E_PARAM;
   7802     }
   7803 
   7804     if (refresh_time < 1) {
   7805         return BCM_E_PARAM;
   7806     }
   7807 
   7808     start_index = index;
   7809     end_index = start_index + end_offset;
   7810 
   7811     rate = _bcm_hx5_percent_to_drop_prob(drop_probability);
   7812 
   7813     for (pipe = from_pipe; pipe <= to_pipe; pipe++ ) {
   7814         /* Config MMU_WRED_CONFIGm for the respective resource */
   7815         wred_config_mem = MMU_WRED_CONFIGm;
   7816         wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, wred_config_mem)[pipe];
   7817         if (wred_config_mem == INVALIDm) {
   7818             return BCM_E_PARAM;
   7819         }
   7820 
   7821         for (i=0; i < 9; i++) {
   7822             mems[i] = INVALIDm;
   7823         }
   7824 
   7825         if (wred_flags & (BCM_COSQ_DISCARD_COLOR_ALL |
   7826                           BCM_COSQ_DISCARD_TCP |
   7827                           BCM_COSQ_DISCARD_NONTCP |
   7828                           BCM_COSQ_DISCARD_ECT_MARKED |
   7829                           BCM_COSQ_DISCARD_RESPONSIVE_DROP |
   7830                           BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) {
   7831             need_profile = 1;
   7832 
   7833             if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN |
   7834                            BCM_COSQ_DISCARD_COLOR_YELLOW |
   7835                            BCM_COSQ_DISCARD_COLOR_RED))) {
   7836                 flags |= BCM_COSQ_DISCARD_COLOR_ALL;
   7837             }
   7838 
   7839             if (!(wred_flags & (BCM_COSQ_DISCARD_NONTCP |
   7840                                 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP |
   7841                                 BCM_COSQ_DISCARD_ECT_MARKED)) ||
   7842                  ((wred_flags & BCM_COSQ_DISCARD_TCP) ||
   7843                  (wred_flags & BCM_COSQ_DISCARD_RESPONSIVE_DROP))) {
   7844                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   7845                     mems[0] = wred_mems[0];
   7846                 }
   7847                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   7848                     mems[1] = wred_mems[1];
   7849                 }
   7850                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   7851                     mems[2] = wred_mems[2];
   7852                 }
   7853             }
   7854             if ((wred_flags & BCM_COSQ_DISCARD_NONTCP) ||
   7855                 (wred_flags & BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)){
   7856                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   7857                     mems[3] = wred_mems[3];
   7858                 }
   7859                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   7860                     mems[4] = wred_mems[4];
   7861                 }
   7862                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   7863                     mems[5] = wred_mems[5];
   7864                 }
   7865             }
   7866             if (wred_flags & BCM_COSQ_DISCARD_ECT_MARKED) {
   7867                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   7868                     mems[6] = wred_mems[6];
   7869                 }
   7870                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   7871                     mems[7] = wred_mems[7];
   7872                 }
   7873                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   7874                     mems[8] = wred_mems[8];
   7875                 }
   7876             }
   7877         }
   7878 
   7879         entries[0] = &entry_tcp_green;
   7880         entries[1] = &entry_tcp_yellow;
   7881         entries[2] = &entry_tcp_red;
   7882         entries[3] = &entry_nontcp_green;
   7883         entries[4] = &entry_nontcp_yellow;
   7884         entries[5] = &entry_nontcp_red;
   7885         entries[6] = &entry_ecn_green;
   7886         entries[7] = &entry_ecn_yellow;
   7887         entries[8] = &entry_ecn_red;
   7888 
   7889         for (index = start_index; index <= end_index; index++) {
   7890             old_profile_index = 0xffffffff;
   7891             BCM_IF_ERROR_RETURN
   7892                 (soc_mem_read(unit, wred_config_mem, MEM_BLOCK_ALL, index, &entry));
   7893 
   7894             if (need_profile) {
   7895                 old_profile_index = soc_mem_field32_get(unit, wred_config_mem,
   7896                                                         &entry, PROFILE_INDEXf);
   7897 
   7898                 BCM_IF_ERROR_RETURN
   7899                     (soc_profile_mem_get(unit, _bcm_hx5_wred_profile[unit],
   7900                                          old_profile_index, 1, entries));
   7901 
   7902                 for (i = 0; i < HX5_WRED_PROFILE_NUM; i++) {
   7903                     if (mems[i] == INVALIDm) {
   7904                         continue;
   7905                     }
   7906                     soc_mem_field32_set(unit, wred_mems[i], entries[i],
   7907                                         MIN_THDf, min_thresh);
   7908                     soc_mem_field32_set(unit, wred_mems[i], entries[i],
   7909                                         MAX_THDf, max_thresh);
   7910                     soc_mem_field32_set(unit, wred_mems[i], entries[i],
   7911                                         MAX_DROP_RATEf, rate);
   7912                 }
   7913                 BCM_IF_ERROR_RETURN
   7914                     (soc_profile_mem_add(unit, _bcm_hx5_wred_profile[unit],
   7915                                          entries, 1, &profile_index));
   7916                 soc_mem_field32_set(unit, wred_config_mem, &entry, PROFILE_INDEXf, profile_index);
   7917             }
   7918                 soc_mem_field32_set(unit, wred_config_mem, &entry, WEIGHTf, gain);
   7919 
   7920             /* Some APIs only modify profiles */
   7921             if (!ignore_enable_flags) {
   7922                 soc_mem_field32_set(unit, wred_config_mem, &entry, CAP_AVERAGEf,
   7923                                     flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   7924                 soc_mem_field32_set(unit, wred_config_mem, &entry, WRED_ENf,
   7925                                     flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   7926                 soc_mem_field32_set(unit, wred_config_mem, &entry, ECN_MARKING_ENf,
   7927                                     flags & BCM_COSQ_DISCARD_MARK_CONGESTION ?  1 : 0);
   7928             }
   7929 
   7930             current_time_sel = soc_mem_field32_get(unit, wred_config_mem,
   7931                                                    &entry, TIME_DOMAIN_SELf);
   7932             time = refresh_time - 1;
   7933             exists = 0;
   7934             /* If the time value exist, update reference count only */
   7935             for (time_id = 0; time_id < _BCM_HX5_NUM_TIME_DOMAIN; time_id++) {
   7936                 BCM_IF_ERROR_RETURN
   7937                     (_bcm_hx5_cosq_time_domain_get(unit, time_id, &old_time));
   7938                 if (time == old_time) {
   7939                     /* Only set exist flag if this entry reference count already update,
   7940                                   otherwise update reference count */
   7941                     if(time_id != current_time_sel){
   7942                         soc_mem_field32_set(unit, wred_config_mem, &entry,
   7943                                             TIME_DOMAIN_SELf, time_id);
   7944                         hx5_time_domain_info[unit][time_id].ref_count++;
   7945                         hx5_time_domain_info[unit][current_time_sel].ref_count--;
   7946                     }
   7947                     exists = 1;
   7948                     break;
   7949                 }
   7950             }
   7951 
   7952             if(!exists){
   7953                 rv = _bcm_hx5_cosq_time_domain_set(unit, time, &time_id);
   7954                 if(rv == SOC_E_NONE){
   7955                     soc_mem_field32_set(unit, wred_config_mem, &entry,
   7956                                         TIME_DOMAIN_SELf, time_id);
   7957                     hx5_time_domain_info[unit][current_time_sel].ref_count--;
   7958                 } else {
   7959                     return rv;
   7960                 }
   7961             }
   7962 
   7963             soc_mem_field32_set(unit, wred_config_mem, &entry, QG_ENf,
   7964                                 use_queue_group ? 1 : 0);
   7965             if (flags & BCM_COSQ_DISCARD_MARK_CONGESTION) {
   7966                 soc_mem_field32_set(unit, wred_config_mem, &entry,
   7967                     WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf,
   7968                     resolution_id);
   7969             } else {
   7970                 soc_mem_field32_set(unit, wred_config_mem, &entry,
   7971                     WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf,
   7972                     resolution_id);
   7973             }
   7974 
   7975 
   7976             BCM_IF_ERROR_RETURN(
   7977                     soc_mem_write(unit, wred_config_mem, MEM_BLOCK_ALL, index, &entry));
   7978 
   7979             if (old_profile_index != 0xffffffff) {
   7980                 SOC_IF_ERROR_RETURN
   7981                     (soc_profile_mem_delete(unit, _bcm_hx5_wred_profile[unit],
   7982                                             old_profile_index));
   7983             }
   7984 
   7985         }
   7986 
   7987     }
   7988 
   7989     /* Check Flags for WRED profile based on Color */
   7990     return BCM_E_NONE;
   7991 }
   7992 
   7993 /*
   7994  * Function:
   7995  *     _bcm_hx5_cosq_wred_get
   7996  * Purpose:
   7997  *     Configure unicast queue WRED setting
   7998  * Parameters:
   7999  *     unit                - (IN) unit number
   8000  *     port                - (IN) port number or GPORT identifier
   8001  *     cosq                - (IN) COS queue number
   8002  *     flags               - (IN/OUT) BCM_COSQ_DISCARD_XXX
   8003  *     min_thresh          - (OUT) Min Threshold
   8004  *     max_thresh          - (OUT) Max Threshold
   8005  *     drop_probablity     - (OUT) Probabilistic drop rate
   8006  *     gain                - (OUT)
   8007  *     lflags              - (IN) Config flags
   8008  *     refresh_time        - (OUT) Time Domain
   8009  *     resolution_id       - (OUT) Resolution index
   8010  *     use_queue_group     - (OUT) Queue group status is used
   8011  * Returns:
   8012  *     BCM_E_XXX
   8013  * Notes:
   8014  *     If port is any form of local port, cosq is the hardware queue index.
   8015  */
   8016 STATIC int
   8017 _bcm_hx5_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8018                       uint32 *flags, uint32 *min_thresh, uint32 *max_thresh,
   8019                       int *drop_probability, int *gain, uint32 lflags,
   8020                       int *refresh_time, uint32 *resolution_id,
   8021                       uint32 *use_queue_group)
   8022 {
   8023     soc_mem_t wred_config_mem = INVALIDm, mem = INVALIDm;
   8024     bcm_port_t local_port = -1;
   8025     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   8026     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   8027     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   8028     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   8029     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   8030     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   8031     mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green;
   8032     mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow;
   8033     mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red;
   8034     void *entries[9];
   8035     void *entry_p;
   8036     int index, profile_index;
   8037     mmu_wred_config_entry_t entry;
   8038     uint32 wred_flags = 0;
   8039     int rate = 0, pipe = -1;
   8040     int time_id, time;
   8041 
   8042     if (flags) {
   8043         wred_flags = *flags | lflags;
   8044     } else {
   8045         wred_flags = lflags;
   8046     }
   8047 
   8048     if ((wred_flags & BCM_COSQ_DISCARD_DEVICE) && (port == BCM_GPORT_INVALID)) {
   8049         /* (Port == -1) For all Global SPs */
   8050         index = _HX5_WRED_PER_PIPE_GLOBAL_SP_BASE;
   8051         pipe = 0;
   8052 
   8053     } else {
   8054         BCM_IF_ERROR_RETURN
   8055             (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
   8056         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8057 
   8058         /* Check Flags for WRED res level - Device-SP/Port-SP/Queues */
   8059         if(wred_flags & BCM_COSQ_DISCARD_DEVICE) {
   8060             BCM_IF_ERROR_RETURN
   8061                 (_bcm_hx5_cosq_index_resolve(unit, port, cosq,
   8062                                         _BCM_HX5_COSQ_INDEX_STYLE_WRED_DEVICE,
   8063                                         NULL, &index, NULL));
   8064         } else if (wred_flags & BCM_COSQ_DISCARD_PORT) {
   8065             /* Port SP - Given or all SPs of the port */
   8066             BCM_IF_ERROR_RETURN
   8067                 (_bcm_hx5_cosq_index_resolve(unit, port, cosq,
   8068                                             _BCM_HX5_COSQ_INDEX_STYLE_WRED_PORT,
   8069                                             NULL, &index, NULL));
   8070         } else {
   8071             /* Per Queue WRED settings */
   8072             BCM_IF_ERROR_RETURN
   8073                 (_bcm_hx5_cosq_index_resolve(unit, port, cosq,
   8074                                             _BCM_HX5_COSQ_INDEX_STYLE_WRED_QUEUE,
   8075                                             NULL, &index, NULL));
   8076         }
   8077     }
   8078 
   8079     if ((index < 0) || (pipe == -1)) {
   8080         return BCM_E_PARAM;
   8081     }
   8082 
   8083     wred_config_mem = MMU_WRED_CONFIGm;
   8084     wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, wred_config_mem)[pipe];
   8085     if (wred_config_mem == INVALIDm) {
   8086         return BCM_E_PARAM;
   8087     }
   8088 
   8089     BCM_IF_ERROR_RETURN
   8090         (soc_mem_read(unit, wred_config_mem, MEM_BLOCK_ALL, index, &entry));
   8091     profile_index = soc_mem_field32_get(unit, wred_config_mem,
   8092                                         &entry, PROFILE_INDEXf);
   8093 
   8094     if (!(wred_flags & (BCM_COSQ_DISCARD_NONTCP |
   8095                         BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP |
   8096                         BCM_COSQ_DISCARD_ECT_MARKED))) {
   8097         /* By default we will assume
   8098            BCM_COSQ_DISCARD_TCP */
   8099         if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   8100             mem = MMU_WRED_DROP_CURVE_PROFILE_1m;
   8101             entry_p = &entry_tcp_yellow;
   8102         } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) {
   8103             mem = MMU_WRED_DROP_CURVE_PROFILE_2m;
   8104             entry_p = &entry_tcp_red;
   8105         } else {
   8106             /* By default we will assume
   8107                BCM_COSQ_DISCARD_COLOR_GREEN */
   8108             mem = MMU_WRED_DROP_CURVE_PROFILE_0m;
   8109             entry_p = &entry_tcp_green;
   8110         }
   8111     } else if ((wred_flags & BCM_COSQ_DISCARD_NONTCP) ||
   8112                (wred_flags & BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) {
   8113         if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   8114             mem = MMU_WRED_DROP_CURVE_PROFILE_4m;
   8115             entry_p = &entry_nontcp_yellow;
   8116         } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) {
   8117             mem = MMU_WRED_DROP_CURVE_PROFILE_5m;
   8118             entry_p = &entry_nontcp_red;
   8119         } else {
   8120             /* By default we will assume
   8121                BCM_COSQ_DISCARD_COLOR_GREEN */
   8122             mem = MMU_WRED_DROP_CURVE_PROFILE_3m;
   8123             entry_p = &entry_nontcp_green;
   8124         }
   8125     } else {
   8126         if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   8127             mem = MMU_WRED_DROP_CURVE_PROFILE_7m;
   8128             entry_p = &entry_ecn_yellow;
   8129         } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) {
   8130             mem = MMU_WRED_DROP_CURVE_PROFILE_8m;
   8131             entry_p = &entry_ecn_red;
   8132         } else {
   8133             /* By default we will assume
   8134                BCM_COSQ_DISCARD_COLOR_GREEN */
   8135             mem = MMU_WRED_DROP_CURVE_PROFILE_6m;
   8136             entry_p = &entry_ecn_green;
   8137         }
   8138     }
   8139 
   8140     entries[0] = &entry_tcp_green;
   8141     entries[1] = &entry_tcp_yellow;
   8142     entries[2] = &entry_tcp_red;
   8143     entries[3] = &entry_nontcp_green;
   8144     entries[4] = &entry_nontcp_yellow;
   8145     entries[5] = &entry_nontcp_red;
   8146     entries[6] = &entry_ecn_green;
   8147     entries[7] = &entry_ecn_yellow;
   8148     entries[8] = &entry_ecn_red;
   8149 
   8150     BCM_IF_ERROR_RETURN
   8151         (soc_profile_mem_get(unit, _bcm_hx5_wred_profile[unit],
   8152                              profile_index, 1, entries));
   8153     if (min_thresh != NULL) {
   8154         *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf);
   8155     }
   8156     if (max_thresh != NULL) {
   8157         *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf);
   8158     }
   8159     if (drop_probability != NULL) {
   8160         rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf);
   8161         *drop_probability = _bcm_hx5_drop_prob_to_percent(rate);
   8162     }
   8163     if (gain) {
   8164         *gain = soc_mem_field32_get(unit, wred_config_mem, &entry, WEIGHTf);
   8165     }
   8166 
   8167     if (refresh_time) {
   8168             time_id = soc_mem_field32_get(unit, wred_config_mem, &entry,
   8169                                           TIME_DOMAIN_SELf);
   8170             BCM_IF_ERROR_RETURN
   8171                 (_bcm_hx5_cosq_time_domain_get(unit,time_id,&time));
   8172             *refresh_time = time + 1;
   8173     }
   8174 
   8175     /* Get flags */
   8176     if (flags) {
   8177         if (soc_mem_field32_get(unit, wred_config_mem, &entry, CAP_AVERAGEf)) {
   8178             *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   8179         }
   8180         if (soc_mem_field32_get(unit, wred_config_mem, &entry, WRED_ENf)) {
   8181             *flags |= BCM_COSQ_DISCARD_ENABLE;
   8182         }
   8183         if (soc_mem_field32_get(unit, wred_config_mem, &entry, ECN_MARKING_ENf)) {
   8184             *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION;
   8185         }
   8186     }
   8187 
   8188     /* Get resolution table index */
   8189     if (resolution_id) {
   8190         if (soc_mem_field32_get(unit, wred_config_mem, &entry, ECN_MARKING_ENf)) {
   8191             *resolution_id = soc_mem_field32_get(unit, wred_config_mem, &entry,
   8192                 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf);
   8193         } else {
   8194             *resolution_id = soc_mem_field32_get(unit, wred_config_mem, &entry,
   8195                 WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf);
   8196         }
   8197     }
   8198 
   8199     /* Get use_queue_group */
   8200     if (use_queue_group) {
   8201         *use_queue_group =
   8202             soc_mem_field32_get(unit, wred_config_mem, &entry, QG_ENf);
   8203     }
   8204 
   8205     return BCM_E_NONE;
   8206 }
   8207 
   8208 
   8209 int
   8210 bcm_hx5_cosq_discard_set(int unit, uint32 flags)
   8211 {
   8212     bcm_port_t port;
   8213 
   8214     if (_bcm_hx5_cosq_port_info[unit] == NULL) {
   8215         return BCM_E_INIT;
   8216     }
   8217 
   8218     if (flags & ~(BCM_COSQ_DISCARD_DEVICE |
   8219                   BCM_COSQ_DISCARD_NONTCP |
   8220                   BCM_COSQ_DISCARD_COLOR_ALL |
   8221                   BCM_COSQ_DISCARD_PORT |
   8222                   BCM_COSQ_DISCARD_TCP |
   8223                   BCM_COSQ_DISCARD_COLOR_GREEN |
   8224                   BCM_COSQ_DISCARD_COLOR_YELLOW |
   8225                   BCM_COSQ_DISCARD_COLOR_RED |
   8226                   BCM_COSQ_DISCARD_CAP_AVERAGE |
   8227                   BCM_COSQ_DISCARD_ENABLE |
   8228                   BCM_COSQ_DISCARD_MARK_CONGESTION)) {
   8229         return BCM_E_PARAM;
   8230     }
   8231 
   8232     flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL);
   8233 
   8234     PBMP_PORT_ITER(unit, port) {
   8235         BCM_IF_ERROR_RETURN
   8236             (_bcm_hx5_cosq_wred_set(unit, port, 0, flags, 0, 0, 0, 0,
   8237                                    FALSE, BCM_COSQ_DISCARD_PORT, 0x1, 0, 0));
   8238     }
   8239 
   8240     return BCM_E_NONE;
   8241 }
   8242 
   8243 int
   8244 bcm_hx5_cosq_discard_get(int unit, uint32 *flags)
   8245 {
   8246     bcm_port_t port;
   8247 
   8248     PBMP_PORT_ITER(unit, port) {
   8249         *flags = 0;
   8250         /* use setting from hardware cosq index 0 of the first port */
   8251         return _bcm_hx5_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL,
   8252                                      NULL, BCM_COSQ_DISCARD_PORT, NULL, NULL,
   8253                                      NULL);
   8254     }
   8255 
   8256     return BCM_E_NOT_FOUND;
   8257 }
   8258 
   8259 /*
   8260  * Function:
   8261  *     bcm_hx5_cosq_discard_port_set
   8262  * Purpose:
   8263  *     Configure port WRED setting
   8264  * Parameters:
   8265  *     unit          - (IN) unit number
   8266  *     port          - (IN) port number or GPORT identifier
   8267  *     cosq          - (IN) COS queue number
   8268  *     color         - (IN)
   8269  *     drop_start    - (IN)
   8270  *     drop_slot     - (IN)
   8271  *     average_time  - (IN)
   8272  * Returns:
   8273  *     BCM_E_XXX
   8274  * Notes:
   8275  *     If port is any form of local port, cosq is the hardware queue index.
   8276  *     Same as TD2 except for Reg changes.
   8277  */
   8278 int
   8279 bcm_hx5_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8280                              uint32 color, int drop_start, int drop_slope,
   8281                              int average_time)
   8282 {
   8283     bcm_port_t local_port;
   8284     bcm_pbmp_t pbmp;
   8285     int gain;
   8286     uint32 min_thresh, max_thresh, shared_limit;
   8287     uint32 rval, bits, flags = 0;
   8288     int numq, i;
   8289 
   8290     if (drop_start < 0 || drop_start > 100 ||
   8291         drop_slope < 0 || drop_slope > 90) {
   8292         return BCM_E_PARAM;
   8293     }
   8294 
   8295     /*
   8296      * average queue size is reculated every 8us, the formula is
   8297      * avg_qsize(t + 1) =
   8298      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   8299      * gain = log2(average_time / 8)
   8300      */
   8301     bits = (average_time / 8) & 0xffff;
   8302     if (bits != 0) {
   8303         bits |= bits >> 1;
   8304         bits |= bits >> 2;
   8305         bits |= bits >> 4;
   8306         bits |= bits >> 8;
   8307         gain = _shr_popcount(bits) - 1;
   8308     } else {
   8309         gain = 0;
   8310     }
   8311 
   8312     /*
   8313      * per-port cell limit may be disabled.
   8314      * per-port per-cos cell limit may be set to use dynamic method.
   8315      * therefore drop_start percentage is based on per-device total shared
   8316      * cells.
   8317      */
   8318     BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval));
   8319     shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
   8320                                      rval, SHARED_LIMITf);
   8321     min_thresh = ((drop_start * shared_limit) + (100 - 1)) / 100;
   8322 
   8323     /* Calculate the max threshold. For a given slope (angle in
   8324      * degrees), determine how many packets are in the range from
   8325      * 0% drop probability to 100% drop probability. Add that
   8326      * number to the min_treshold to the the max_threshold.
   8327      */
   8328     max_thresh = min_thresh + _bcm_hx5_angle_to_cells(drop_slope);
   8329     if (max_thresh > HX5_WRED_CELL_FIELD_MAX) {
   8330         max_thresh = HX5_WRED_CELL_FIELD_MAX;
   8331     }
   8332 
   8333     if (BCM_GPORT_IS_SET(port)) {
   8334         numq = 1;
   8335         for (i = 0; i < numq; i++) {
   8336             BCM_IF_ERROR_RETURN
   8337                 (_bcm_hx5_cosq_wred_set(unit, port, cosq + i, color,
   8338                                         min_thresh, max_thresh, 100, gain,
   8339                                         TRUE, flags, 0x1, 0, 0));
   8340         }
   8341     } else {
   8342         if (port == -1) {
   8343             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   8344         } else if (!SOC_PORT_VALID(unit, port)) {
   8345             return BCM_E_PORT;
   8346         } else {
   8347             BCM_PBMP_PORT_SET(pbmp, port);
   8348         }
   8349 
   8350         BCM_PBMP_ITER(pbmp, local_port) {
   8351             numq = 1;
   8352             for (i = 0; i < numq; i++) {
   8353                 BCM_IF_ERROR_RETURN
   8354                     (_bcm_hx5_cosq_wred_set(unit, local_port, cosq + i,
   8355                                             color, min_thresh, max_thresh, 100,
   8356                                             gain, TRUE, 0, 0x1, 0, 0));
   8357             }
   8358         }
   8359     }
   8360 
   8361     return BCM_E_NONE;
   8362 }
   8363 
   8364 /*
   8365  * Function:
   8366  *     bcm_hx5_cosq_discard_port_get
   8367  * Purpose:
   8368  *     Get port WRED setting
   8369  * Parameters:
   8370  *     unit          - (IN) unit number
   8371  *     port          - (IN) port number or GPORT identifier
   8372  *     cosq          - (IN) COS queue number
   8373  *     color         - (OUT)
   8374  *     drop_start    - (OUT)
   8375  *     drop_slot     - (OUT)
   8376  *     average_time  - (OUT)
   8377  * Returns:
   8378  *     BCM_E_XXX
   8379  * Notes:
   8380  *     If port is any form of local port, cosq is the hardware queue index.
   8381  *     Same as TD2 except for Reg changes.
   8382  */
   8383 int
   8384 bcm_hx5_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8385                              uint32 color, int *drop_start, int *drop_slope,
   8386                              int *average_time)
   8387 {
   8388     bcm_port_t local_port;
   8389     bcm_pbmp_t pbmp;
   8390     int gain, drop_prob;
   8391     uint32 min_thresh, max_thresh, shared_limit;
   8392     uint32 rval;
   8393 
   8394     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   8395         return BCM_E_PARAM;
   8396     }
   8397 
   8398     if (BCM_GPORT_IS_SET(port)) {
   8399         local_port = port;
   8400     } else {
   8401         if (port == -1) {
   8402             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   8403         } else if (!SOC_PORT_VALID(unit, port)) {
   8404             return BCM_E_PORT;
   8405         } else {
   8406             BCM_PBMP_PORT_SET(pbmp, port);
   8407         }
   8408         BCM_PBMP_ITER(pbmp, local_port) {
   8409             break;
   8410         }
   8411     }
   8412 
   8413     BCM_IF_ERROR_RETURN
   8414         (_bcm_hx5_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq,
   8415                                 &color, &min_thresh, &max_thresh, &drop_prob,
   8416                                 &gain, 0, NULL, NULL, NULL));
   8417 
   8418     /*
   8419      * average queue size is reculated every 8us, the formula is
   8420      * avg_qsize(t + 1) =
   8421      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   8422      */
   8423     *average_time = (1 << gain) * 8;
   8424 
   8425     BCM_IF_ERROR_RETURN(READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval));
   8426     shared_limit = soc_reg_field_get(unit, MMU_THDM_DB_POOL_SHARED_LIMITr,
   8427                                      rval, SHARED_LIMITf);
   8428     if (min_thresh > shared_limit) {
   8429         min_thresh = shared_limit;
   8430     }
   8431 
   8432     if (max_thresh > shared_limit) {
   8433         max_thresh = shared_limit;
   8434     }
   8435 
   8436     *drop_start = min_thresh * 100 / shared_limit;
   8437 
   8438     /* Calculate the slope using the min and max threshold.
   8439      * The angle is calculated knowing drop probability at min
   8440      * threshold is 0% and drop probability at max threshold is 100%.
   8441      */
   8442     *drop_slope = _bcm_hx5_cells_to_angle(max_thresh - min_thresh);
   8443 
   8444     return BCM_E_NONE;
   8445 }
   8446 
   8447 /*
   8448  * Function:
   8449  *     bcm_hx5_cosq_gport_discard_set
   8450  * Purpose:
   8451  *     Configure port WRED setting
   8452  * Parameters:
   8453  *     unit    - (IN) unit number
   8454  *     port    - (IN) GPORT identifier
   8455  *     cosq    - (IN) COS queue to configure, -1 for all COS queues
   8456  *     discard - (IN) discard settings
   8457  * Returns:
   8458  *     BCM_E_XXX
   8459  */
   8460 int
   8461 bcm_hx5_cosq_gport_discard_set(int unit, bcm_gport_t gport,
   8462                                bcm_cos_queue_t cosq,
   8463                                bcm_cosq_gport_discard_t *discard)
   8464 {
   8465     int numq, i;
   8466     uint32 min_thresh, max_thresh, flags = 0;
   8467     int cell_size, cell_field_max;
   8468     bcm_port_t local_port = -1;
   8469 
   8470     /* the reasonable range of refresh_time  is from 1 to 64 */
   8471     if (discard == NULL ||
   8472         discard->gain < 0 || discard->gain > 15 ||
   8473         discard->drop_probability < 0 || discard->drop_probability > 100 ||
   8474         discard->refresh_time <= 0 || discard->refresh_time > 64 || 
   8475         discard->profile_id > 3) {
   8476         return BCM_E_PARAM;
   8477     }
   8478 
   8479     if (discard == NULL ||
   8480         discard->gain < 0 || discard->gain > 15 ||
   8481         discard->drop_probability < 0 || discard->drop_probability > 100) {
   8482         return BCM_E_PARAM;
   8483     }
   8484 
   8485     cell_size = _HX5_MMU_BYTES_PER_CELL;
   8486     cell_field_max = HX5_WRED_CELL_FIELD_MAX;
   8487 
   8488     min_thresh = discard->min_thresh;
   8489     max_thresh = discard->max_thresh;
   8490     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   8491         /* Convert bytes to cells */
   8492         min_thresh += (cell_size - 1);
   8493         min_thresh /= cell_size;
   8494 
   8495         max_thresh += (cell_size - 1);
   8496         max_thresh /= cell_size;
   8497 
   8498         if ((min_thresh > cell_field_max) ||
   8499             (max_thresh > cell_field_max)) {
   8500             return BCM_E_PARAM;
   8501         }
   8502     } else if (discard->flags & BCM_COSQ_DISCARD_PACKETS) {
   8503         /* Packet mode not supported */
   8504         return BCM_E_PARAM;
   8505     } else {
   8506         /* Lower layer function will update thresh when these flags are
   8507          * configured, this interface only allow such opration when
   8508          * BCM_COSQ_DISCARD_BYTES is also configured.
   8509          */
   8510         if (discard->flags & (BCM_COSQ_DISCARD_COLOR_ALL |
   8511             BCM_COSQ_DISCARD_TCP |
   8512             BCM_COSQ_DISCARD_NONTCP |
   8513             BCM_COSQ_DISCARD_ECT_MARKED |
   8514             BCM_COSQ_DISCARD_RESPONSIVE_DROP |
   8515             BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) {
   8516             return BCM_E_PARAM;
   8517         }
   8518     }
   8519 
   8520     if (gport != BCM_GPORT_INVALID) {
   8521         BCM_IF_ERROR_RETURN
   8522             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   8523         if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) {
   8524             return BCM_E_PORT;
   8525         }
   8526         if ((cosq < -1) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) {
   8527             return BCM_E_PARAM;
   8528         }
   8529     }
   8530 
   8531     numq = 1;
   8532 
   8533     for (i = 0; i < numq; i++) {
   8534         BCM_IF_ERROR_RETURN
   8535             (_bcm_hx5_cosq_wred_set(unit, gport, cosq + i, discard->flags,
   8536                                    min_thresh, max_thresh,
   8537                                    discard->drop_probability, discard->gain,
   8538                                    FALSE, flags, discard->refresh_time,
   8539                                    discard->profile_id, discard->use_queue_group));
   8540     }
   8541 
   8542     return BCM_E_NONE;
   8543 }
   8544 
   8545 /*
   8546  * Function:
   8547  *     bcm_hx5_cosq_gport_discard_get
   8548  * Purpose:
   8549  *     Get port WRED setting
   8550  * Parameters:
   8551  *     unit    - (IN) unit number
   8552  *     port    - (IN) GPORT identifier
   8553  *     cosq    - (IN) COS queue to get, -1 for any queue
   8554  *     discard - (OUT) discard settings
   8555  * Returns:
   8556  *     BCM_E_XXX
   8557  */
   8558 int
   8559 bcm_hx5_cosq_gport_discard_get(int unit, bcm_gport_t gport,
   8560                               bcm_cos_queue_t cosq,
   8561                               bcm_cosq_gport_discard_t *discard)
   8562 {
   8563     uint32 min_thresh, max_thresh;
   8564     bcm_port_t local_port = -1;
   8565 
   8566     if (discard == NULL) {
   8567         return BCM_E_PARAM;
   8568     }
   8569 
   8570     if (gport != BCM_GPORT_INVALID) {
   8571         BCM_IF_ERROR_RETURN
   8572             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   8573         if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) {
   8574             return BCM_E_PORT;
   8575         }
   8576         if ((cosq < -1) || (cosq >= SOC_PORT_NUM_COSQ(unit, local_port))) {
   8577             return BCM_E_PARAM;
   8578         }
   8579     }
   8580 
   8581     BCM_IF_ERROR_RETURN
   8582         (_bcm_hx5_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq,
   8583                                 &discard->flags, &min_thresh, &max_thresh,
   8584                                 &discard->drop_probability, &discard->gain,
   8585                                 0, &discard->refresh_time,
   8586                                 &discard->profile_id, &discard->use_queue_group));
   8587 
   8588     /* Convert number of cells to number of bytes */
   8589     discard->min_thresh = min_thresh * _HX5_MMU_BYTES_PER_CELL;
   8590     discard->max_thresh = max_thresh * _HX5_MMU_BYTES_PER_CELL;
   8591 
   8592     return BCM_E_NONE;
   8593 }
   8594 
   8595 
   8596 /*
   8597  * Function:
   8598  *      _bcm_hx5_cosq_qgroup_limit_enables_set
   8599  * Purpose:
   8600  *      set enables for Qgroup Min and Shared Limits
   8601  * Parameters:
   8602  *      unit - (IN) Unit number.
   8603  *      port - (IN) GPORT ID.
   8604  *      cosq - (IN) COS queue.
   8605  *      type - (IN) feature
   8606  *      arg  - (IN) feature value
   8607  * Returns:
   8608  *      BCM_E_XXX
   8609  * Notes:
   8610  */
   8611 STATIC int
   8612 _bcm_hx5_cosq_qgroup_limit_enables_set(int unit, bcm_gport_t gport,
   8613         bcm_cos_t cosq,
   8614         bcm_cosq_control_t type,
   8615         int arg)
   8616 {
   8617     bcm_port_t local_port = 0;
   8618     int startq = 0, pipe = 0, count = 1, lc = 0, to_cos = 0;
   8619     uint32 entry[SOC_MAX_MEM_WORDS];
   8620     uint32 entry2[SOC_MAX_MEM_WORDS];
   8621     soc_mem_t mem = INVALIDm;
   8622     soc_mem_t base_mem = INVALIDm;
   8623     int enable = 0;
   8624     int valid = 0;
   8625     soc_field_t field = INVALIDf;
   8626     soc_field_t field2 = INVALIDf;
   8627 
   8628     if (arg < 0) {
   8629         return BCM_E_PARAM;
   8630     }
   8631     arg = arg ? 1 : 0;
   8632 
   8633     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8634         BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   8635                     _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, &local_port, &startq, NULL));
   8636     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8637         return BCM_E_PARAM;
   8638     } else {
   8639         if (cosq < -1) {
   8640             return BCM_E_PARAM;
   8641         }
   8642         BCM_IF_ERROR_RETURN
   8643             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   8644         if (local_port < 0) {
   8645             return BCM_E_PORT;
   8646         }
   8647         BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_index_resolve(unit, local_port, cosq,
   8648                     _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, &startq, &count));
   8649     }
   8650 
   8651     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8652     base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   8653     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   8654     if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) {
   8655         field = QGROUP_LIMIT_ENABLEf;
   8656         field2 = QGROUP_VALIDf;
   8657     } else if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
   8658         field = USE_QGROUP_MINf;
   8659         field2 = QGROUP_VALIDf;
   8660     } else {
   8661         return BCM_E_PARAM;
   8662     }
   8663 
   8664     to_cos = startq + count;
   8665     for (lc = startq; lc < to_cos; lc++) {
   8666         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, lc, entry));
   8667         enable = soc_mem_field32_get(unit, mem, entry, field);
   8668         if (enable != arg) {
   8669             soc_mem_field32_set(unit, mem, entry, field, arg);
   8670             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, lc, entry));
   8671         }
   8672         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, lc, entry2));
   8673         valid = soc_mem_field32_get(unit, mem, entry2, field2);
   8674         if (valid != 1) {
   8675             soc_mem_field32_set(unit, mem, entry2, field2, 1);
   8676             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, lc, entry2));
   8677         }
   8678     }
   8679 
   8680     return BCM_E_NONE;
   8681 }
   8682 
   8683 /*
   8684  * Function:
   8685  *       _bcm_hx5_cosq_qgroup_limit_enables_get
   8686  * Purpose:
   8687  *       get enables for Qgroup Min and Shared Limits
   8688  * Parameters:
   8689  *      unit - (IN) Unit number.
   8690  *      port - (IN) GPORT ID.
   8691  *      cosq - (IN) COS queue.
   8692  *      type - (IN) feature
   8693  *      arg  - (OUT) feature value
   8694  *  Returns:
   8695  *       BCM_E_XXX
   8696  *  Notes:
   8697  */
   8698 
   8699 STATIC int
   8700 _bcm_hx5_cosq_qgroup_limit_enables_get(int unit, bcm_gport_t gport,
   8701         bcm_cos_queue_t cosq,
   8702         bcm_cosq_control_t type,
   8703         int *arg)
   8704 {
   8705     int startq, pipe;
   8706     bcm_port_t local_port;
   8707     uint32 entry[SOC_MAX_MEM_WORDS];
   8708     soc_mem_t mem = INVALIDm;
   8709     soc_mem_t base_mem = INVALIDm;
   8710     soc_field_t field = INVALIDf;
   8711 
   8712     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   8713         BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
   8714                     _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, &local_port, &startq, NULL));
   8715     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8716         return BCM_E_PARAM;
   8717     } else {
   8718         if (cosq < 0) {
   8719             return BCM_E_PARAM;
   8720         }
   8721         BCM_IF_ERROR_RETURN
   8722             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   8723         if (local_port < 0) {
   8724             return BCM_E_PORT;
   8725         }
   8726         BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_index_resolve(unit, local_port, cosq,
   8727                     _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, NULL, &startq, NULL));
   8728     }
   8729 
   8730     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8731     base_mem = MMU_THDU_Q_TO_QGRP_MAPm;
   8732     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   8733     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   8734 
   8735     if (type == bcmCosqControlEgressUCQueueGroupSharedLimitEnable) {
   8736         field = QGROUP_LIMIT_ENABLEf;
   8737     } else if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
   8738         field = USE_QGROUP_MINf;
   8739     } else {
   8740         return BCM_E_PARAM;
   8741     }
   8742 
   8743     *arg = soc_mem_field32_get(unit, mem, entry, field);
   8744     return BCM_E_NONE;
   8745 }
   8746 
   8747 /*
   8748  *Function:
   8749  *      _bcm_hx5_cosq_qgroup_limit_set
   8750  *Purpose:
   8751  *      set limits for Qgroup Min and Shared Limits
   8752  *Parameters:
   8753  *      unit - (IN) Unit number.
   8754  *      port - (IN) GPORT ID.
   8755  *      cosq - (IN) COS queue.
   8756  *      type - (IN) feature
   8757  *      arg  - (IN) feature value
   8758  * Returns:
   8759  *      BCM_E_XXX
   8760  * Notes:
   8761  */
   8762 
   8763 STATIC int
   8764 _bcm_hx5_cosq_qgroup_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq,
   8765         bcm_cosq_control_t type, int arg)
   8766 {
   8767     int pipe;
   8768     int phy_port;
   8769     int mmu_port;
   8770     bcm_port_t local_port;
   8771     soc_mem_t mem = INVALIDm;
   8772     soc_mem_t base_mem = INVALIDm;
   8773     soc_field_t field = INVALIDf;
   8774     int granularity;
   8775     int egr_db_shd_size;
   8776     int egr_qe_shd_size;
   8777     int cur_val;
   8778     int max_val;
   8779     int delta;
   8780     uint32 rval;
   8781     uint32 entry[SOC_MAX_MEM_WORDS];
   8782     soc_info_t *si = &SOC_INFO(unit);
   8783 
   8784     if (cosq < 0) {
   8785         return BCM_E_PARAM;
   8786     }
   8787 
   8788     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8789         return BCM_E_PARAM;
   8790     }
   8791     BCM_IF_ERROR_RETURN(
   8792             _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   8793     if (local_port < 0) {
   8794         return BCM_E_PORT;
   8795     }
   8796 
   8797     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes ||
   8798             type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) {
   8799         arg = (arg + _HX5_MMU_BYTES_PER_CELL - 1) / _HX5_MMU_BYTES_PER_CELL;
   8800     }
   8801 
   8802     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8803     phy_port = si->port_l2p_mapping[local_port];
   8804     mmu_port = si->port_p2m_mapping[phy_port];
   8805     base_mem = MMU_THDU_CONFIG_QGROUPm;
   8806     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   8807     BCM_IF_ERROR_RETURN(soc_mem_read(
   8808                 unit, mem, MEM_BLOCK_ALL, mmu_port, entry));
   8809 
   8810     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) {
   8811         field = Q_MIN_LIMIT_CELLf;
   8812         granularity = 1;
   8813 
   8814         rval = 0;
   8815         SOC_IF_ERROR_RETURN(
   8816                 READ_MMU_THDM_DB_POOL_SHARED_LIMITr(unit, 0, &rval));
   8817         egr_db_shd_size = soc_reg_field_get(
   8818                 unit, MMU_THDM_DB_POOL_SHARED_LIMITr, rval, SHARED_LIMITf);
   8819 
   8820         rval = 0;
   8821         SOC_IF_ERROR_RETURN(
   8822                 READ_MMU_THDM_MCQE_POOL_SHARED_LIMITr(unit, 0, &rval));
   8823         egr_qe_shd_size = soc_reg_field_get(
   8824                 unit, MMU_THDM_MCQE_POOL_SHARED_LIMITr, rval, SHARED_LIMITf);
   8825 
   8826         cur_val = soc_mem_field32_get(unit, mem, entry, field);
   8827         delta = ((arg / granularity) - cur_val) * granularity;
   8828         if (delta > egr_db_shd_size) {
   8829             return BCM_E_PARAM;
   8830         }
   8831 
   8832         SOC_IF_ERROR_RETURN(soc_hx5_mmu_config_shared_buf_recalc(
   8833                     unit, 2, -1, egr_db_shd_size - delta, egr_qe_shd_size, 1));
   8834     } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) {
   8835         field = Q_SHARED_LIMIT_CELLf;
   8836         granularity = 1;
   8837     } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) {
   8838         field = Q_LIMIT_DYNAMIC_CELLf;
   8839         granularity = 1;
   8840     } else {
   8841         return BCM_E_PARAM;
   8842     }
   8843 
   8844     max_val = (1 << soc_mem_field_length(unit, mem, field)) - 1;
   8845     if ((arg < 0) || ((arg / granularity) > max_val)) {
   8846         return BCM_E_PARAM;
   8847     }
   8848 
   8849     soc_mem_field32_set(unit, mem, entry, field, (arg / granularity));
   8850     BCM_IF_ERROR_RETURN(soc_mem_write(
   8851                 unit, mem, MEM_BLOCK_ALL, mmu_port, entry));
   8852     return BCM_E_NONE;
   8853 }
   8854 
   8855 
   8856 /*
   8857  * Function:
   8858  *      _bcm_hx5_cosq_qgroup_limit_get
   8859  * Purpose:
   8860  *      get limits for Qgroup Min and Shared Limits
   8861  * Parameters:
   8862  *      unit - (IN) Unit number.
   8863  *      port - (IN) GPORT ID.
   8864  *      cosq - (IN) COS queue.
   8865  *      type - (IN) feature
   8866  *      arg  - (OUT) feature value
   8867  * Returns:
   8868  *       BCM_E_XXX
   8869  *  Notes:
   8870  */
   8871 
   8872 STATIC int
   8873 _bcm_hx5_cosq_qgroup_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq,
   8874         bcm_cosq_control_t type, int *arg) {
   8875     int pipe;
   8876     int phy_port;
   8877     int mmu_port;
   8878     bcm_port_t local_port;
   8879     soc_mem_t mem = INVALIDm;
   8880     soc_mem_t base_mem = INVALIDm;
   8881     soc_field_t field = INVALIDf;
   8882     uint32 entry[SOC_MAX_MEM_WORDS];
   8883     soc_info_t *si = &SOC_INFO(unit);
   8884 
   8885     if (cosq < 0) {
   8886         return BCM_E_PARAM;
   8887     }
   8888 
   8889     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8890         return BCM_E_PARAM;
   8891     }
   8892     BCM_IF_ERROR_RETURN(
   8893             _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   8894     if (local_port < 0) {
   8895         return BCM_E_PORT;
   8896     }
   8897 
   8898     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, & pipe));
   8899     phy_port = si->port_l2p_mapping[local_port];
   8900     mmu_port = si->port_p2m_mapping[phy_port];
   8901     base_mem = MMU_THDU_CONFIG_QGROUPm;
   8902     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   8903     BCM_IF_ERROR_RETURN(
   8904             soc_mem_read(unit, mem, MEM_BLOCK_ALL, mmu_port, entry));
   8905 
   8906     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) {
   8907         field = Q_MIN_LIMIT_CELLf;
   8908     } else if (type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) {
   8909         field = Q_SHARED_LIMIT_CELLf;
   8910     } else if (type == bcmCosqControlEgressUCQueueGroupSharedDynamicEnable) {
   8911         field = Q_LIMIT_DYNAMIC_CELLf;
   8912     } else {
   8913         return BCM_E_PARAM;
   8914     }
   8915 
   8916     *arg = soc_mem_field32_get(unit, mem, entry, field);
   8917     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes ||
   8918             type == bcmCosqControlEgressUCQueueGroupSharedLimitBytes) {
   8919         *arg = (*arg) * _HX5_MMU_BYTES_PER_CELL;
   8920     }
   8921     return BCM_E_NONE;
   8922 }
   8923 
   8924 /*
   8925  *Function:
   8926  *      _bcm_hx5_cosq_qgroup_alpha_set
   8927  * Purpose:
   8928  *      set alpha for qgroup
   8929  * Parameters:
   8930  *      unit - (IN) Unit number.
   8931  *      port - (IN) GPORT ID.
   8932  *      cosq - (IN) COS queue.
   8933  *      arg  - (IN) feature value
   8934  * Returns:
   8935  *      BCM_E_XXX
   8936  * Notes:
   8937  */ 
   8938 STATIC int
   8939 _bcm_hx5_cosq_qgroup_alpha_set(int unit, bcm_gport_t gport,
   8940         bcm_cos_queue_t cosq,
   8941         bcm_cosq_control_drop_limit_alpha_value_t arg)
   8942 {   
   8943     int alpha;
   8944     int pipe;
   8945     int phy_port;
   8946     int mmu_port;
   8947     bcm_port_t local_port;
   8948     soc_mem_t mem = INVALIDm;
   8949     soc_mem_t base_mem = INVALIDm;
   8950     uint32 entry[SOC_MAX_MEM_WORDS];
   8951     soc_info_t *si = &SOC_INFO(unit);
   8952 
   8953     if (cosq < 0) {
   8954         return BCM_E_PARAM;
   8955     }
   8956 
   8957     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8958         return BCM_E_PARAM;
   8959     }
   8960 
   8961     BCM_IF_ERROR_RETURN(
   8962             _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   8963     if (local_port < 0) {
   8964         return BCM_E_PORT;
   8965     }
   8966 
   8967     switch(arg) {
   8968         case bcmCosqControlDropLimitAlpha_1_128:
   8969             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128;
   8970             break;
   8971         case bcmCosqControlDropLimitAlpha_1_64:
   8972             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_64;
   8973             break;
   8974         case bcmCosqControlDropLimitAlpha_1_32:
   8975             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_32;
   8976             break;
   8977         case bcmCosqControlDropLimitAlpha_1_16:
   8978             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_16;
   8979             break;
   8980         case bcmCosqControlDropLimitAlpha_1_8:
   8981             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_8;
   8982             break;
   8983         case bcmCosqControlDropLimitAlpha_1_4:
   8984             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_4;
   8985             break;
   8986         case bcmCosqControlDropLimitAlpha_1_2:
   8987             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_2;
   8988             break;
   8989         case bcmCosqControlDropLimitAlpha_1:
   8990             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1;
   8991             break;
   8992         case bcmCosqControlDropLimitAlpha_2:
   8993             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_2;
   8994             break;
   8995         case bcmCosqControlDropLimitAlpha_4:
   8996             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_4;
   8997             break;
   8998         case bcmCosqControlDropLimitAlpha_8:
   8999             alpha = SOC_HX5_COSQ_DROP_LIMIT_ALPHA_8;
   9000             break;
   9001         default:
   9002             return BCM_E_PARAM;
   9003     }
   9004 
   9005     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   9006     phy_port = si->port_l2p_mapping[local_port];
   9007     mmu_port = si->port_p2m_mapping[phy_port];
   9008     base_mem = MMU_THDU_CONFIG_QGROUPm;
   9009     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9010     BCM_IF_ERROR_RETURN(soc_mem_read(
   9011                 unit, mem, MEM_BLOCK_ALL, mmu_port, entry));
   9012 
   9013     soc_mem_field32_set(unit, mem, entry, Q_SHARED_ALPHA_CELLf, alpha);
   9014     BCM_IF_ERROR_RETURN(soc_mem_write(
   9015                 unit, mem, MEM_BLOCK_ALL, mmu_port, entry));
   9016     return BCM_E_NONE;
   9017 }
   9018 
   9019 /*
   9020  * Function:
   9021  *       _bcm_hx5_cosq_qgroup_alpha_get
   9022  * Purpose:
   9023  *      get alpha for qgroup
   9024  * Parameters:
   9025  *      unit - (IN) Unit number.
   9026  *      port - (IN) GPORT ID.
   9027  *      cosq - (IN) COS queue.
   9028  *      arg  - (OUT) feature value
   9029  * Returns:
   9030  *      BCM_E_XXX
   9031  * Notes:
   9032  */
   9033 
   9034 STATIC int
   9035 _bcm_hx5_cosq_qgroup_alpha_get(int unit, bcm_gport_t gport,
   9036         bcm_cos_queue_t cosq,
   9037         bcm_cosq_control_drop_limit_alpha_value_t *arg)
   9038 {
   9039     int alpha;
   9040     int pipe;
   9041     int phy_port;
   9042     int mmu_port;
   9043     bcm_port_t local_port;
   9044     soc_mem_t mem = INVALIDm;
   9045     soc_mem_t base_mem = INVALIDm;
   9046     uint32 entry[SOC_MAX_MEM_WORDS];
   9047     soc_info_t *si = &SOC_INFO(unit);
   9048 
   9049     if (cosq < 0) {
   9050         return BCM_E_PARAM;
   9051     }
   9052 
   9053     if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9054         return BCM_E_PARAM;
   9055     }
   9056 
   9057     BCM_IF_ERROR_RETURN(
   9058             _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
   9059     if (local_port < 0) {
   9060         return BCM_E_PORT;
   9061     }
   9062 
   9063     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   9064     phy_port = si->port_l2p_mapping[local_port];
   9065     mmu_port = si->port_p2m_mapping[phy_port];
   9066     base_mem = MMU_THDU_CONFIG_QGROUPm;
   9067     mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe];
   9068     BCM_IF_ERROR_RETURN(soc_mem_read(
   9069                 unit, mem, MEM_BLOCK_ALL, mmu_port, entry));
   9070     alpha = soc_mem_field32_get(unit, mem, entry, Q_SHARED_ALPHA_CELLf);
   9071 
   9072     switch(alpha) {
   9073         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_128:
   9074             *arg = bcmCosqControlDropLimitAlpha_1_128;
   9075             break;
   9076         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_64:
   9077             *arg = bcmCosqControlDropLimitAlpha_1_64;
   9078             break;
   9079         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_32:
   9080             *arg = bcmCosqControlDropLimitAlpha_1_32;
   9081             break;
   9082         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_16:
   9083             *arg = bcmCosqControlDropLimitAlpha_1_16;
   9084             break;
   9085         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_8:
   9086             *arg = bcmCosqControlDropLimitAlpha_1_8;
   9087             break;
   9088         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_4:
   9089             *arg = bcmCosqControlDropLimitAlpha_1_4;
   9090             break;
   9091         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1_2:
   9092             *arg = bcmCosqControlDropLimitAlpha_1_2;
   9093             break;
   9094         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_1:
   9095             *arg = bcmCosqControlDropLimitAlpha_1;
   9096             break;
   9097         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_2:
   9098             *arg = bcmCosqControlDropLimitAlpha_2;
   9099             break;
   9100         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_4:
   9101             *arg = bcmCosqControlDropLimitAlpha_4;
   9102             break;
   9103         case SOC_HX5_COSQ_DROP_LIMIT_ALPHA_8:
   9104             *arg = bcmCosqControlDropLimitAlpha_8;
   9105             break;
   9106         default:
   9107             return BCM_E_PARAM;
   9108     }
   9109 
   9110     return BCM_E_NONE;
   9111 }
   9112 
   9113 
   9114 /*
   9115  * Function:
   9116  *      bcm_hx5_cosq_control_set
   9117  * Purpose:
   9118  *      Set specified feature configuration
   9119  *
   9120  * Parameters:
   9121  *      unit - (IN) Unit number.
   9122  *      port - (IN) GPORT ID.
   9123  *      cosq - (IN) COS queue.
   9124  *      type - (IN) feature
   9125  *      arg  - (IN) feature value
   9126  * Returns:
   9127  *      BCM_E_XXX
   9128  * Notes:
   9129  */
   9130 int
   9131 bcm_hx5_cosq_control_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   9132                         bcm_cosq_control_t type, int arg)
   9133 {
   9134     uint32 kbits_burst_min, kbits_burst_max;
   9135     uint32 kbits_burst;
   9136 
   9137     kbits_burst_min = 0;
   9138     kbits_burst_max = 0;
   9139 
   9140     COMPILER_REFERENCE(kbits_burst_min);
   9141     COMPILER_REFERENCE(kbits_burst_max);
   9142 
   9143     switch (type) {
   9144         case bcmCosqControlBandwidthBurstMax:
   9145             kbits_burst = arg & 0x7fffffff; /* Convert to uint32  */
   9146             BCM_IF_ERROR_RETURN
   9147                 (bcm_hx5_cosq_gport_bandwidth_burst_get(unit, gport, cosq,
   9148                                                         &kbits_burst_min,
   9149                                                         &kbits_burst_max));
   9150             return bcm_hx5_cosq_gport_bandwidth_burst_set(unit, gport, cosq,
   9151                                                              kbits_burst_min,
   9152                                                              kbits_burst);
   9153         case bcmCosqControlBandwidthBurstMin:
   9154             kbits_burst = arg & 0x7fffffff; /* Convert to uint32  */
   9155             BCM_IF_ERROR_RETURN
   9156                 (bcm_hx5_cosq_gport_bandwidth_burst_get(unit, gport, cosq,
   9157                                                        &kbits_burst_min,
   9158                                                        &kbits_burst_max));
   9159             return bcm_hx5_cosq_gport_bandwidth_burst_set(unit, gport, cosq,
   9160                                                          kbits_burst,
   9161                                                          kbits_burst_max);
   9162         case bcmCosqControlEgressPool:
   9163         case bcmCosqControlEgressPoolLimitBytes:
   9164         case bcmCosqControlEgressPoolYellowLimitBytes:
   9165         case bcmCosqControlEgressPoolRedLimitBytes:
   9166         case bcmCosqControlEgressPoolLimitEnable:
   9167         case bcmCosqControlUCEgressPool:
   9168         case bcmCosqControlMCEgressPool:
   9169         case bcmCosqControlEgressPoolSharedLimitBytes:
   9170         case bcmCosqControlEgressPoolResumeLimitBytes:
   9171         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
   9172         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
   9173         case bcmCosqControlEgressPoolRedSharedLimitBytes:
   9174         case bcmCosqControlEgressPoolRedResumeLimitBytes:
   9175         case bcmCosqControlEgressPoolHighCongestionLimitBytes:
   9176         case bcmCosqControlEgressPoolLowCongestionLimitBytes:
   9177             return _bcm_hx5_cosq_egr_pool_set(unit, gport, cosq, type, arg);
   9178         case bcmCosqControlEgressUCQueueSharedLimitBytes:
   9179         case bcmCosqControlEgressMCQueueSharedLimitBytes:
   9180         case bcmCosqControlEgressUCQueueMinLimitBytes:
   9181         case bcmCosqControlEgressMCQueueMinLimitBytes:
   9182             return _bcm_hx5_cosq_egr_queue_set(unit, gport, cosq, type, arg);
   9183         case bcmCosqControlIngressPortPGSharedLimitBytes:
   9184         case bcmCosqControlIngressPortPGMinLimitBytes:
   9185         case bcmCosqControlIngressPortPoolMaxLimitBytes:
   9186         case bcmCosqControlIngressPortPoolMinLimitBytes:
   9187         case bcmCosqControlIngressPortPGHeadroomLimitBytes:
   9188         case bcmCosqControlIngressPortPGResetFloorBytes:
   9189             return _bcm_hx5_cosq_ing_res_set(unit, gport, cosq, type, arg);
   9190         case bcmCosqControlIngressPool:
   9191         case bcmCosqControlIngressHeadroomPool:
   9192             return _bcm_hx5_cosq_ing_pool_set(unit, gport, cosq, type, arg);
   9193         case bcmCosqControlDropLimitAlpha:
   9194             return _bcm_hx5_cosq_alpha_set(unit, gport, cosq,
   9195                                 (bcm_cosq_control_drop_limit_alpha_value_t)arg);
   9196         case bcmCosqControlIngressPortPGSharedDynamicEnable:
   9197         case bcmCosqControlEgressUCSharedDynamicEnable:
   9198         case bcmCosqControlEgressMCSharedDynamicEnable:
   9199             return _bcm_hx5_cosq_dynamic_thresh_enable_set(unit, gport, cosq,
   9200                                                            type, arg);
   9201         case bcmCosqControlEgressPortPoolYellowLimitBytes:
   9202         case bcmCosqControlEgressPortPoolRedLimitBytes:
   9203             return _bcm_hx5_cosq_egr_port_pool_set(unit, gport, cosq, type, arg);
   9204         case bcmCosqControlEgressUCQueueLimitEnable:
   9205         case bcmCosqControlEgressMCQueueLimitEnable:
   9206             return _bcm_hx5_cosq_egr_queue_limit_enable_set(unit, gport, cosq,
   9207                                                             type, arg);
   9208         case bcmCosqControlIngressPoolLimitBytes:
   9209         case bcmCosqControlIngressHeadroomPoolLimitBytes:
   9210             return _bcm_hx5_cosq_ing_res_limit_set(unit, gport, cosq, type, arg);
   9211         case bcmCosqControlEgressUCQueueGroupMinEnable:
   9212         case bcmCosqControlEgressUCQueueGroupSharedLimitEnable:
   9213             return _bcm_hx5_cosq_qgroup_limit_enables_set(
   9214                     unit, gport, cosq, type, arg); 
   9215         case bcmCosqControlEgressUCQueueGroupMinLimitBytes:
   9216         case bcmCosqControlEgressUCQueueGroupSharedLimitBytes:
   9217         case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable:
   9218             return _bcm_hx5_cosq_qgroup_limit_set(unit, gport, cosq, type, arg); 
   9219         case bcmCosqControlEgressUCQueueGroupDropLimitAlpha:
   9220             return _bcm_hx5_cosq_qgroup_alpha_set(unit, gport, cosq, 
   9221                     (bcm_cosq_control_drop_limit_alpha_value_t)arg);
   9222 
   9223         default:
   9224             break;
   9225     }
   9226     return BCM_E_UNAVAIL;
   9227 }
   9228 
   9229 /*
   9230  * Function:
   9231  *      bcm_hx5_cosq_control_get
   9232  * Purpose:
   9233  *      Get specified feature configuration
   9234  *
   9235  * Parameters:
   9236  *      unit - (IN) Unit number.
   9237  *      port - (IN) GPORT ID.
   9238  *      cosq - (IN) COS queue.
   9239  *      type - (IN) feature
   9240  *      arg  - (OUT) feature value
   9241  * Returns:
   9242  *      BCM_E_XXX
   9243  * Notes:
   9244  */
   9245 int
   9246 bcm_hx5_cosq_control_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   9247                         bcm_cosq_control_t type, int *arg)
   9248 {
   9249     uint32 kburst_tmp, kbits_burst;
   9250 
   9251     switch (type) {
   9252         case bcmCosqControlBandwidthBurstMax:
   9253             BCM_IF_ERROR_RETURN
   9254                 (bcm_hx5_cosq_gport_bandwidth_burst_get(unit, gport, cosq,
   9255                                                        &kburst_tmp,
   9256                                                        &kbits_burst));
   9257             *arg = kbits_burst & 0x7fffffff; /* Convert to int  */
   9258             return BCM_E_NONE;
   9259 
   9260         case bcmCosqControlBandwidthBurstMin:
   9261             return bcm_hx5_cosq_gport_bandwidth_burst_get(unit, gport, cosq,
   9262                                                          (uint32*)arg,
   9263                                                          &kburst_tmp);
   9264         case bcmCosqControlEgressPool:
   9265         case bcmCosqControlEgressPoolLimitBytes:
   9266         case bcmCosqControlEgressPoolYellowLimitBytes:
   9267         case bcmCosqControlEgressPoolRedLimitBytes:
   9268         case bcmCosqControlEgressPoolLimitEnable:
   9269         case bcmCosqControlUCEgressPool:
   9270         case bcmCosqControlMCEgressPool:
   9271         case bcmCosqControlEgressPoolSharedLimitBytes:
   9272         case bcmCosqControlEgressPoolResumeLimitBytes:
   9273         case bcmCosqControlEgressPoolYellowSharedLimitBytes:
   9274         case bcmCosqControlEgressPoolYellowResumeLimitBytes:
   9275         case bcmCosqControlEgressPoolRedSharedLimitBytes:
   9276         case bcmCosqControlEgressPoolRedResumeLimitBytes:
   9277         case bcmCosqControlEgressPoolHighCongestionLimitBytes:
   9278         case bcmCosqControlEgressPoolLowCongestionLimitBytes:
   9279             return _bcm_hx5_cosq_egr_pool_get(unit, gport, cosq, type, arg);
   9280         case bcmCosqControlEgressUCQueueSharedLimitBytes:
   9281         case bcmCosqControlEgressMCQueueSharedLimitBytes:
   9282         case bcmCosqControlEgressUCQueueMinLimitBytes:
   9283         case bcmCosqControlEgressMCQueueMinLimitBytes:
   9284             return _bcm_hx5_cosq_egr_queue_get(unit, gport, cosq, type, arg);
   9285         case bcmCosqControlIngressPortPGSharedLimitBytes:
   9286         case bcmCosqControlIngressPortPGMinLimitBytes:
   9287         case bcmCosqControlIngressPortPoolMaxLimitBytes:
   9288         case bcmCosqControlIngressPortPoolMinLimitBytes:
   9289         case bcmCosqControlIngressPortPGHeadroomLimitBytes:
   9290         case bcmCosqControlIngressPortPGResetFloorBytes:
   9291             return _bcm_hx5_cosq_ing_res_get(unit, gport, cosq, type, arg);
   9292         case bcmCosqControlIngressPool:
   9293         case bcmCosqControlIngressHeadroomPool:
   9294             return _bcm_hx5_cosq_ing_pool_get(unit, gport, cosq, type, arg);
   9295         case bcmCosqControlDropLimitAlpha:
   9296             return _bcm_hx5_cosq_alpha_get(unit, gport, cosq,
   9297                             (bcm_cosq_control_drop_limit_alpha_value_t *)arg);
   9298         case bcmCosqControlIngressPortPGSharedDynamicEnable:
   9299         case bcmCosqControlEgressUCSharedDynamicEnable:
   9300         case bcmCosqControlEgressMCSharedDynamicEnable:
   9301             return _bcm_hx5_cosq_dynamic_thresh_enable_get(unit, gport, cosq,
   9302                                                           type, arg);
   9303         case bcmCosqControlEgressPortPoolYellowLimitBytes:
   9304         case bcmCosqControlEgressPortPoolRedLimitBytes:
   9305             return _bcm_hx5_cosq_egr_port_pool_get(unit, gport, cosq, type, arg);
   9306         case bcmCosqControlEgressUCQueueLimitEnable:
   9307         case bcmCosqControlEgressMCQueueLimitEnable:
   9308             return _bcm_hx5_cosq_egr_queue_limit_enable_get(unit, gport, cosq,
   9309                                                            type, arg);
   9310         case bcmCosqControlIngressPoolLimitBytes:
   9311         case bcmCosqControlIngressHeadroomPoolLimitBytes:
   9312             return _bcm_hx5_cosq_ing_res_limit_get(unit, gport, cosq, type, arg);
   9313         case bcmCosqControlEgressUCQueueGroupMinEnable:
   9314         case bcmCosqControlEgressUCQueueGroupSharedLimitEnable:
   9315             return _bcm_hx5_cosq_qgroup_limit_enables_get(
   9316                     unit, gport, cosq, type, arg);
   9317         case bcmCosqControlEgressUCQueueGroupMinLimitBytes:
   9318         case bcmCosqControlEgressUCQueueGroupSharedLimitBytes:
   9319         case bcmCosqControlEgressUCQueueGroupSharedDynamicEnable:
   9320             return _bcm_hx5_cosq_qgroup_limit_get(unit, gport, cosq, type, arg);
   9321         case bcmCosqControlEgressUCQueueGroupDropLimitAlpha:
   9322             return _bcm_hx5_cosq_qgroup_alpha_get(unit, gport, cosq,
   9323                     (bcm_cosq_control_drop_limit_alpha_value_t*)arg);
   9324         default:
   9325             break;
   9326     }
   9327     return BCM_E_UNAVAIL;
   9328 }
   9329 /*
   9330  * Function:
   9331  *     bcm_hx5_cosq_gport_bandwidth_get
   9332  * Purpose:
   9333  *     Get COS queue bandwidth control configuration
   9334  * Parameters:
   9335  *     unit   - (IN) unit number
   9336  *     gport  - (IN) GPORT identifier
   9337  *     cosq   - (IN) COS queue number
   9338  *     kbits_sec_min - (OUT) minimum bandwidth, kbits/sec
   9339  *     kbits_sec_max - (OUT) maximum bandwidth, kbits/sec
   9340  *     flags  - (OUT) BCM_COSQ_BW_XXX
   9341  * Returns:
   9342  *     BCM_E_XXX
   9343  */
   9344 int
   9345 bcm_hx5_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
   9346                                  bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
   9347                                  uint32 *kbits_sec_max, uint32 *flags)
   9348 {
   9349     uint32 kbits_sec_burst;
   9350 
   9351     BCM_IF_ERROR_RETURN
   9352         (_bcm_hx5_cosq_bucket_get(unit, gport, cosq, kbits_sec_min,
   9353                                   kbits_sec_max, &kbits_sec_burst,
   9354                                   &kbits_sec_burst, flags));
   9355 
   9356     return BCM_E_NONE;
   9357 }
   9358 
   9359 /*
   9360  * Function:
   9361  *     bcm_hx5_cosq_gport_bandwidth_set
   9362  * Purpose:
   9363  *     Configure COS queue bandwidth control
   9364  * Parameters:
   9365  *     unit   - (IN) unit number
   9366  *     gport  - (IN) GPORT identifier
   9367  *     cosq   - (IN) COS queue number
   9368  *     kbits_sec_min - (IN) minimum bandwidth, kbits/sec
   9369  *     kbits_sec_max - (IN) maximum bandwidth, kbits/sec
   9370  *     flags  - (IN) BCM_COSQ_BW_XXX
   9371  * Returns:
   9372  *     BCM_E_XXX
   9373  */
   9374 int
   9375 bcm_hx5_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
   9376                                  bcm_cos_queue_t cosq, uint32 kbits_sec_min,
   9377                                  uint32 kbits_sec_max, uint32 flags)
   9378 {
   9379     int i = 0, local_port;
   9380     _bcm_hx5_cosq_node_t *node = NULL;
   9381     uint32 burst_min, burst_max;
   9382 
   9383     BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_localport_resolve(unit, gport,
   9384                                                         &local_port));
   9385 
   9386     if (BCM_GPORT_IS_SET(gport)) {
   9387         if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   9388             BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   9389             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   9390             BCM_IF_ERROR_RETURN
   9391                 (_bcm_hx5_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   9392 
   9393             if (node != NULL) {
   9394                  i = node->hw_index;
   9395             } else {
   9396                 cosq = 0;
   9397             }
   9398         } else {
   9399             if (cosq < 0) {
   9400                 return BCM_E_PARAM;
   9401             }
   9402             i  = cosq;
   9403         }
   9404     } else {
   9405         if (cosq < 0) {
   9406             return BCM_E_PARAM;
   9407         }
   9408         i = cosq;
   9409     }
   9410 
   9411     burst_min = (kbits_sec_min > 0) ?
   9412         _bcm_td_default_burst_size(unit, local_port, kbits_sec_min) : 0;
   9413 
   9414     burst_max = (kbits_sec_max > 0) ?
   9415         _bcm_td_default_burst_size(unit, local_port, kbits_sec_max) : 0;
   9416 
   9417     BCM_IF_ERROR_RETURN
   9418         (_bcm_hx5_cosq_bucket_set(unit, gport, i, kbits_sec_min,
   9419                                       kbits_sec_max, burst_min, burst_max,
   9420                                       flags));
   9421 
   9422     return BCM_E_NONE;
   9423 }
   9424 
   9425 /*
   9426  * Function:
   9427  *     bcm_hx5_cosq_port_bandwidth_set
   9428  * Purpose:
   9429  *     Configure COS queue bandwidth control
   9430  * Parameters:
   9431  *     unit   - (IN) unit number
   9432  *     port   - (IN) port number
   9433  *     cosq   - (IN) COS queue number
   9434  *     min_quantum   - (IN) minimum bandwidth, kbits/sec
   9435  *     max_quantum   - (IN) maximum bandwidth, kbits/sec
   9436  *     burst_quantum - (IN) burst size, kbits/sec
   9437  *     flags  - (IN) BCM_COSQ_BW_XXX
   9438  * Returns:
   9439  *     BCM_E_XXX
   9440  */
   9441 int
   9442 bcm_hx5_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   9443                                 bcm_cos_queue_t cosq, uint32 min_quantum,
   9444                                 uint32 max_quantum, uint32 burst_quantum,
   9445                                 uint32 flags)
   9446 {
   9447     uint32 burst_min, burst_max;
   9448 
   9449     if (cosq < 0) {
   9450         return BCM_E_PARAM;
   9451     }
   9452 
   9453     if (BCM_GPORT_IS_SET(port)) {
   9454         if ((BCM_GPORT_IS_SCHEDULER(port)) ||
   9455             BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9456             BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9457             BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port)) {
   9458             return BCM_E_UNAVAIL;
   9459         }
   9460     }
   9461 
   9462     burst_min = (min_quantum > 0) ?
   9463         _bcm_td_default_burst_size(unit, port, min_quantum) : 0;
   9464 
   9465     burst_max = (max_quantum > 0) ?
   9466         _bcm_td_default_burst_size(unit, port, max_quantum) : 0;
   9467 
   9468         BCM_IF_ERROR_RETURN
   9469             (_bcm_hx5_cosq_bucket_set(unit, port, cosq, min_quantum,
   9470                                       max_quantum, burst_min, burst_max,
   9471                                       flags));
   9472 
   9473     return BCM_E_NONE;
   9474 }
   9475 
   9476 /*
   9477  * Function:
   9478  *     bcm_hx5_cosq_port_bandwidth_get
   9479  * Purpose:
   9480  *     Get COS queue bandwidth control configuration
   9481  * Parameters:
   9482  *     unit   - (IN) unit number
   9483  *     port   - (IN) port number
   9484  *     cosq   - (IN) COS queue number
   9485  *     min_quantum   - (OUT) minimum bandwidth, kbits/sec
   9486  *     max_quantum   - (OUT) maximum bandwidth, kbits/sec
   9487  *     burst_quantum - (OUT) burst size, kbits/sec
   9488  *     flags  - (OUT) BCM_COSQ_BW_XXX
   9489  * Returns:
   9490  *     BCM_E_XXX
   9491  */
   9492 int
   9493 bcm_hx5_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   9494                                  bcm_cos_queue_t cosq, uint32 *min_quantum,
   9495                                  uint32 *max_quantum, uint32 *burst_quantum,
   9496                                  uint32 *flags)
   9497 {
   9498     uint32 kbits_burst_min;
   9499 
   9500     if (cosq < -1) {
   9501         return BCM_E_PARAM;
   9502     }
   9503 
   9504     if (BCM_GPORT_IS_SET(port) &&
   9505         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   9506         BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9507         BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9508         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   9509         return BCM_E_UNAVAIL;
   9510     }
   9511 
   9512     BCM_IF_ERROR_RETURN
   9513         (_bcm_hx5_cosq_bucket_get(unit, port, cosq, min_quantum,
   9514                                   max_quantum, &kbits_burst_min,
   9515                                   burst_quantum, flags));
   9516 
   9517     return BCM_E_NONE;
   9518 }
   9519 
   9520 
   9521 /*
   9522  * Function:
   9523  *     bcm_hx5_cosq_port_pps_set
   9524  * Purpose:
   9525  *     Set the RX per-Cos rate limiting value
   9526  * Parameters:
   9527  *     unit     - (IN) unit number
   9528  *     port     - (IN) queue group GPORT identifier
   9529  *     cosq     - (IN) CoS to configure
   9530  *     pps      - (IN) Rate in packets/second
   9531  * Returns:
   9532  *     BCM_E_XXX
   9533  */
   9534 int
   9535 bcm_hx5_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9536         int pps)
   9537 {
   9538     uint32 min, max, burst, burst_min, flags;
   9539     bcm_port_t  local_port =  port;
   9540 
   9541     if (!IS_CPU_PORT(unit, port)) {
   9542         return BCM_E_PORT;
   9543     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   9544         return BCM_E_PARAM;
   9545     }
   9546 
   9547     if (BCM_GPORT_IS_SET(port) &&
   9548             ((BCM_GPORT_IS_SCHEDULER(port)) ||
   9549              BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) { 
   9550         return BCM_E_UNAVAIL;
   9551     }
   9552 
   9553     BCM_IF_ERROR_RETURN
   9554         (_bcm_hx5_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min,
   9555                                   &burst, &flags));
   9556 
   9557     min = pps;
   9558     burst_min = (min > 0) ?
   9559         _bcm_td_default_burst_size(unit, local_port, min) : 0;
   9560     burst = burst_min;
   9561 
   9562     return _bcm_hx5_cosq_bucket_set(unit, port, cosq, min, pps, burst_min,
   9563             burst, flags | BCM_COSQ_BW_PACKET_MODE);
   9564 }
   9565 
   9566 /*
   9567  * Function:
   9568  *     bcm_hx5_cosq_port_pps_get
   9569  * Purpose:
   9570  *     Get the RX per-Cos rate limiting value
   9571  * Parameters:
   9572  *     unit     - (IN) unit number
   9573  *     port     - (IN) queue group GPORT identifier
   9574  *     cosq     - (IN) COS queue number
   9575  *     pps      - (OUT) Rate in packets/second
   9576  * Returns:
   9577  *     BCM_E_XXX
   9578  */
   9579 int
   9580 bcm_hx5_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9581         int *pps)
   9582 {
   9583     uint32 min, max, burst, flags;
   9584 
   9585     if (!IS_CPU_PORT(unit, port)) {
   9586         return BCM_E_PORT;
   9587     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   9588         return BCM_E_PARAM;
   9589     }
   9590 
   9591     if (BCM_GPORT_IS_SET(port) &&
   9592             ((BCM_GPORT_IS_SCHEDULER(port)) ||
   9593              BCM_GPORT_IS_MCAST_QUEUE_GROUP(port))) {
   9594         return BCM_E_UNAVAIL;
   9595     }
   9596 
   9597     BCM_IF_ERROR_RETURN
   9598         (_bcm_hx5_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst,
   9599                                   &flags));
   9600 
   9601     *pps = max;
   9602 
   9603     return BCM_E_NONE;
   9604 }
   9605 
   9606 /*
   9607  * Function:
   9608  *     bcm_hx5_cosq_port_burst_set
   9609  * Purpose:
   9610  *     Set the per-Cos burst setting
   9611  * Parameters:
   9612  *     unit     - (IN) unit number
   9613  *     port     - (IN) queue group GPORT identifier
   9614  *     cosq     - (IN) CoS to configure
   9615  *     burst    - (IN) Burst rate for the system in packets
   9616  * Returns:
   9617  *     BCM_E_XXX
   9618  */
   9619 int
   9620 bcm_hx5_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9621         int burst)
   9622 {
   9623     uint32 min, max, cur_burst, flags;
   9624 
   9625     if (!IS_CPU_PORT(unit, port)) {
   9626         return BCM_E_PORT;
   9627     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   9628         return BCM_E_PARAM;
   9629     }
   9630 
   9631     if (BCM_GPORT_IS_SET(port) &&
   9632             ((BCM_GPORT_IS_SCHEDULER(port)) ||
   9633              BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9634              BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9635              BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   9636         return BCM_E_UNAVAIL;
   9637     }
   9638 
   9639     BCM_IF_ERROR_RETURN
   9640         (_bcm_hx5_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst,
   9641                                   &cur_burst, &flags));
   9642 
   9643     /* Replace the current BURST setting, keep PPS the same */
   9644     return _bcm_hx5_cosq_bucket_set(unit, port, cosq, min, max, burst, burst,
   9645             flags | BCM_COSQ_BW_PACKET_MODE);
   9646 }
   9647 
   9648 /*
   9649  * Function:
   9650  *     bcm_hx5_cosq_port_burst_set
   9651  * Purpose:
   9652  *     Get the per-Cos burst setting
   9653  * Parameters:
   9654  *     unit     - (IN) unit number
   9655  *     port     - (IN) queue group GPORT identifier
   9656  *     cosq     - (IN) CoS queue number
   9657  *     burst    - (OUT) Burst rate for the system in packets
   9658  * Returns:
   9659  *     BCM_E_XXX
   9660  */
   9661 int
   9662 bcm_hx5_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   9663         int *burst)
   9664 {
   9665     uint32 min, max, cur_burst, cur_burst_min, flags;
   9666 
   9667     if (!IS_CPU_PORT(unit, port)) {
   9668         return BCM_E_PORT;
   9669     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   9670         return BCM_E_PARAM;
   9671     }
   9672 
   9673     if (BCM_GPORT_IS_SET(port) &&
   9674             ((BCM_GPORT_IS_SCHEDULER(port)) ||
   9675              BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9676              BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   9677              BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   9678         return BCM_E_UNAVAIL;
   9679     }
   9680 
   9681     BCM_IF_ERROR_RETURN
   9682         (_bcm_hx5_cosq_bucket_get(unit, port, cosq, &min, &max,
   9683                                   &cur_burst_min, &cur_burst, &flags));
   9684 
   9685     *burst = cur_burst;
   9686 
   9687     return BCM_E_NONE;
   9688 }
   9689 
   9690 STATIC int
   9691 _bcm_hx5_cosq_obmhighwatermark_set(int unit, bcm_port_t port, uint64 value)
   9692 {
   9693     int pipe, obm_id, lane;
   9694     soc_reg_t reg;
   9695     uint64 rval64;
   9696     soc_info_t *si;
   9697     soc_reg_t obm_high_watermark_reg[] = {
   9698         /* PM4x10Q */
   9699         IDB_OBM0_Q_MAX_USAGEr, IDB_OBM1_Q_MAX_USAGEr, IDB_OBM2_Q_MAX_USAGEr,
   9700         /* PM4x10 */
   9701         IDB_OBM0_MAX_USAGEr, IDB_OBM1_MAX_USAGEr, IDB_OBM2_MAX_USAGEr, IDB_OBM3_MAX_USAGEr,
   9702         /* PM4x25 */
   9703         IDB_OBM0_48_MAX_USAGEr, IDB_OBM1_48_MAX_USAGEr, IDB_OBM2_48_MAX_USAGEr,
   9704     };
   9705 
   9706 
   9707     soc_field_t obm_high_watermark_fields[] = {
   9708         PORT0_MAX_USAGEf, PORT1_MAX_USAGEf,
   9709         PORT2_MAX_USAGEf, PORT3_MAX_USAGEf
   9710     };
   9711 
   9712     SOC_IF_ERROR_RETURN
   9713         (soc_helix5_port_obm_info_get(unit, port, &obm_id, &lane));
   9714     if (obm_id >= _HX5_OBMS_PER_PIPE ||
   9715         (lane < 0 || lane >= _HX5_PORTS_PER_PBLK)) {
   9716         return BCM_E_PARAM;
   9717     }
   9718     if(!COMPILER_64_IS_ZERO(value)) {
   9719         return BCM_E_PARAM;
   9720     }
   9721     si = &SOC_INFO(unit);
   9722     pipe = si->port_pipe[port];
   9723 
   9724     reg = SOC_REG_UNIQUE_ACC(unit, obm_high_watermark_reg[obm_id])[pipe];
   9725     COMPILER_64_ZERO(rval64);
   9726     BCM_IF_ERROR_RETURN
   9727             (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64));
   9728 
   9729     soc_reg64_field32_set(unit, reg, &rval64, obm_high_watermark_fields[lane], 0);
   9730     BCM_IF_ERROR_RETURN
   9731             (soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval64));
   9732     return BCM_E_NONE;
   9733 }
   9734 
   9735 STATIC int
   9736 _bcm_hx5_cosq_obmhighwatermark_get(int unit, bcm_port_t port, uint64 *value)
   9737 {
   9738     int pipe, obm_id, lane;
   9739     soc_reg_t reg;
   9740     uint64 rval64;
   9741     soc_info_t *si;
   9742     soc_reg_t obm_high_watermark_reg[] = {
   9743         /* PM4x10Q */
   9744         IDB_OBM0_Q_MAX_USAGEr, IDB_OBM1_Q_MAX_USAGEr, IDB_OBM2_Q_MAX_USAGEr,
   9745         /* PM4x10 */
   9746         IDB_OBM0_MAX_USAGEr, IDB_OBM1_MAX_USAGEr, IDB_OBM2_MAX_USAGEr, IDB_OBM3_MAX_USAGEr,
   9747         /* PM4x25 */
   9748         IDB_OBM0_48_MAX_USAGEr, IDB_OBM1_48_MAX_USAGEr, IDB_OBM2_48_MAX_USAGEr,
   9749     };
   9750 
   9751     soc_field_t obm_high_watermark_fields[] = {
   9752         PORT0_MAX_USAGEf, PORT1_MAX_USAGEf,
   9753         PORT2_MAX_USAGEf, PORT3_MAX_USAGEf
   9754     };
   9755 
   9756     SOC_IF_ERROR_RETURN
   9757         (soc_helix5_port_obm_info_get(unit, port, &obm_id, &lane));
   9758     if (obm_id >= _HX5_OBMS_PER_PIPE ||
   9759         (lane < 0 || lane >= _HX5_PORTS_PER_PBLK)) {
   9760         return BCM_E_PARAM;
   9761     }
   9762     si = &SOC_INFO(unit);
   9763     pipe = si->port_pipe[port];
   9764 
   9765     reg = SOC_REG_UNIQUE_ACC(unit, obm_high_watermark_reg[obm_id])[pipe];
   9766     COMPILER_64_ZERO(rval64);
   9767     BCM_IF_ERROR_RETURN
   9768             (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval64));
   9769 
   9770     *value = soc_reg64_field_get(unit, reg, rval64, obm_high_watermark_fields[lane]);
   9771     COMPILER_64_UMUL_32(*value, 16);    /* 16B cell granularity. */
   9772 
   9773     return BCM_E_NONE;
   9774 }
   9775 
   9776 STATIC int
   9777 _bcm_hx5_cosq_obm_buf_use_cnt_set(int unit, bcm_port_t port, uint64 value)
   9778 {
   9779     int pipe, obm_id, lane;
   9780     soc_reg_t reg;
   9781     soc_field_t fld;
   9782     uint64 rval64;
   9783     soc_info_t *si;
   9784     soc_reg_t obm_usage_reg[] = {
   9785         /* PM4x10Q */
   9786         IDB_OBM0_Q_USAGEr, IDB_OBM1_Q_USAGEr, IDB_OBM2_Q_USAGEr,
   9787         /* PM4x10 */
   9788         IDB_OBM0_USAGEr, IDB_OBM1_USAGEr, IDB_OBM2_USAGEr, IDB_OBM3_USAGEr,
   9789         /* PM4x25 */
   9790         IDB_OBM0_48_USAGEr, IDB_OBM1_48_USAGEr, IDB_OBM2_48_USAGEr,
   9791     };
   9792 
   9793     SOC_IF_ERROR_RETURN
   9794             (soc_helix5_port_obm_info_get(unit, port, &obm_id, &lane));
   9795     if (obm_id >= _HX5_OBMS_PER_PIPE || (lane < 0 || lane >= _HX5_PORTS_PER_PBLK)) {
   9796         return BCM_E_PARAM;
   9797     }
   9798     if(!COMPILER_64_IS_ZERO(value)) {
   9799         return BCM_E_PARAM;
   9800     }
   9801     si = &SOC_INFO(unit);
   9802     pipe = si->port_pipe[port];
   9803 
   9804     reg = SOC_REG_UNIQUE_ACC(unit, obm_usage_reg[obm_id])[pipe];
   9805     fld = si->mmu_lossless ? LOSSLESS0_COUNTf : LOSSY_COUNTf;
   9806     COMPILER_64_ZERO(rval64);
   9807     BCM_IF_ERROR_RETURN
   9808             (soc_reg64_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   9809 
   9810     soc_reg64_field_set(unit, reg, &rval64, fld, value);
   9811     BCM_IF_ERROR_RETURN
   9812             (soc_reg64_set(unit, reg, REG_PORT_ANY, lane, rval64));
   9813     return BCM_E_NONE;
   9814 }
   9815 
   9816 STATIC int
   9817 _bcm_hx5_cosq_obm_buf_use_cnt_get(int unit, bcm_port_t port, uint64 *value)
   9818 {
   9819     int pipe, obm_id, lane;
   9820     soc_reg_t reg;
   9821     soc_field_t fld;
   9822     uint64 rval64;
   9823     soc_info_t *si;
   9824     soc_reg_t obm_usage_reg[] = {
   9825         /* PM4x10Q */
   9826         IDB_OBM0_Q_USAGEr, IDB_OBM1_Q_USAGEr, IDB_OBM2_Q_USAGEr,
   9827         /* PM4x10 */
   9828         IDB_OBM0_USAGEr, IDB_OBM1_USAGEr, IDB_OBM2_USAGEr, IDB_OBM3_USAGEr,
   9829         /* PM4x25 */
   9830         IDB_OBM0_48_USAGEr, IDB_OBM1_48_USAGEr, IDB_OBM2_48_USAGEr,
   9831     };
   9832 
   9833     SOC_IF_ERROR_RETURN
   9834             (soc_helix5_port_obm_info_get(unit, port, &obm_id, &lane));
   9835     if (obm_id >= _HX5_OBMS_PER_PIPE || (lane < 0 || lane >= _HX5_PORTS_PER_PBLK)) {
   9836         return BCM_E_PARAM;
   9837     }
   9838     si = &SOC_INFO(unit);
   9839     pipe = si->port_pipe[port];
   9840 
   9841     reg = SOC_REG_UNIQUE_ACC(unit, obm_usage_reg[obm_id])[pipe];
   9842     fld = si->mmu_lossless ? LOSSLESS0_COUNTf : LOSSY_COUNTf;
   9843     COMPILER_64_ZERO(rval64);
   9844     BCM_IF_ERROR_RETURN
   9845             (soc_reg64_get(unit, reg, REG_PORT_ANY, lane, &rval64));
   9846 
   9847     *value = soc_reg64_field_get(unit, reg, rval64, fld);
   9848     COMPILER_64_UMUL_32(*value, 16);    /* 16B cell granularity. */
   9849 
   9850     return BCM_E_NONE;
   9851 }
   9852 
   9853 /*
   9854  * Function:
   9855  *      bcm_hx5_cosq_stat_set
   9856  * Purpose:
   9857  *      Set MMU statistics on a per port per cosq basis.
   9858  * Parameters:
   9859  *      unit  - (IN) Unit number.
   9860  *      port  - (IN) GPORT ID
   9861  *      cosq  - (IN) COS queue.
   9862  *      stat  - (IN) Statistic to be set.
   9863  *      value - (IN) Statistic value to be set.
   9864  * Returns:
   9865  *      BCM_E_xxx
   9866  * Notes:
   9867  */
   9868 int
   9869 bcm_hx5_cosq_stat_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   9870                      bcm_cosq_stat_t stat, uint64 value)
   9871 {
   9872     soc_ctr_control_info_t ctrl_info;
   9873     soc_reg_t ctr_reg, ctr_reg_uc, ctr_reg_mc;
   9874     _bcm_hx5_cosq_index_style_t style = _BCM_HX5_COSQ_INDEX_STYLE_COUNT;
   9875     int startq = 0, ci, from_cos, to_cos;
   9876     bcm_port_t local_port = -1;
   9877     soc_info_t *si = &SOC_INFO(unit);
   9878 
   9879     ctrl_info.instance = -1;
   9880     ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE;
   9881 
   9882     BCM_IF_ERROR_RETURN
   9883         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
   9884     if ((cosq < -1) || (cosq >= si->port_num_cosq[local_port])) {
   9885         return BCM_E_PARAM;
   9886     }
   9887 
   9888     switch (stat) {
   9889         case bcmCosqStatDroppedPackets:
   9890         case bcmCosqStatDroppedBytes:
   9891         case bcmCosqStatOutPackets:
   9892         case bcmCosqStatOutBytes:
   9893             style = _BCM_HX5_COSQ_INDEX_STYLE_COS;
   9894             if (stat == bcmCosqStatDroppedBytes) {
   9895                 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC;
   9896                 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE;
   9897             } else if (stat == bcmCosqStatDroppedPackets) {
   9898                 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC;
   9899                 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT;
   9900             } else if (stat == bcmCosqStatOutBytes) {
   9901                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC;
   9902                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
   9903                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
   9904             } else { /* (stat == bcmCosqStatOutPackets) */
   9905                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC;
   9906                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT;
   9907                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
   9908             }
   9909             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   9910                 if (ctr_reg_uc != INVALIDr) {
   9911                     BCM_IF_ERROR_RETURN
   9912                         (_bcm_hx5_cosq_index_resolve
   9913                          (unit, port, cosq, style, &local_port, &startq, NULL));
   9914 
   9915                     ctrl_info.instance = local_port;
   9916                     startq = startq - si->port_uc_cosq_base[local_port];
   9917                     BCM_IF_ERROR_RETURN
   9918                         (soc_counter_generic_set(unit, ctr_reg_uc, ctrl_info, 0,
   9919                                                  startq, value));
   9920                 }
   9921             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9922                 if (ctr_reg_mc != INVALIDr) {
   9923                     BCM_IF_ERROR_RETURN
   9924                         (_bcm_hx5_cosq_index_resolve
   9925                          (unit, port, cosq, style, &local_port, &startq, NULL));
   9926 
   9927                     ctrl_info.instance = local_port;
   9928                     startq = startq - si->port_cosq_base[local_port];
   9929                     BCM_IF_ERROR_RETURN
   9930                         (soc_counter_generic_set(unit, ctr_reg_mc, ctrl_info, 0,
   9931                                                  startq, value));
   9932                 }
   9933             } else {
   9934                 if (BCM_GPORT_IS_SCHEDULER(port)) {
   9935                     BCM_IF_ERROR_RETURN
   9936                         (_bcm_hx5_cosq_index_resolve
   9937                          (unit, port, cosq, style, &local_port, &startq, NULL));
   9938                     from_cos = to_cos = startq;
   9939                 } else {
   9940                     BCM_IF_ERROR_RETURN
   9941                         (_bcm_hx5_cosq_localport_resolve(unit, port,
   9942                                                         &local_port));
   9943 
   9944                     if (cosq == BCM_COS_INVALID) {
   9945                         /* if (cosq == -1) set value for the first cosq */
   9946                         cosq = 0;
   9947                     }
   9948                     from_cos = to_cos = cosq;
   9949                 }
   9950                 ctrl_info.instance = local_port;
   9951                 for (ci = from_cos; ci <= to_cos; ci++) {
   9952                     if (!IS_CPU_PORT(unit, local_port)) {
   9953                         if (ctr_reg_uc != INVALIDr) {
   9954                             /* Set UC values if NOT CPU port */
   9955                             BCM_IF_ERROR_RETURN
   9956                                 (soc_counter_generic_set(unit, ctr_reg_uc,
   9957                                                          ctrl_info, 0,
   9958                                                          ci, value));
   9959                         }
   9960                     }
   9961 
   9962                     if (ctr_reg_mc != INVALIDr) {
   9963                         BCM_IF_ERROR_RETURN
   9964                             (soc_counter_generic_set(unit, ctr_reg_mc,
   9965                                                      ctrl_info, 0, ci, value));
   9966                     }
   9967                 }
   9968             }
   9969             break;
   9970         case bcmCosqStatYellowCongestionDroppedPackets:
   9971         case bcmCosqStatRedCongestionDroppedPackets:
   9972         case bcmCosqStatGreenDiscardDroppedPackets:
   9973         case bcmCosqStatYellowDiscardDroppedPackets:
   9974         case bcmCosqStatRedDiscardDroppedPackets:
   9975             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   9976                 BCM_GPORT_IS_SCHEDULER(port) ||
   9977                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   9978                 return BCM_E_PARAM;
   9979             }
   9980             if (cosq != BCM_COS_INVALID) {
   9981                 return BCM_E_UNAVAIL;
   9982             }
   9983             if (stat == bcmCosqStatYellowCongestionDroppedPackets) {
   9984                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW;
   9985             } else if (stat == bcmCosqStatRedCongestionDroppedPackets) {
   9986                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED;
   9987             } else if (stat == bcmCosqStatYellowDiscardDroppedPackets) {
   9988                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW;
   9989             } else if (stat == bcmCosqStatRedDiscardDroppedPackets) {
   9990                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED;
   9991             } else {
   9992                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN;
   9993             }
   9994             BCM_IF_ERROR_RETURN
   9995                 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
   9996 
   9997             ctrl_info.instance = local_port;
   9998             BCM_IF_ERROR_RETURN
   9999                 (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0,
  10000                                          startq, value));
  10001             break;
  10002         case bcmCosqStatHighPriDroppedPackets:
  10003         case bcmCosqStatOBMLossyHighPriDroppedPackets:
  10004         case bcmCosqStatLowPriDroppedPackets:
  10005         case bcmCosqStatOBMLossyLowPriDroppedPackets:
  10006         case bcmCosqStatHighPriDroppedBytes:
  10007         case bcmCosqStatOBMLossyHighPriDroppedBytes:
  10008         case bcmCosqStatLowPriDroppedBytes:
  10009         case bcmCosqStatOBMLossyLowPriDroppedBytes:
  10010         case bcmCosqStatOBMLossless0DroppedPackets:
  10011         case bcmCosqStatOBMLossless1DroppedPackets:
  10012         case bcmCosqStatOBMLossless0DroppedBytes:
  10013         case bcmCosqStatOBMLossless1DroppedBytes:
  10014         case bcmCosqStatOBMFlowControlEvents:
  10015             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10016                 BCM_GPORT_IS_SCHEDULER(port) ||
  10017                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10018                 return BCM_E_PARAM;
  10019             }
  10020             if ((stat == bcmCosqStatHighPriDroppedPackets) ||
  10021                 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) {
  10022                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI;
  10023             } else if ((stat == bcmCosqStatLowPriDroppedPackets) ||
  10024                        (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) {
  10025                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO;
  10026             } else if ((stat == bcmCosqStatHighPriDroppedBytes) ||
  10027                        (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) {
  10028                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI;
  10029             } else if ((stat == bcmCosqStatLowPriDroppedBytes) ||
  10030                        (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) {
  10031                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO;
  10032             } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) {
  10033                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0;
  10034             } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) {
  10035                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1;
  10036             } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) {
  10037                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0;
  10038             } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) {
  10039                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1;
  10040             } else { /* (stat == bcmCosqStatOBMFlowControlEvents) */
  10041                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_OBM_FC_EVENTS;
  10042             }
  10043             ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  10044             ctrl_info.instance = local_port;
  10045             BCM_IF_ERROR_RETURN
  10046                 (soc_counter_generic_set(unit, ctr_reg, ctrl_info, 0,
  10047                                          0, value));
  10048             break;
  10049         case bcmCosqStatOBMHighWatermark:
  10050         case bcmCosqStatOBMBufferBytes:
  10051             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10052                 BCM_GPORT_IS_SCHEDULER(port) ||
  10053                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10054                 return BCM_E_PARAM;
  10055             }
  10056             if (stat == bcmCosqStatOBMHighWatermark) {
  10057                 BCM_IF_ERROR_RETURN
  10058                     (_bcm_hx5_cosq_obmhighwatermark_set(unit, local_port, value));
  10059             } else { /* stat == bcmCosqStatOBMBufferBytes */
  10060                 BCM_IF_ERROR_RETURN
  10061                     (_bcm_hx5_cosq_obm_buf_use_cnt_set(unit, local_port, value));
  10062             }
  10063             break;
  10064         default:
  10065             return BCM_E_PARAM;
  10066     }
  10067 
  10068     return BCM_E_NONE;
  10069 }
  10070 
  10071 /*
  10072  * Function:
  10073  *      bcm_hx5_cosq_stat_get
  10074  * Purpose:
  10075  *      Get MMU statistics on a per port per cosq basis.
  10076  * Parameters:
  10077  *      unit      - (IN) Unit number.
  10078  *      port      - (IN) GPORT ID.
  10079  *      cosq      - (IN) COS queue.
  10080  *      stat      - (IN) Statistic to be retrieved.
  10081  *      sync_mode - (IN) whether to sync before read.
  10082  *      value     - (OUT) Returned statistic value.
  10083  * Returns:
  10084  *      BCM_E_xxx
  10085  * Notes:
  10086  */
  10087 int
  10088 bcm_hx5_cosq_stat_get(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
  10089                      bcm_cosq_stat_t stat, int sync_mode, uint64 *value)
  10090 {
  10091     soc_ctr_control_info_t ctrl_info;
  10092     soc_reg_t ctr_reg, ctr_reg_uc, ctr_reg_mc;
  10093     _bcm_hx5_cosq_index_style_t style = _BCM_HX5_COSQ_INDEX_STYLE_COUNT;
  10094     uint64 sum, value64;
  10095     int startq = 0, ci, from_cos, to_cos, i, start_hw_index, end_hw_index;
  10096     bcm_port_t local_port = -1;
  10097     int sync = sync_mode ? SOC_COUNTER_SYNC_ENABLE : 0;
  10098     soc_info_t *si = &SOC_INFO(unit);
  10099 
  10100     BCM_IF_ERROR_RETURN
  10101         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  10102     ctrl_info.instance = -1;
  10103     ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE;
  10104 
  10105     switch (stat) {
  10106         case bcmCosqStatDroppedPackets:
  10107         case bcmCosqStatDroppedBytes:
  10108         case bcmCosqStatOutPackets:
  10109         case bcmCosqStatOutBytes:
  10110         case bcmCosqStatEgressMCQueueBytesPeak:
  10111         case bcmCosqStatEgressMCQueueBytesCurrent:
  10112         case bcmCosqStatEgressUCQueueBytesPeak:
  10113         case bcmCosqStatEgressUCQueueBytesCurrent:
  10114             if ((cosq < -1) || (cosq >=  si->port_num_cosq[local_port])) {
  10115                 return BCM_E_PARAM;
  10116             }
  10117             style = _BCM_HX5_COSQ_INDEX_STYLE_COS;
  10118             if (stat == bcmCosqStatEgressMCQueueBytesPeak) {
  10119                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10120                     BCM_GPORT_IS_SCHEDULER(port)) {
  10121                     return BCM_E_PARAM;
  10122                 }
  10123                 ctr_reg_uc = INVALIDr;
  10124                 ctr_reg_mc = SOC_COUNTER_NON_DMA_QUEUE_PEAK;
  10125             } else if (stat == bcmCosqStatEgressMCQueueBytesCurrent) {
  10126                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10127                     BCM_GPORT_IS_SCHEDULER(port)) {
  10128                     return BCM_E_PARAM;
  10129                 }
  10130                 ctr_reg_uc = INVALIDr;
  10131                 ctr_reg_mc = SOC_COUNTER_NON_DMA_QUEUE_CURRENT;
  10132             } else if (stat == bcmCosqStatEgressUCQueueBytesPeak) {
  10133                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
  10134                     BCM_GPORT_IS_SCHEDULER(port)) {
  10135                     return BCM_E_PARAM;
  10136                 }
  10137                 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10138                     BCM_IF_ERROR_RETURN
  10139                         (_bcm_hx5_cosq_localport_resolve(unit, port,
  10140                                                          &local_port));
  10141                     if (IS_CPU_PORT(unit, local_port))
  10142                     {
  10143                         return BCM_E_PARAM;
  10144                     }
  10145                 }
  10146                 ctr_reg_uc = SOC_COUNTER_NON_DMA_UC_QUEUE_PEAK;
  10147                 ctr_reg_mc = INVALIDr;
  10148             } else if (stat == bcmCosqStatEgressUCQueueBytesCurrent) {
  10149                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
  10150                     BCM_GPORT_IS_SCHEDULER(port)) {
  10151                     return BCM_E_PARAM;
  10152                 }
  10153                 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10154                     BCM_IF_ERROR_RETURN
  10155                         (_bcm_hx5_cosq_localport_resolve(unit, port,
  10156                                                          &local_port));
  10157                     if (IS_CPU_PORT(unit, local_port))
  10158                     {
  10159                         return BCM_E_PARAM;
  10160                     }
  10161                 }
  10162                 ctr_reg_uc = SOC_COUNTER_NON_DMA_UC_QUEUE_CURRENT;
  10163                 ctr_reg_mc = INVALIDr;
  10164             } else if (stat == bcmCosqStatDroppedBytes) {
  10165                 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE_UC;
  10166                 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_BYTE;
  10167             } else if (stat == bcmCosqStatDroppedPackets) {
  10168                 ctr_reg_uc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT_UC;
  10169                 ctr_reg_mc = SOC_COUNTER_NON_DMA_COSQ_DROP_PKT;
  10170             } else if (stat == bcmCosqStatOutBytes) {
  10171                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE_UC;
  10172                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_BYTE;
  10173                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  10174             } else { /* (stat == bcmCosqStatOutPackets) */
  10175                 ctr_reg_uc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT_UC;
  10176                 ctr_reg_mc = SOC_COUNTER_NON_DMA_EGR_PERQ_XMT_PKT;
  10177                 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  10178             }
  10179             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
  10180                 if (ctr_reg_uc != INVALIDr) {
  10181                     BCM_IF_ERROR_RETURN
  10182                         (_bcm_hx5_cosq_index_resolve
  10183                          (unit, port, cosq, style, &local_port, &startq, NULL));
  10184 
  10185                     startq = startq - si->port_uc_cosq_base[local_port];
  10186                     ctrl_info.instance = local_port;
  10187                     BCM_IF_ERROR_RETURN
  10188                         (soc_counter_generic_get(unit, ctr_reg_uc, ctrl_info,
  10189                                                  sync, startq, value));
  10190                 }
  10191             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10192                 if (ctr_reg_mc != INVALIDr) {
  10193                     BCM_IF_ERROR_RETURN
  10194                         (_bcm_hx5_cosq_index_resolve
  10195                          (unit, port, cosq, style, &local_port, &startq, NULL));
  10196                     ctrl_info.instance = local_port;
  10197                     startq = startq - si->port_cosq_base[local_port];
  10198                     BCM_IF_ERROR_RETURN
  10199                         (soc_counter_generic_get(unit, ctr_reg_mc, ctrl_info,
  10200                                                  sync, startq, value));
  10201                 }
  10202             } else {
  10203                 if (BCM_GPORT_IS_SCHEDULER(port)) {
  10204                     BCM_IF_ERROR_RETURN
  10205                         (_bcm_hx5_cosq_index_resolve
  10206                          (unit, port, cosq, style, &local_port, &startq, NULL));
  10207                     from_cos = to_cos = startq;
  10208                 } else {
  10209                     BCM_IF_ERROR_RETURN
  10210                         (_bcm_hx5_cosq_localport_resolve(unit, port,
  10211                                                         &local_port));
  10212 
  10213                     if (cosq == BCM_COS_INVALID) {
  10214                         from_cos = 0;
  10215                         to_cos = (IS_CPU_PORT(unit, local_port)) ? \
  10216                             NUM_CPU_COSQ(unit) - 1 : _BCM_HX5_NUM_COS(unit) - 1;
  10217                     } else {
  10218                         from_cos = to_cos = cosq;
  10219                     }
  10220                 }
  10221                 COMPILER_64_ZERO(sum);
  10222                 ctrl_info.instance = local_port;
  10223                 for (ci = from_cos; ci <= to_cos; ci++) {
  10224 
  10225                     if (!IS_CPU_PORT(unit, local_port)) {
  10226                         /* Get UC values if NOT CPU port */
  10227                         if (ctr_reg_uc != INVALIDr) {
  10228                             BCM_IF_ERROR_RETURN
  10229                                 (soc_counter_generic_get(unit, ctr_reg_uc,
  10230                                                          ctrl_info,
  10231                                                          sync, ci, &value64));
  10232                             COMPILER_64_ADD_64(sum, value64);
  10233                         }
  10234                     }
  10235 
  10236                     if (ctr_reg_mc != INVALIDr) {
  10237                         BCM_IF_ERROR_RETURN
  10238                             (soc_counter_generic_get(unit, ctr_reg_mc,
  10239                                                      ctrl_info,
  10240                                                      sync, ci, &value64));
  10241                         COMPILER_64_ADD_64(sum, value64);
  10242                     }
  10243                 }
  10244                 *value = sum;
  10245             }
  10246             break;
  10247         case bcmCosqStatYellowCongestionDroppedPackets:
  10248         case bcmCosqStatRedCongestionDroppedPackets:
  10249         case bcmCosqStatGreenDiscardDroppedPackets:
  10250         case bcmCosqStatYellowDiscardDroppedPackets:
  10251         case bcmCosqStatRedDiscardDroppedPackets:
  10252             if ((cosq < -1) || (cosq >=  si->port_num_cosq[local_port])) {
  10253                 return BCM_E_PARAM;
  10254             }
  10255 
  10256             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10257                 BCM_GPORT_IS_SCHEDULER(port) ||
  10258                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10259                 return BCM_E_PARAM;
  10260             }
  10261             if (cosq != BCM_COS_INVALID) {
  10262                 return BCM_E_UNAVAIL;
  10263             }
  10264             if (stat == bcmCosqStatYellowCongestionDroppedPackets) {
  10265                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_YELLOW;
  10266             } else if (stat == bcmCosqStatRedCongestionDroppedPackets) {
  10267                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_RED;
  10268             } else if (stat == bcmCosqStatYellowDiscardDroppedPackets) {
  10269                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_YELLOW;
  10270             } else if (stat == bcmCosqStatRedDiscardDroppedPackets) {
  10271                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_RED;
  10272             } else { /* (stat == bcmCosqStatGreenDiscardDroppedPackets) */
  10273                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_WRED_PKT_GREEN;
  10274             }
  10275             BCM_IF_ERROR_RETURN
  10276                 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  10277 
  10278             ctrl_info.instance = local_port;
  10279             BCM_IF_ERROR_RETURN
  10280                 (soc_counter_generic_get(unit, ctr_reg, ctrl_info,
  10281                                          sync, startq, value));
  10282             break;
  10283         case bcmCosqStatIngressPortPGMinBytesPeak:
  10284         case bcmCosqStatIngressPortPGMinBytesCurrent:
  10285         case bcmCosqStatIngressPortPGSharedBytesPeak:
  10286         case bcmCosqStatIngressPortPGSharedBytesCurrent:
  10287         case bcmCosqStatIngressPortPGHeadroomBytesPeak:
  10288         case bcmCosqStatIngressPortPGHeadroomBytesCurrent:
  10289             if (cosq < -1) {
  10290                 return BCM_E_PARAM;
  10291             }
  10292 
  10293             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10294                 BCM_GPORT_IS_SCHEDULER(port) ||
  10295                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10296                 return BCM_E_PARAM;
  10297             }
  10298             if (stat == bcmCosqStatIngressPortPGMinBytesPeak) {
  10299                 ctr_reg = SOC_COUNTER_NON_DMA_PG_MIN_PEAK;
  10300             } else if (stat == bcmCosqStatIngressPortPGMinBytesCurrent) {
  10301                 ctr_reg = SOC_COUNTER_NON_DMA_PG_MIN_CURRENT;
  10302             } else if (stat == bcmCosqStatIngressPortPGSharedBytesPeak) {
  10303                 ctr_reg = SOC_COUNTER_NON_DMA_PG_SHARED_PEAK;
  10304             } else if (stat == bcmCosqStatIngressPortPGSharedBytesCurrent) {
  10305                 ctr_reg = SOC_COUNTER_NON_DMA_PG_SHARED_CURRENT;
  10306             } else if (stat == bcmCosqStatIngressPortPGHeadroomBytesPeak) {
  10307                 ctr_reg = SOC_COUNTER_NON_DMA_PG_HDRM_PEAK;
  10308             } else {
  10309                 /* (stat == bcmCosqStatIngressPortPGHeadroomBytesCurrent) */
  10310                 ctr_reg = SOC_COUNTER_NON_DMA_PG_HDRM_CURRENT;
  10311             }
  10312             BCM_IF_ERROR_RETURN
  10313                 (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  10314             BCM_IF_ERROR_RETURN
  10315                 (_bcm_hx5_cosq_ingress_pg_get(unit, port, cosq,
  10316                                              &start_hw_index, &end_hw_index));
  10317 
  10318             COMPILER_64_ZERO(sum);
  10319             for (i = start_hw_index; i <= end_hw_index; i++) {
  10320                 ctrl_info.instance = local_port;
  10321                 BCM_IF_ERROR_RETURN
  10322                     (soc_counter_generic_get(unit, ctr_reg, ctrl_info,
  10323                                              sync, i, &value64));
  10324                 COMPILER_64_ADD_64(sum, value64);
  10325             }
  10326 
  10327             COMPILER_64_UMUL_32(sum, _HX5_MMU_BYTES_PER_CELL);
  10328             *value = sum;
  10329             break;
  10330         case bcmCosqStatIngressPortPoolSharedBytesPeak:
  10331             if (cosq < -1) {
  10332                 return BCM_E_PARAM;
  10333             }
  10334 
  10335             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10336                 BCM_GPORT_IS_SCHEDULER(port) ||
  10337                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10338                 return BCM_E_PARAM;
  10339             }
  10340             BCM_IF_ERROR_RETURN
  10341                 (_bcm_hx5_cosq_ingress_sp_get_by_pg(unit, port, cosq,
  10342                                              &start_hw_index, &end_hw_index));
  10343 
  10344             BCM_IF_ERROR_RETURN(
  10345                 _bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  10346 
  10347             ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE;
  10348             ctrl_info.instance = local_port;
  10349             ctr_reg = SOC_COUNTER_NON_DMA_POOL_PEAK;
  10350 
  10351             COMPILER_64_ZERO(sum);
  10352             for (i = start_hw_index; i <= end_hw_index; i++) {
  10353                 BCM_IF_ERROR_RETURN
  10354                     (soc_counter_generic_get(unit, ctr_reg, ctrl_info,
  10355                                              sync, i, &value64));
  10356                 COMPILER_64_ADD_64(sum, value64);
  10357             }
  10358 
  10359             COMPILER_64_UMUL_32(sum, _HX5_MMU_BYTES_PER_CELL);
  10360             *value = sum;
  10361             break;
  10362         case bcmCosqStatIngressPortPoolSharedBytesCurrent:
  10363             if (cosq < -1) {
  10364                 return BCM_E_PARAM;
  10365             }
  10366 
  10367             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10368                 BCM_GPORT_IS_SCHEDULER(port) ||
  10369                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10370                 return BCM_E_PARAM;
  10371             }
  10372             BCM_IF_ERROR_RETURN
  10373                 (_bcm_hx5_cosq_ingress_sp_get_by_pg(unit, port, cosq,
  10374                                              &start_hw_index, &end_hw_index));
  10375             BCM_IF_ERROR_RETURN(
  10376                 _bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  10377 
  10378             ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_XPE;
  10379             ctrl_info.instance = local_port;
  10380             ctr_reg = SOC_COUNTER_NON_DMA_POOL_CURRENT;
  10381 
  10382             COMPILER_64_ZERO(sum);
  10383             for (i = start_hw_index; i <= end_hw_index; i++) {
  10384                 BCM_IF_ERROR_RETURN
  10385                     (soc_counter_generic_get(unit, ctr_reg, ctrl_info,
  10386                                              sync, i, &value64));
  10387                COMPILER_64_ADD_64(sum, value64);
  10388             }
  10389 
  10390             COMPILER_64_UMUL_32(sum, _HX5_MMU_BYTES_PER_CELL);
  10391             *value = sum;
  10392             break;
  10393         case bcmCosqStatHighPriDroppedPackets:
  10394         case bcmCosqStatOBMLossyHighPriDroppedPackets:
  10395         case bcmCosqStatLowPriDroppedPackets:
  10396         case bcmCosqStatOBMLossyLowPriDroppedPackets:
  10397         case bcmCosqStatHighPriDroppedBytes:
  10398         case bcmCosqStatOBMLossyHighPriDroppedBytes:
  10399         case bcmCosqStatLowPriDroppedBytes:
  10400         case bcmCosqStatOBMLossyLowPriDroppedBytes:
  10401         case bcmCosqStatOBMLossless0DroppedPackets:
  10402         case bcmCosqStatOBMLossless1DroppedPackets:
  10403         case bcmCosqStatOBMLossless0DroppedBytes:
  10404         case bcmCosqStatOBMLossless1DroppedBytes:
  10405         case bcmCosqStatOBMFlowControlEvents:
  10406             if ((cosq < -1) || (cosq >=  si->port_num_cosq[local_port])) {
  10407                 return BCM_E_PARAM;
  10408             }
  10409 
  10410             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10411                 BCM_GPORT_IS_SCHEDULER(port) ||
  10412                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10413                 return BCM_E_PARAM;
  10414             }
  10415             if ((stat == bcmCosqStatHighPriDroppedPackets) ||
  10416                 (stat == bcmCosqStatOBMLossyHighPriDroppedPackets)) {
  10417                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI;
  10418             } else if ((stat == bcmCosqStatLowPriDroppedPackets) ||
  10419                        (stat == bcmCosqStatOBMLossyLowPriDroppedPackets)) {
  10420                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO;
  10421             } else if ((stat == bcmCosqStatHighPriDroppedBytes) ||
  10422                        (stat == bcmCosqStatOBMLossyHighPriDroppedBytes)) {
  10423                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI;
  10424             } else if ((stat == bcmCosqStatLowPriDroppedBytes) ||
  10425                        (stat == bcmCosqStatOBMLossyLowPriDroppedBytes)) {
  10426                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO;
  10427             } else if (stat == bcmCosqStatOBMLossless0DroppedPackets) {
  10428                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0;
  10429             } else if (stat == bcmCosqStatOBMLossless1DroppedPackets) {
  10430                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1;
  10431             } else if (stat == bcmCosqStatOBMLossless0DroppedBytes) {
  10432                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0;
  10433             } else if (stat == bcmCosqStatOBMLossless1DroppedBytes) {
  10434                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1;
  10435             } else { /* (stat == bcmCosqStatOBMFlowControlEvents) */
  10436                 ctr_reg = SOC_COUNTER_NON_DMA_PORT_OBM_FC_EVENTS;
  10437             }
  10438             ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT;
  10439             ctrl_info.instance = local_port;
  10440             BCM_IF_ERROR_RETURN
  10441                 (soc_counter_generic_get(unit, ctr_reg, ctrl_info, 0,
  10442                                          0, value));
  10443             break;
  10444         case bcmCosqStatOBMHighWatermark:
  10445         case bcmCosqStatOBMBufferBytes:
  10446             if ((cosq < -1) || (cosq >=  si->port_num_cosq[local_port])) {
  10447                 return BCM_E_PARAM;
  10448             }
  10449 
  10450             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
  10451                 BCM_GPORT_IS_SCHEDULER(port) ||
  10452                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
  10453                 return BCM_E_PARAM;
  10454             }
  10455             if (stat == bcmCosqStatOBMHighWatermark) {
  10456                 BCM_IF_ERROR_RETURN
  10457                     (_bcm_hx5_cosq_obmhighwatermark_get(unit, local_port, value));
  10458             } else { /* stat == bcmCosqStatOBMBufferBytes */
  10459                 BCM_IF_ERROR_RETURN
  10460                     (_bcm_hx5_cosq_obm_buf_use_cnt_get(unit, local_port, value));
  10461             }
  10462             break;
  10463         default:
  10464             return BCM_E_PARAM;
  10465     }
  10466 
  10467     return BCM_E_NONE;
  10468 }
  10469 
  10470 
  10471 STATIC int
  10472 _bcm_hx5_cosq_cpu_tree_create(int unit, bcm_port_t port)
  10473 {
  10474     int id, sc_id;
  10475     bcm_gport_t sched_gport[SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT];
  10476     bcm_gport_t cpu_mc_gport[SOC_HX5_NUM_CPU_QUEUES];
  10477     int numq = 1;
  10478 
  10479     /*Creating all L0,L1 and L2 scheduler nodes for cpu port  */
  10480     for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; id++) {
  10481         if (id == 1) {
  10482             numq = 10;
  10483         } else if (id >= 2 && id <= 11) {
  10484             numq = 48;
  10485         }
  10486 
  10487         BCM_IF_ERROR_RETURN
  10488             (_bcm_hx5_cosq_gport_add(unit, port, numq,
  10489                                      BCM_COSQ_GPORT_SCHEDULER,
  10490                                      &sched_gport[id]));
  10491     }
  10492 
  10493     /* Attaching L0 schedular node to front panel port */
  10494     BCM_IF_ERROR_RETURN
  10495         (bcm_hx5_cosq_gport_attach(unit, sched_gport[0], port, 0));
  10496 
  10497     /* Attaching L1 schedular node to L0 schedular node  */
  10498     BCM_IF_ERROR_RETURN
  10499         (bcm_hx5_cosq_gport_attach(unit, sched_gport[1],  sched_gport[0], 1));
  10500 
  10501     /* Attaching L2 schedular node to L1 schedular node  */
  10502     for (sc_id = 2; sc_id < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; sc_id++) {
  10503         BCM_IF_ERROR_RETURN
  10504             (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id],  sched_gport[1], sc_id));
  10505     }
  10506 
  10507     numq = 1;
  10508     for (id = 0; id < SOC_HX5_NUM_CPU_QUEUES; id++) {
  10509         BCM_IF_ERROR_RETURN
  10510             (_bcm_hx5_cosq_gport_add(unit, port, numq,
  10511                                      BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
  10512                                      &cpu_mc_gport[id]));
  10513         /* Attach all the 48 CPU MC queues to L2.0 node */
  10514         BCM_IF_ERROR_RETURN
  10515             (bcm_hx5_cosq_gport_attach(unit, cpu_mc_gport[id],
  10516                                        sched_gport[2], id));
  10517     }
  10518 
  10519     return BCM_E_NONE;
  10520 
  10521 
  10522 }
  10523 
  10524 /*
  10525  *  Function:
  10526  *      bcm_hx5_cosq_gport_child_get
  10527  *  Purpose:
  10528  *      Get the child node GPORT atatched to N-th index (cosq)
  10529  *      of the scheduler GPORT.
  10530  *  Parameters:
  10531  *      unit       - (IN)  Unit number.
  10532  *      in_gport   - (IN)  Scheduler GPORT ID.
  10533  *      cosq       - (IN)  COS queue attached to.
  10534  *      out_gport  - (OUT) Child GPORT ID.
  10535  *  Returns:
  10536  *       BCM_E_XXX
  10537  */
  10538 
  10539 int
  10540 bcm_hx5_cosq_gport_child_get(int unit, bcm_gport_t in_gport,
  10541         bcm_cos_queue_t cosq, bcm_gport_t *out_gport)
  10542 {
  10543     _bcm_hx5_cosq_node_t *tmp_node = NULL;
  10544     bcm_port_t local_port = -1;
  10545     _bcm_hx5_cosq_cpu_port_info_t *port_info = NULL;
  10546     int index = -1, cpu_mc_base = 0;
  10547     soc_info_t *si = &SOC_INFO(unit);
  10548 
  10549     if (out_gport == NULL) {
  10550         return BCM_E_PARAM;
  10551     }
  10552 
  10553     BCM_IF_ERROR_RETURN
  10554         (_bcm_hx5_cosq_localport_resolve(unit, in_gport, &local_port));
  10555 
  10556     if (!SOC_PORT_VALID(unit, local_port)) {
  10557         return BCM_E_PORT;
  10558     }
  10559 
  10560     /* This API is only supported for CPU ports because
  10561      *        for all other ports we have fixed hierarchy */
  10562     if (!IS_CPU_PORT(unit, local_port)) {
  10563         return BCM_E_PARAM;
  10564     }
  10565     
  10566     if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) {
  10567         return BCM_E_PARAM;
  10568     }
  10569 
  10570     if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) {
  10571         return BCM_E_INIT;
  10572     }
  10573 
  10574     port_info = _bcm_hx5_cosq_cpu_port_info[unit];
  10575     cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
  10576 
  10577     if (BCM_GPORT_IS_SCHEDULER(in_gport)) {
  10578         for (index = 0; index < SOC_HX5_NUM_CPU_QUEUES; index++) {
  10579             if (port_info->mcast[index].parent_gport == in_gport) {
  10580                 if (cosq == ((port_info->mcast[index].hw_index - cpu_mc_base) %
  10581                             SOC_HX5_NUM_CPU_QUEUES)) {
  10582                     tmp_node = &port_info->mcast[index];
  10583                     break;
  10584                 }
  10585             }
  10586         }
  10587     } else {
  10588         return BCM_E_PARAM;
  10589     }
  10590 
  10591     if (tmp_node == NULL) {
  10592         return BCM_E_NOT_FOUND;
  10593     }
  10594 
  10595     *out_gport = tmp_node->gport;
  10596 
  10597     return BCM_E_NONE;
  10598 }
  10599 
  10600 /*
  10601  * Function:
  10602  *      _bcm_hx5_cosq_gport_tree_create
  10603  * Purpose:
  10604  *      During cosq init create the default cosq gport tree.
  10605  *      Schedualar (L0) nodes are created and attach to physical ports.
  10606  *      UC and MC queues are added and attached to each L0 nodes.
  10607  * Parameters:
  10608  *      unit - (IN) unit number.
  10609  *      port - (IN) port number
  10610  * Returns:
  10611  *     BCM_E_XXX
  10612  */
  10613 STATIC int
  10614 _bcm_hx5_cosq_gport_tree_create(int unit, bcm_port_t port)
  10615 {
  10616     int id, sc_id;
  10617     bcm_gport_t sched_gport[SOC_HX5_NUM_SCHEDULER_PER_PORT];
  10618     bcm_gport_t uc_gport[SOC_HX5_NUM_UCAST_QUEUE_PER_PORT];
  10619     bcm_gport_t mc_gport[SOC_HX5_NUM_MCAST_QUEUE_PER_PORT];
  10620     int numq = 1;
  10621 
  10622     /*Creating all L0,L1 and L2 scheduler nodes */
  10623     for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_PORT; id++) {
  10624         if (id == 0 || id >= 3) {
  10625            numq = 2;
  10626         } else if(id > 0 && id < 3) {
  10627            numq = 8;
  10628         }
  10629         BCM_IF_ERROR_RETURN
  10630             (_bcm_hx5_cosq_gport_add(unit, port, numq,
  10631                                      BCM_COSQ_GPORT_SCHEDULER,
  10632                                      &sched_gport[id]));
  10633     }
  10634 
  10635     /* Attaching L0 schedular node to front panel port */
  10636     BCM_IF_ERROR_RETURN
  10637         (bcm_hx5_cosq_gport_attach(unit, sched_gport[0], port, 0));
  10638 
  10639     /* Attaching L1 schedular nodes to L0 schedular node */
  10640     for(sc_id = 1; sc_id < 3; sc_id++){
  10641         BCM_IF_ERROR_RETURN
  10642             (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], sched_gport[0], sc_id));
  10643     }
  10644     /* Attaching L2 schedular nodes to L1 schedular node */
  10645     for(sc_id = 3; sc_id < SOC_HX5_NUM_SCHEDULER_PER_PORT; sc_id++){
  10646         BCM_IF_ERROR_RETURN
  10647             (bcm_hx5_cosq_gport_attach(unit, sched_gport[sc_id], (sc_id < 11) ? sched_gport[1] : sched_gport[2], sc_id));
  10648     }
  10649     numq = 1;
  10650     /* Creating and attaching l3 uc and l2 mc queues to  l2 Schedular nodes */
  10651     for (id = 0, sc_id = 3; id < SOC_HX5_NUM_UCAST_QUEUE_PER_PORT &&
  10652             sc_id < SOC_HX5_NUM_SCHEDULER_PER_PORT; id++, sc_id++) {
  10653         BCM_IF_ERROR_RETURN
  10654             (_bcm_hx5_cosq_gport_add(unit, port, numq,
  10655                                      BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
  10656                                      &uc_gport[id]));
  10657         BCM_IF_ERROR_RETURN
  10658             (bcm_hx5_cosq_gport_attach(unit, uc_gport[id],
  10659                                        sched_gport[sc_id], id));
  10660         BCM_IF_ERROR_RETURN
  10661             (_bcm_hx5_cosq_gport_add(unit, port, numq,
  10662                                      BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
  10663                                      &mc_gport[id]));
  10664         BCM_IF_ERROR_RETURN
  10665             (bcm_hx5_cosq_gport_attach(unit, mc_gport[id],
  10666                                        sched_gport[sc_id], id));
  10667     }
  10668     return BCM_E_NONE;
  10669 }
  10670 
  10671 /*
  10672  * Function:
  10673  *     bcm_hx5_cosq_port_pfc_op
  10674  * Purpose:
  10675  *     Set PFC Prio 2 Cos Map and set the profile index for the Port
  10676  * Parameters:
  10677  *     unit     - (IN) unit number
  10678  *     port     - (IN) GPORT identifier
  10679  *     sctype   - (IN) Input Class
  10680  *     op       - (IN) Operation to be performed (ADD|SET|CLEAR)
  10681  *     gport    - (IN) Gport/Cos array
  10682  *     gport_ct - (IN) Count of values in the array
  10683  * Returns:
  10684  *     BCM_E_XXX
  10685  */
  10686 int
  10687 bcm_hx5_cosq_port_pfc_op(int unit, bcm_port_t port,
  10688                          bcm_switch_control_t sctype, _bcm_cosq_op_t op,
  10689                          bcm_gport_t *gport, int gport_count)
  10690 {
  10691     bcm_port_t local_port;
  10692     int type = -1, class = -1, index, hw_cosq;
  10693     uint32 profile_index, old_profile_index;
  10694     uint32 rval, fval, cos_bmp;
  10695     uint64 rval64[16], *rval64s[1];
  10696     _bcm_hx5_cosq_node_t *node;
  10697     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
  10698     soc_field_t field = INVALIDf;
  10699     soc_info_t *si = &SOC_INFO(unit);
  10700     int rv = SOC_E_NONE;
  10701 
  10702     if (gport_count < 0) {
  10703         return BCM_E_PARAM;
  10704     }
  10705 
  10706     BCM_IF_ERROR_RETURN
  10707         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  10708     if (IS_CPU_PORT(unit, local_port)) {
  10709         return BCM_E_PARAM;
  10710     }
  10711 
  10712     BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_pfc_class_resolve(sctype, &type, &class));
  10713 
  10714     cos_bmp = 0;
  10715 
  10716     if (type == _BCM_HX5_COSQ_TYPE_MCAST) {
  10717         field = MC_COS_BMPf;
  10718     } else {
  10719         field = UC_COS_BMPf;
  10720     }
  10721 
  10722     for (index = 0; index < gport_count; index++) {
  10723         hw_cosq = -1;
  10724         if (BCM_GPORT_IS_SET(gport[index]) &&
  10725             ((BCM_GPORT_IS_SCHEDULER(gport[index])) ||
  10726               BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport[index]) ||
  10727               BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport[index]))) {
  10728             BCM_IF_ERROR_RETURN
  10729                 (_bcm_hx5_cosq_node_get(unit, gport[index], NULL,
  10730                                         NULL, NULL, &node));
  10731             if (BCM_GPORT_IS_SCHEDULER(gport[index])) {
  10732                 hw_cosq = node->hw_index % SOC_HX5_NUM_SCHEDULER_PER_PORT;
  10733             } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport[index])) {
  10734                 if (type != _BCM_HX5_COSQ_TYPE_UCAST) {
  10735                     return BCM_E_PARAM;
  10736                 }
  10737                 hw_cosq = node->hw_index - si->port_uc_cosq_base[local_port];
  10738 
  10739             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport[index])) {
  10740                 if (type != _BCM_HX5_COSQ_TYPE_MCAST) {
  10741                     return BCM_E_PARAM;
  10742                 }
  10743                 hw_cosq = node->hw_index - si->port_cosq_base[local_port];;
  10744             }
  10745         } else {
  10746             /* Find hardware index for given local_port, cosq */
  10747             hw_cosq = gport[index] % si->port_num_cosq[local_port];
  10748         }
  10749         cos_bmp |= (1 << hw_cosq);
  10750     }
  10751 
  10752     rval64s[0] = rval64;
  10753     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval));
  10754 
  10755     if (op == _BCM_COSQ_OP_CLEAR || cos_bmp != 0) {
  10756         old_profile_index = 16 * soc_reg_field_get(unit, port_fc_reg, rval,
  10757                                                    PROFILE_INDEXf);
  10758 
  10759         BCM_IF_ERROR_RETURN
  10760             (soc_profile_reg_get(unit, _bcm_hx5_prio2cos_profile[unit],
  10761                                  old_profile_index, 16, rval64s));
  10762         if (op == _BCM_COSQ_OP_SET) {
  10763             soc_reg64_field32_set(unit, PRIO2COS_PROFILE_64r, &rval64[class],
  10764                                   field, cos_bmp);
  10765         } else if (op == _BCM_COSQ_OP_CLEAR || cos_bmp != 0) {
  10766             fval = soc_reg64_field32_get(unit, PRIO2COS_PROFILE_64r, rval64[class],
  10767                                          field);
  10768             if (op == _BCM_COSQ_OP_ADD) {
  10769                 fval |= cos_bmp;
  10770             } else { /* _BCM_COSQ_OP_CLEAR */
  10771                 fval = 0;
  10772             }
  10773             soc_reg64_field32_set(unit, PRIO2COS_PROFILE_64r, &rval64[class],
  10774                                   field, fval);
  10775         }
  10776         BCM_IF_ERROR_RETURN
  10777             (soc_profile_reg_delete(unit, _bcm_hx5_prio2cos_profile[unit],
  10778                                     old_profile_index));
  10779         rv = soc_profile_reg_add(unit, _bcm_hx5_prio2cos_profile[unit], rval64s,
  10780                                  16, &profile_index);
  10781         if (rv != BCM_E_NONE) {
  10782             SOC_IF_ERROR_RETURN
  10783                 (soc_profile_reg_reference(unit, _bcm_hx5_prio2cos_profile[unit],
  10784                                            old_profile_index, 16));
  10785             return rv;
  10786         }
  10787         soc_reg_field_set(unit, port_fc_reg, &rval, PROFILE_INDEXf,
  10788                           profile_index / 16);
  10789     }
  10790     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, port_fc_reg, local_port, 0, rval));
  10791     return BCM_E_NONE;
  10792 }
  10793 
  10794 /*
  10795  * Function:
  10796  *     bcm_hx5_cosq_port_pfc_get
  10797  * Purpose:
  10798  *     Get PFC Prio2Cos Map for a given Traffic Class
  10799  * Parameters:
  10800  *     unit     - (IN) unit number
  10801  *     port     - (IN) GPORT identifier
  10802  *     sctype   - (IN) Input Traffic Class
  10803  *     gport    - (OUT) Gport/Cos array
  10804  *     gport_ct - (IN) Input Count of gport required
  10805  *     actual_gport_ct - (OUT) Actual Count of gport/cos in the array
  10806  * Returns:
  10807  *     BCM_E_XXX
  10808  */
  10809 int
  10810 bcm_hx5_cosq_port_pfc_get(int unit, bcm_port_t port,
  10811                           bcm_switch_control_t sctype,
  10812                           bcm_gport_t *gport, int gport_count,
  10813                           int *actual_gport_count)
  10814 {
  10815     bcm_port_t local_port;
  10816     int type = 0, class = -1, hw_cosq, count = 0;
  10817     int port_index;
  10818     uint32 profile_index;
  10819     uint32 rval, cos_bmp;
  10820     uint64 rval64[16], *rval64s[1];
  10821     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
  10822     soc_field_t field = INVALIDf;
  10823     _bcm_hx5_cosq_node_t *port_node = NULL;
  10824     int phy_port, mmu_port;
  10825     soc_info_t *si = &SOC_INFO(unit);
  10826 
  10827     if (gport == NULL || gport_count <= 0 || actual_gport_count == NULL) {
  10828         return BCM_E_PARAM;
  10829     }
  10830 
  10831     BCM_IF_ERROR_RETURN
  10832         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  10833     if (IS_CPU_PORT(unit, local_port)) {
  10834         return BCM_E_PARAM;
  10835     }
  10836 
  10837     BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_pfc_class_resolve(sctype, &type, &class));
  10838 
  10839     phy_port = si->port_l2p_mapping[local_port];
  10840     mmu_port = si->port_p2m_mapping[phy_port];
  10841     _HX5_PORT_INDEX_GET(unit, mmu_port, port_index);
  10842 
  10843     rval64s[0] = rval64;
  10844     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval));
  10845     profile_index = 16 * soc_reg_field_get(unit, port_fc_reg, rval,
  10846                                            PROFILE_INDEXf);
  10847 
  10848     if (type == _BCM_HX5_COSQ_TYPE_MCAST) {
  10849         field = MC_COS_BMPf;
  10850         port_node = _HX5_IS_ST_PORT(unit, mmu_port) ?
  10851                     _bcm_hx5_cosq_st_port_info[unit][port_index].mcast :
  10852                     _bcm_hx5_cosq_port_info[unit][port_index].mcast;
  10853     } else {
  10854         field = UC_COS_BMPf;
  10855         port_node = _HX5_IS_ST_PORT(unit, mmu_port) ?
  10856                     _bcm_hx5_cosq_st_port_info[unit][port_index].ucast :
  10857                     _bcm_hx5_cosq_port_info[unit][port_index].ucast;
  10858     }
  10859 
  10860     BCM_IF_ERROR_RETURN
  10861         (soc_profile_reg_get(unit, _bcm_hx5_prio2cos_profile[unit],
  10862                              profile_index, 16, rval64s));
  10863 
  10864     cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILE_64r, rval64[class],
  10865                                     field);
  10866     for (hw_cosq = 0; hw_cosq < si->port_num_cosq[local_port]; hw_cosq++) {
  10867         if (!(cos_bmp & (1 << hw_cosq))) {
  10868             continue;
  10869         }
  10870         gport[count++] = port_node[hw_cosq].gport;
  10871 
  10872         if (count == gport_count) {
  10873             break;
  10874         }
  10875     }
  10876     if (count == 0) {
  10877         return BCM_E_NOT_FOUND;
  10878     }
  10879     *actual_gport_count = count;
  10880 
  10881     return BCM_E_NONE;
  10882 }
  10883 
  10884 /*
  10885  * Function:
  10886  *     _bcm_hx5_cosq_port_fc_get
  10887  * Purpose:
  10888  *     Get the UC|MC gport values associated with
  10889  *     the given PFC/SAFC class.
  10890  * Parameters:
  10891  *     unit             - (IN) unit number
  10892  *     port             - (IN) port number
  10893  *     fc_class         - (IN) PFC/SAFC internal priority class
  10894  *     gport_list       - (OUT) UC|MC gport list
  10895  *     gport_count      - (OUT) gport count
  10896  * Returns:
  10897  *     BCM_E_XXX
  10898  */
  10899 STATIC int
  10900 _bcm_hx5_cosq_port_fc_get(int unit, bcm_gport_t local_port,
  10901                          int fc_class, bcm_gport_t *gport_list,
  10902                          int *gport_count)
  10903 {
  10904     int hw_cosq, count = 0;
  10905     uint32 profile_index;
  10906     uint32 rval, uc_cos_bmp, mc_cos_bmp;
  10907     uint64 rval64[16], *rval64s[1];
  10908     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
  10909     soc_info_t *si = &SOC_INFO(unit);
  10910 
  10911     if ((gport_list == NULL) || (gport_count == NULL)) {
  10912         return BCM_E_PARAM;
  10913     }
  10914 
  10915     rval64s[0] = rval64;
  10916     BCM_IF_ERROR_RETURN
  10917         (soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval));
  10918     profile_index = 16 * soc_reg_field_get(unit, port_fc_reg, rval,
  10919                                            PROFILE_INDEXf);
  10920 
  10921     BCM_IF_ERROR_RETURN
  10922         (soc_profile_reg_get(unit, _bcm_hx5_prio2cos_profile[unit],
  10923                              profile_index, 16, rval64s));
  10924 
  10925     uc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILE_64r, rval64[fc_class],
  10926                                        UC_COS_BMPf);
  10927     mc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILE_64r, rval64[fc_class],
  10928                                        MC_COS_BMPf);
  10929 
  10930     for (hw_cosq = 0; hw_cosq < si->port_num_uc_cosq[local_port]; hw_cosq++) {
  10931         if (!(uc_cos_bmp & (1 << hw_cosq))) {
  10932             continue;
  10933         }
  10934         BCM_IF_ERROR_RETURN
  10935             (_bcm_hx5_cosq_port_cos_resolve(unit, local_port, hw_cosq,
  10936                                            _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE,
  10937                                            &gport_list[count++]));
  10938     }
  10939 
  10940     for (hw_cosq = 0; hw_cosq < si->port_num_cosq[local_port]; hw_cosq++) {
  10941         if (!(mc_cos_bmp & (1 << hw_cosq))) {
  10942             continue;
  10943         }
  10944         BCM_IF_ERROR_RETURN
  10945             (_bcm_hx5_cosq_port_cos_resolve(unit, local_port, hw_cosq,
  10946                                            _BCM_HX5_COSQ_INDEX_STYLE_MCAST_QUEUE,
  10947                                            &gport_list[count++]));
  10948     }
  10949 
  10950     if (count == 0) {
  10951         return BCM_E_NOT_FOUND;
  10952     }
  10953     *gport_count = count;
  10954 
  10955     return BCM_E_NONE;
  10956 }
  10957 
  10958 /*
  10959  * Function:
  10960  *    _bcm_hx5_cosq_port_fc_profile_set
  10961  * Purpose:
  10962  *     Set PFC/SAFC Prio 2 Cos Map and set the profile index for the Port
  10963  * Parameters:
  10964  *     unit       - (IN) unit number
  10965  *     port       - (IN) GPORT identifier
  10966  *     fc_class   - (IN) Input Class
  10967  *     uc_cos_bmp - (IN) UC Cos bitmap array
  10968  *     mc_cos_bmp - (IN) MC Cos bitmap array
  10969  *     num_class  - (IN) Number of input class
  10970  * Returns:
  10971  *     BCM_E_XXX
  10972  */
  10973 STATIC int
  10974 _bcm_hx5_cosq_port_fc_profile_set(int unit, bcm_port_t local_port,
  10975                 int *fc_class, uint32 *uc_cos_bmp, uint32 *mc_cos_bmp,
  10976                 int num_class)
  10977 {
  10978     uint32 profile_index, old_profile_index;
  10979     uint32 rval;
  10980     uint64 rval64[16], *rval64s[1];
  10981     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
  10982     int entry, cur_class;
  10983     uint32 cur_uc_bmp, cur_mc_bmp;
  10984 
  10985     if ((fc_class == NULL) ||
  10986         (uc_cos_bmp == NULL) ||
  10987         (mc_cos_bmp == NULL)) {
  10988         return BCM_E_PARAM;
  10989     }
  10990 
  10991     rval64s[0] = rval64;
  10992     BCM_IF_ERROR_RETURN
  10993         (soc_reg32_get(unit, port_fc_reg, local_port, 0, &rval));
  10994 
  10995     old_profile_index = 16 * soc_reg_field_get(unit, port_fc_reg, rval,
  10996                                                PROFILE_INDEXf);
  10997 
  10998     BCM_IF_ERROR_RETURN
  10999         (soc_profile_reg_get(unit, _bcm_hx5_prio2cos_profile[unit],
  11000                              old_profile_index, 16, rval64s));
  11001 
  11002     for (entry = 0; entry < num_class; entry++) {
  11003         cur_class = fc_class[entry];
  11004         cur_uc_bmp = uc_cos_bmp[entry];
  11005         cur_mc_bmp = mc_cos_bmp[entry];
  11006         soc_reg64_field32_set(unit, PRIO2COS_PROFILE_64r, &rval64[cur_class],
  11007                               UC_COS_BMPf, cur_uc_bmp);
  11008         soc_reg64_field32_set(unit, PRIO2COS_PROFILE_64r, &rval64[cur_class],
  11009                               MC_COS_BMPf, cur_mc_bmp);
  11010 
  11011     }
  11012 
  11013     BCM_IF_ERROR_RETURN
  11014         (soc_profile_reg_add(unit, _bcm_hx5_prio2cos_profile[unit], rval64s,
  11015                              16, &profile_index));
  11016 
  11017     soc_reg_field_set(unit, port_fc_reg, &rval, PROFILE_INDEXf,
  11018                       profile_index / 16);
  11019 
  11020     BCM_IF_ERROR_RETURN
  11021         (soc_profile_reg_delete(unit, _bcm_hx5_prio2cos_profile[unit],
  11022                                 old_profile_index));
  11023 
  11024     BCM_IF_ERROR_RETURN
  11025         (soc_reg32_set(unit, port_fc_reg, local_port, 0, rval));
  11026 
  11027     return BCM_E_NONE;
  11028 }
  11029 
  11030 /*
  11031  * Function:
  11032  *      _bcm_hx5_fc_status_map_gport
  11033  * Purpose:
  11034  *      Set mapping in PFC/SAFC for gport, and update
  11035  *      uc_cos_bmp/mc_cos_bmp with gport cosq.
  11036  * Parameters:
  11037  *      unit        - (IN) unit number
  11038  *      port        - (IN) port number
  11039  *      gport       - (IN) gport to be mapped
  11040  *      uc_cos_map  - (OUT) unicast hw_cosq of gport
  11041  *      mc_cos_map  - (OUT) multicast hw_cosq of gport
  11042  * Returns:
  11043  *      BCM_E_XXX
  11044  */
  11045 STATIC int
  11046 _bcm_hx5_fc_status_map_gport(int unit, bcm_port_t port,
  11047                 bcm_gport_t gport, uint32 *uc_cos_bmp, uint32 *mc_cos_bmp)
  11048 {
  11049     _bcm_hx5_cosq_node_t *node = NULL;
  11050     bcm_port_t local_port = -1;
  11051     bcm_cos_queue_t cosq = -1;
  11052     soc_info_t *si = &SOC_INFO(unit);
  11053 
  11054     BCM_IF_ERROR_RETURN
  11055         (_bcm_hx5_cosq_node_get(unit, gport, NULL, &local_port, NULL, &node));
  11056 
  11057     if (node == NULL) {
  11058         return BCM_E_PARAM;
  11059     }
  11060     if (local_port < 0) {
  11061         return BCM_E_PARAM;
  11062     }
  11063     if (local_port != port) {
  11064         return BCM_E_PARAM;
  11065     }
  11066 
  11067     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11068         cosq = node->hw_index - si->port_uc_cosq_base[local_port];
  11069         *uc_cos_bmp |= 1 << cosq;
  11070     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  11071         cosq = node->hw_index - si->port_cosq_base[local_port]; 
  11072         *mc_cos_bmp |= 1 << cosq;
  11073     }
  11074 
  11075     return BCM_E_NONE;
  11076 }
  11077 
  11078 /*
  11079  * Function:
  11080  *     _bcm_hx5_pfc_class_mapping_check
  11081  * Purpose:
  11082  *     Validate param of bcm_cosq_pfc_class_mapping_t.
  11083  * Parameters:
  11084  *     unit             - (IN) unit number
  11085  *     port             - (IN) port number
  11086  *     array_count      - (IN) count of mapping array
  11087  *     mapping_array    - (IN) mapping array list
  11088  * Returns:
  11089  *     BCM_E_XXX
  11090  */
  11091 STATIC int
  11092 _bcm_hx5_pfc_class_mapping_check(int unit,
  11093     bcm_gport_t port,
  11094     int array_count,
  11095     bcm_cosq_pfc_class_mapping_t *mapping_array)
  11096 {
  11097     int count, index, cur_class;
  11098     bcm_port_t local_port = -1, resolved_port;
  11099     bcm_gport_t cur_gport = 0;
  11100 
  11101     if (mapping_array == NULL) {
  11102         return BCM_E_PARAM;
  11103     }
  11104 
  11105     BCM_IF_ERROR_RETURN
  11106         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  11107     if (local_port < 0) {
  11108         return BCM_E_PORT;
  11109     }
  11110     if (IS_CPU_PORT(unit, local_port)) {
  11111         return BCM_E_PARAM;
  11112     }
  11113 
  11114     for (count = 0; count < array_count; count++) {
  11115         cur_class = mapping_array[count].class_id;
  11116         if ((cur_class < 0) || (cur_class >= _BCM_HX5_NUM_PFC_CLASS)) {
  11117             return BCM_E_PARAM;
  11118         }
  11119 
  11120         for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) {
  11121             cur_gport = mapping_array[count].gport_list[index];
  11122             if (cur_gport == BCM_GPORT_INVALID) {
  11123                 break;
  11124             }
  11125             if (BCM_GPORT_IS_SET(cur_gport)) {
  11126                 if (!((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) ||
  11127                       (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport)))) {
  11128                     return BCM_E_PARAM;
  11129                 }
  11130                 BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_node_get(unit, cur_gport,
  11131                                         NULL, &resolved_port, NULL, NULL));
  11132                 if (resolved_port != local_port) {
  11133                     return BCM_E_PARAM;
  11134                 }
  11135             } else {
  11136                 return BCM_E_PARAM;
  11137             }
  11138         }
  11139     }
  11140 
  11141     return BCM_E_NONE;
  11142 }
  11143 
  11144 /*
  11145  * Function:
  11146  *     bcm_hx5_cosq_pfc_class_mapping_set
  11147  * Purpose:
  11148  *     Set PFC mapping for port.
  11149  *     PFC class is mapped to cosq or scheduler node gports.
  11150  * Parameters:
  11151  *     unit             - (IN) unit number
  11152  *     port             - (IN) port number
  11153  *     array_count      - (IN) count of mapping
  11154  *     mapping_array    - (IN) mappings
  11155  * Returns:
  11156  *     BCM_E_XXX
  11157  */
  11158 int
  11159 bcm_hx5_cosq_pfc_class_mapping_set(int unit, bcm_gport_t port,
  11160                                    int array_count,
  11161                                    bcm_cosq_pfc_class_mapping_t *mapping_array)
  11162 {
  11163     int index, count;
  11164     int cur_class = 0;
  11165     int pfc_class[_BCM_HX5_NUM_PFC_CLASS];
  11166     bcm_gport_t cur_gport = 0;
  11167     uint32 uc_cos_bmp[_BCM_HX5_NUM_PFC_CLASS] = {0};
  11168     uint32 mc_cos_bmp[_BCM_HX5_NUM_PFC_CLASS] = {0};
  11169     bcm_port_t local_port = -1;
  11170 
  11171     if ((array_count < 0) || (array_count > _BCM_HX5_NUM_PFC_CLASS)) {
  11172         return BCM_E_PARAM;
  11173     }
  11174     if (mapping_array == NULL) {
  11175         return BCM_E_PARAM;
  11176     }
  11177     BCM_IF_ERROR_RETURN
  11178         (_bcm_hx5_pfc_class_mapping_check(unit, port,
  11179                                           array_count, mapping_array));
  11180 
  11181     BCM_IF_ERROR_RETURN
  11182         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  11183 
  11184     for (count = 0; count < array_count; count++) {
  11185         cur_class = mapping_array[count].class_id;
  11186         uc_cos_bmp[cur_class] = 0;
  11187         mc_cos_bmp[cur_class] = 0;
  11188 
  11189         for (index = 0; index < BCM_COSQ_PFC_GPORT_COUNT; index++) {
  11190             cur_gport = mapping_array[count].gport_list[index];
  11191             if (cur_gport == BCM_GPORT_INVALID) {
  11192                 break;
  11193             }
  11194 
  11195             BCM_IF_ERROR_RETURN
  11196                 (_bcm_hx5_fc_status_map_gport(unit, local_port, cur_gport,
  11197                                               &uc_cos_bmp[cur_class],
  11198                                               &mc_cos_bmp[cur_class]));
  11199         }
  11200     }
  11201 
  11202     for (index = 0; index < _BCM_HX5_NUM_PFC_CLASS; index++) {
  11203         pfc_class[index] = index;
  11204     }
  11205     BCM_IF_ERROR_RETURN
  11206         (_bcm_hx5_cosq_port_fc_profile_set(unit, local_port, pfc_class,
  11207                                            uc_cos_bmp, mc_cos_bmp,
  11208                                            _BCM_HX5_NUM_PFC_CLASS));
  11209 
  11210     return BCM_E_NONE;
  11211 }
  11212 
  11213 /*
  11214  * Function:
  11215  *     bcm_hx5_cosq_pfc_class_mapping_get
  11216  * Purpose:
  11217  *     Get PFC mapping for port.
  11218  *     Retrieves cosq or scheduler node gports
  11219  *     associated to PFC classes.
  11220  * Parameters:
  11221  *     unit             - (IN) unit number
  11222  *     port             - (IN) port number
  11223  *     array_max        - (IN) max retrieve count
  11224  *     mapping_array    - (OUT) mappings
  11225  *     array_count      - (OUT) retrieved mapping count
  11226  * Returns:
  11227  *     BCM_E_XXX
  11228  */
  11229 int
  11230 bcm_hx5_cosq_pfc_class_mapping_get(int unit, bcm_gport_t port,
  11231                                    int array_max,
  11232                                    bcm_cosq_pfc_class_mapping_t *mapping_array,
  11233                                    int *array_count)
  11234 {
  11235     int rv = 0;
  11236     int cur_class = 0;
  11237     int actual_gport_count, class_count = 0;
  11238     bcm_port_t local_port = -1;
  11239 
  11240     BCM_IF_ERROR_RETURN
  11241         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  11242 
  11243     if (local_port < 0) {
  11244         return BCM_E_PORT;
  11245     }
  11246     if (IS_CPU_PORT(unit, local_port)) {
  11247         return BCM_E_PARAM;
  11248     }
  11249     if (((mapping_array == NULL) && (array_max > 0)) ||
  11250         ((mapping_array != NULL) && (array_max <= 0)) ||
  11251         (array_count == NULL)) {
  11252         return BCM_E_PARAM;
  11253     }
  11254     if (array_max <= 0) {
  11255         *array_count = _BCM_HX5_NUM_PFC_CLASS;
  11256         return BCM_E_NONE;
  11257     }
  11258 
  11259     for (cur_class = 0; cur_class < _BCM_HX5_NUM_PFC_CLASS; cur_class++) {
  11260         actual_gport_count = 0;
  11261         rv = _bcm_hx5_cosq_port_fc_get(unit, local_port, cur_class,
  11262                                        mapping_array[class_count].gport_list,
  11263                                        &actual_gport_count);
  11264 
  11265         if (rv == BCM_E_NONE) {
  11266             mapping_array[class_count].class_id = cur_class;
  11267             if (actual_gport_count < BCM_COSQ_PFC_GPORT_COUNT) {
  11268                 mapping_array[class_count].gport_list[actual_gport_count] =
  11269                                                         BCM_GPORT_INVALID;
  11270             }
  11271             class_count++;
  11272         } else if (rv != BCM_E_NOT_FOUND) {
  11273             return rv;
  11274         }
  11275 
  11276         if ((class_count == array_max) && (array_max > 0)) {
  11277             break;
  11278         }
  11279     }
  11280 
  11281     *array_count = class_count;
  11282     if (class_count == 0) {
  11283         return BCM_E_NOT_FOUND;
  11284     }
  11285 
  11286     return BCM_E_NONE;
  11287 }
  11288 
  11289 /*
  11290  * Function:
  11291  *     bcm_hx5_cosq_safc_class_mapping_set
  11292  * Purpose:
  11293  *     Set SAFC mapping for port.
  11294  *     SAFC class is mapped to cosq or scheduler node gports.
  11295  * Parameters:
  11296  *     unit             - (IN) unit number
  11297  *     port             - (IN) port number
  11298  *     array_count      - (IN) count of mapping
  11299  *     mapping_array    - (IN) mappings
  11300  * Returns:
  11301  *     BCM_E_XXX
  11302  */
  11303 int
  11304 bcm_hx5_cosq_safc_class_mapping_set(int unit, bcm_gport_t port, int array_count,
  11305                                 bcm_cosq_safc_class_mapping_t *mapping_array)
  11306 {
  11307     int index, count;
  11308     int cur_class = 0;
  11309     int safc_class[_BCM_HX5_NUM_SAFC_CLASS];
  11310     bcm_gport_t cur_gport = 0;
  11311     uint32 uc_cos_bmp[_BCM_HX5_NUM_SAFC_CLASS] = {0};
  11312     uint32 mc_cos_bmp[_BCM_HX5_NUM_SAFC_CLASS] = {0};
  11313     bcm_port_t local_port = -1;
  11314 
  11315     BCM_IF_ERROR_RETURN
  11316         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  11317 
  11318     if (local_port < 0) {
  11319         return BCM_E_PORT;
  11320     }
  11321 
  11322     if (IS_CPU_PORT(unit, local_port)) {
  11323         return BCM_E_PARAM;
  11324     }
  11325 
  11326     if ((array_count < 0) || (array_count > _BCM_HX5_NUM_SAFC_CLASS)) {
  11327         return BCM_E_PARAM;
  11328     }
  11329 
  11330     if (mapping_array == NULL) {
  11331         return BCM_E_PARAM;
  11332     }
  11333 
  11334     for (count = 0; count < array_count; count++) {
  11335         cur_class = mapping_array[count].class_id;
  11336         if ((cur_class < 0) || (cur_class >= _BCM_HX5_NUM_SAFC_CLASS)) {
  11337             return BCM_E_PARAM;
  11338         } else {
  11339             uc_cos_bmp[cur_class] = 0;
  11340             mc_cos_bmp[cur_class] = 0;
  11341         }
  11342 
  11343         for (index = 0; index < BCM_COSQ_SAFC_GPORT_COUNT; index++) {
  11344             cur_gport = mapping_array[count].gport_list[index];
  11345             if (cur_gport == BCM_GPORT_INVALID) {
  11346                 break;
  11347             }
  11348 
  11349             if ((BCM_GPORT_IS_UCAST_QUEUE_GROUP(cur_gport)) ||
  11350                 (BCM_GPORT_IS_MCAST_QUEUE_GROUP(cur_gport))) {
  11351                 BCM_IF_ERROR_RETURN
  11352                     (_bcm_hx5_fc_status_map_gport(unit, local_port, cur_gport,
  11353                                                   &uc_cos_bmp[cur_class],
  11354                                                   &mc_cos_bmp[cur_class]));
  11355             } else {
  11356                 return BCM_E_PARAM;
  11357             }
  11358         }
  11359     }
  11360 
  11361     for (index = 0; index < _BCM_HX5_NUM_SAFC_CLASS; index++) {
  11362         safc_class[index] = index;
  11363     }
  11364 
  11365     BCM_IF_ERROR_RETURN
  11366         (_bcm_hx5_cosq_port_fc_profile_set(unit, local_port, safc_class,
  11367                                            uc_cos_bmp, mc_cos_bmp,
  11368                                            _BCM_HX5_NUM_SAFC_CLASS));
  11369 
  11370     return BCM_E_NONE;
  11371 }
  11372 
  11373 /*
  11374  * Function:
  11375  *     bcm_hx5_cosq_safc_class_mapping_get
  11376  * Purpose:
  11377  *     Get SAFC mapping for port.
  11378  *     Retrieves cosq or scheduler node gports associated to SAFC classes.
  11379  * Parameters:
  11380  *     unit             - (IN) unit number
  11381  *     port             - (IN) port number
  11382  *     array_max        - (IN) max retrieve count
  11383  *     mapping_array    - (OUT) mappings
  11384  *     array_count      - (OUT) retrieved mapping count
  11385  * Returns:
  11386  *     BCM_E_XXX
  11387  */
  11388 int
  11389 bcm_hx5_cosq_safc_class_mapping_get(int unit, bcm_gport_t port, int array_max,
  11390                                 bcm_cosq_safc_class_mapping_t *mapping_array,
  11391                                 int *array_count)
  11392 {
  11393     int rv = 0;
  11394     int cur_class = 0;
  11395     int actual_gport_count, class_count = 0;
  11396     bcm_port_t local_port = -1;
  11397 
  11398     BCM_IF_ERROR_RETURN
  11399         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  11400 
  11401     if (local_port < 0) {
  11402         return BCM_E_PORT;
  11403     }
  11404 
  11405     if (IS_CPU_PORT(unit, local_port)) {
  11406         return BCM_E_PARAM;
  11407     }
  11408 
  11409     if (((mapping_array == NULL) && (array_max > 0)) ||
  11410         ((mapping_array != NULL) && (array_max <= 0)) ||
  11411         (array_count == NULL)) {
  11412         return BCM_E_PARAM;
  11413     }
  11414 
  11415     if (array_max <= 0) {
  11416         *array_count = _BCM_HX5_NUM_SAFC_CLASS;
  11417         return BCM_E_NONE;
  11418     }
  11419 
  11420     for (cur_class = 0; cur_class < _BCM_HX5_NUM_SAFC_CLASS; cur_class++) {
  11421         actual_gport_count = 0;
  11422         rv = _bcm_hx5_cosq_port_fc_get(unit, local_port, cur_class,
  11423                                        mapping_array[class_count].gport_list,
  11424                                        &actual_gport_count);
  11425 
  11426         if (rv == BCM_E_NONE) {
  11427             mapping_array[class_count].class_id = cur_class;
  11428             if (actual_gport_count < BCM_COSQ_SAFC_GPORT_COUNT) {
  11429                 mapping_array[class_count].gport_list[actual_gport_count] =
  11430                                                 BCM_GPORT_INVALID;
  11431             }
  11432             class_count++;
  11433         } else if (rv != BCM_E_NOT_FOUND) {
  11434             return rv;
  11435         }
  11436 
  11437         if (class_count == array_max) {
  11438             break;
  11439         }
  11440     }
  11441 
  11442     *array_count = class_count;
  11443     if (class_count == 0) {
  11444         return BCM_E_NOT_FOUND;
  11445     }
  11446 
  11447     return BCM_E_NONE;
  11448 }
  11449 /*
  11450  *   Function:
  11451  *        bcm_hx5_cosq_buffer_id_multi_get
  11452  *   Purpose:
  11453  *        Get mutliple buffer ids associated with a specified port.
  11454  *   Parameters:
  11455  *        unit - (IN) BCM device number.
  11456  *        gport - (IN) Port
  11457  *        cosq - (IN) Reserved field
  11458  *        direction - (IN) Specify ingress or egress direction
  11459  *        array_max - (IN) number of entries to be retrieved
  11460  *        buf_id_array - (OUT) Buffer id array
  11461  *        array_count - (OUT) Actural buffer id count in buf_id_array
  11462  *   Returns:
  11463  *       BCM_E_XXX
  11464  */
  11465 int
  11466 bcm_hx5_cosq_buffer_id_multi_get(int unit, bcm_gport_t gport,
  11467         bcm_cos_queue_t cosq, bcm_cosq_dir_t direction,
  11468         int array_max, bcm_cosq_buffer_id_t *buf_id_array,
  11469         int *array_count)
  11470 {
  11471     bcm_port_t local_port;
  11472     int i;
  11473 
  11474     if ((direction < bcmCosqIngress) ||
  11475             (direction >= bcmCosqDirectionMaxCount)) {
  11476         return BCM_E_PARAM;
  11477     }
  11478 
  11479     if (!BCM_GPORT_IS_SET(gport)) {
  11480         local_port = gport;
  11481     } else if (BCM_GPORT_IS_LOCAL(gport)) {
  11482         local_port = BCM_GPORT_LOCAL_GET(gport);
  11483     } else if (BCM_GPORT_IS_MODPORT(gport)) {
  11484         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &local_port));
  11485     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  11486         int idx;
  11487         BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_index_resolve(unit, gport, cosq,
  11488                     _BCM_HX5_COSQ_INDEX_STYLE_UCAST_QUEUE, &local_port, &idx, NULL));
  11489     } else {
  11490         return BCM_E_PARAM;
  11491     }
  11492 
  11493     if (!SOC_PORT_VALID(unit, local_port)) {
  11494         return BCM_E_PORT;
  11495     }
  11496 
  11497     if (array_max >= 1) {
  11498         *array_count = 1;
  11499     } else if (array_max == 0){
  11500         *array_count = array_max;
  11501     } else {
  11502         return BCM_E_PARAM;
  11503     }
  11504 
  11505     for (i = 0; i < *array_count; i++) {
  11506         buf_id_array[i] = 0;
  11507     }
  11508 
  11509     for (i = *array_count; i < array_max; i++) {
  11510         buf_id_array[i] = BCM_COSQ_INVALID_BUF_ID;
  11511     }
  11512 
  11513     return BCM_E_NONE;
  11514 }
  11515 
  11516 #ifdef BCM_WARM_BOOT_SUPPORT
  11517 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
  11518 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
  11519 STATIC int
  11520 _bcm_hx5_cosq_wb_alloc(int unit)
  11521 {
  11522     soc_scache_handle_t scache_handle;
  11523     uint8 *scache_ptr = NULL;
  11524     int rv, alloc_size = 0, max_size = (4096 * 7);
  11525     _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
  11526 
  11527     /*
  11528      * Sync _bcm_hx5_cosq_cpu_port_info structure
  11529      */
  11530     cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit];
  11531     if (cpu_port_info == NULL) {
  11532         return BCM_E_INIT;
  11533     }
  11534     alloc_size += sizeof(_bcm_hx5_cosq_cpu_port_info_t);
  11535 
  11536     /*
  11537      * Sync the ref_count of IFP_COS_MAPm/COS_MAPm
  11538      */
  11539     alloc_size += (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _HX5_MMU_NUM_INT_PRI) *
  11540                    sizeof(uint16);
  11541 
  11542     /*
  11543      * Sync _bcm_hx5_cosq_cpu_cosq_config_t structure for all CPU queues
  11544      */
  11545     alloc_size += (SOC_HX5_NUM_CPU_QUEUES *
  11546                    sizeof(_bcm_hx5_cosq_cpu_cosq_config_t));
  11547 
  11548     /*
  11549      * Sync num_cos value
  11550      */
  11551     alloc_size += sizeof(int);
  11552 
  11553     /*    
  11554      * Sync _soc_td3_mmu_traffic_ctrl_t
  11555      */
  11556     BCM_IF_ERROR_RETURN(soc_td3_mmu_traffic_ctrl_size(unit, &alloc_size));
  11557 
  11558     /*
  11559      * Sync _bcm_pfc_deadlock_control_t structure
  11560      */
  11561     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  11562         alloc_size += sizeof(_bcm_hx5_pfc_deadlock_control_t);
  11563     }
  11564 
  11565     /*
  11566      * Sync _bcm_hx5_cosq_cpu_cosq_config_t structure for all CPU queues
  11567      */
  11568     alloc_size += (_BCM_HX5_NUM_WRED_RESOLUTION_TABLE *
  11569                    sizeof(uint32));
  11570 
  11571     if (soc_feature(unit, soc_feature_mpls_ecn)) {
  11572         uint32 scache_size = 0;
  11573         BCM_IF_ERROR_RETURN(
  11574             bcmi_xgs5_ecn_scache_size_get(unit, &scache_size));
  11575         alloc_size += scache_size;
  11576     }
  11577 
  11578 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB)
  11579     if (soc_feature(unit, soc_feature_tcb)) {
  11580         alloc_size += sizeof(uint16);
  11581     }
  11582 #else
  11583     alloc_size += sizeof(uint16);
  11584 #endif
  11585 
  11586     /* Reserving some space scache for future usecase (max_size) */
  11587     if (alloc_size < max_size) {
  11588         alloc_size = max_size;
  11589     } else {
  11590         /* Required size more than max size allocated for Cosq */
  11591         return BCM_E_INIT;
  11592     }
  11593 
  11594     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
  11595 
  11596     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
  11597                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
  11598 
  11599     if (rv == BCM_E_NOT_FOUND) {
  11600         rv = BCM_E_NONE;
  11601     }
  11602 
  11603     return rv;
  11604 }
  11605 
  11606 int
  11607 bcm_hx5_cosq_reinit(int unit)
  11608 {
  11609     soc_scache_handle_t scache_handle;
  11610     uint8 *scache_ptr = NULL;
  11611     int *int_scache_ptr = NULL;
  11612     uint16 *u16_scache_ptr = NULL;
  11613     uint32 *u32_scache_ptr = NULL;
  11614     _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
  11615     int alloc_size = 0, pipe = -1, i, j;
  11616     soc_profile_mem_t *profile_mem;
  11617     soc_mem_t wred_config_mem = INVALIDm;
  11618     int index, profile_index, resolution_index;
  11619     int stable_size, rv, set_index, num;
  11620     mmu_wred_config_entry_t qentry;
  11621     uint32 entry[SOC_MAX_MEM_WORDS];
  11622     int phy_port, mmu_port;
  11623     bcm_port_t port;
  11624     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
  11625     uint32 rval;
  11626     _bcm_bst_device_handlers_t bst_callbks;
  11627     _bcm_hx5_cosq_cpu_cosq_config_t *cpu_cosq_config_p;
  11628     uint16 recovered_ver = 0;
  11629     int index_min, index_max;
  11630     _bcm_hx5_pfc_deadlock_control_t *pfc_deadlock_control = NULL;
  11631     soc_info_t *si = &SOC_INFO(unit); 
  11632 
  11633 
  11634     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  11635     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
  11636         /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/
  11637         return BCM_E_NONE;
  11638     }
  11639 
  11640     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
  11641     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr,
  11642                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
  11643     if (BCM_FAILURE(rv)) {
  11644         return rv;
  11645     }
  11646 
  11647     /* Restore _bcm_hx5_cosq_cpu_port_info structure */
  11648     cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit];
  11649     if (cpu_port_info == NULL) {
  11650         return BCM_E_INIT;
  11651     }
  11652     alloc_size = sizeof(_bcm_hx5_cosq_cpu_port_info_t);
  11653     sal_memcpy(cpu_port_info, scache_ptr, alloc_size);
  11654     scache_ptr += alloc_size;
  11655 
  11656     /* Update IFP_COS_MAP memory profile reference counter */
  11657     profile_mem = _bcm_hx5_ifp_cos_map_profile[unit];
  11658     num = SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _HX5_MMU_NUM_INT_PRI;
  11659     u16_scache_ptr = (uint16 *)scache_ptr;
  11660     for (i = 0; i < num; i++) {
  11661         for (j = 0; j < *u16_scache_ptr; j++) {
  11662             SOC_IF_ERROR_RETURN(
  11663                 soc_profile_mem_reference(unit, profile_mem,
  11664                                           i * _HX5_MMU_NUM_INT_PRI,
  11665                                           _HX5_MMU_NUM_INT_PRI));
  11666         }
  11667         u16_scache_ptr++;
  11668     }
  11669     scache_ptr = (uint8*)u16_scache_ptr;
  11670 
  11671     /* Recover CPU queue config information from scache */
  11672     cpu_cosq_config_p = _bcm_hx5_cosq_cpu_cosq_config[unit][0];
  11673     if (cpu_cosq_config_p == NULL) {
  11674         return BCM_E_INIT;
  11675     }
  11676     alloc_size = (SOC_HX5_NUM_CPU_QUEUES *
  11677                   sizeof(_bcm_hx5_cosq_cpu_cosq_config_t));
  11678     sal_memcpy(cpu_cosq_config_p, scache_ptr, alloc_size);
  11679     scache_ptr += alloc_size;
  11680 
  11681     /* Retriving num_cos value */
  11682     int_scache_ptr = (int *) scache_ptr;
  11683     _BCM_HX5_NUM_COS(unit) = *int_scache_ptr++;
  11684     scache_ptr = (uint8*) int_scache_ptr;
  11685 
  11686     /* Update PRIO2COS_PROFILE register profile reference counter */
  11687     PBMP_PORT_ITER(unit, port) {
  11688         BCM_IF_ERROR_RETURN
  11689             (soc_reg32_get(unit, port_fc_reg, port, 0, &rval));
  11690         profile_index = 16 * soc_reg_field_get(unit, port_fc_reg, rval,
  11691                                                PROFILE_INDEXf);
  11692         SOC_IF_ERROR_RETURN
  11693             (soc_profile_reg_reference(unit, _bcm_hx5_prio2cos_profile[unit],
  11694                                        profile_index, 16));
  11695     }
  11696 
  11697     /* Update PORT_COS_MAP memory profile reference counter */
  11698     profile_mem = _bcm_hx5_cos_map_profile[unit];
  11699     PBMP_ALL_ITER(unit, port) {
  11700         SOC_IF_ERROR_RETURN
  11701             (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry));
  11702         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
  11703         SOC_IF_ERROR_RETURN
  11704             (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16));
  11705     }
  11706     if (SOC_INFO(unit).cpu_hg_index != -1) {
  11707         SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL,
  11708                                          SOC_INFO(unit).cpu_hg_index, &entry));
  11709         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
  11710         SOC_IF_ERROR_RETURN
  11711             (soc_profile_mem_reference(unit, profile_mem, set_index * 16, 16));
  11712     }
  11713 
  11714     /* Update MMU_WRED_DROP_CURVE_PROFILE memory profile reference counter */
  11715     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  11716         wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_WRED_CONFIGm)[pipe];
  11717         if (wred_config_mem == INVALIDm) {
  11718             return BCM_E_PARAM;
  11719         }
  11720         index_min = soc_mem_index_min(unit, wred_config_mem);
  11721         index_max = soc_mem_index_max(unit, wred_config_mem);
  11722         for (index = index_min; index < index_max; index++) {
  11723             BCM_IF_ERROR_RETURN
  11724                 (soc_mem_read(unit, wred_config_mem,
  11725                               MEM_BLOCK_ALL, index, &qentry));
  11726             profile_index = soc_mem_field32_get(unit, wred_config_mem,
  11727                                                 &qentry, PROFILE_INDEXf);
  11728             BCM_IF_ERROR_RETURN
  11729                 (soc_profile_mem_reference(unit, _bcm_hx5_wred_profile[unit],
  11730                                            profile_index, 1));
  11731 
  11732             if (soc_mem_field32_get(unit, wred_config_mem, &qentry,
  11733                 ECN_MARKING_ENf)) {
  11734                 resolution_index = soc_mem_field32_get(
  11735                     unit, wred_config_mem, &qentry,
  11736                     WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf);
  11737             } else {
  11738                 resolution_index = soc_mem_field32_get(
  11739                     unit, wred_config_mem, &qentry,
  11740                     WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf);
  11741             }
  11742             _bcm_hx5_wred_resolution_tbl[resolution_index] = 1;
  11743         }
  11744     }
  11745 
  11746     /* Create gport tree */
  11747     _BCM_HX5_MMU_INFO(unit)->gport_tree_created = FALSE;
  11748     PBMP_ALL_ITER(unit, port) {
  11749         phy_port = si->port_l2p_mapping[port];
  11750         mmu_port = si->port_p2m_mapping[phy_port];
  11751         if (IS_LB_PORT(unit, port) || IS_CPU_PORT(unit, port)
  11752             || IS_FAE_PORT(unit, port)) {
  11753             continue;
  11754         }
  11755         if (_HX5_IS_ST_PORT(unit, mmu_port)) {
  11756             BCM_IF_ERROR_RETURN
  11757                 (_bcm_hx5_cosq_st_gport_tree_create(unit, port));
  11758         } else {
  11759             BCM_IF_ERROR_RETURN
  11760                 (_bcm_hx5_cosq_gport_tree_create(unit, port));
  11761         }
  11762     }
  11763     _BCM_HX5_MMU_INFO(unit)->gport_tree_created = TRUE;
  11764 
  11765     /* BST reinit */
  11766     sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t));
  11767     bst_callbks.resolve_index = &_bcm_hx5_bst_index_resolve;
  11768     bst_callbks.reverse_resolve_index = NULL;
  11769     BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks));
  11770 
  11771     /* Recover _soc_td3_mmu_traffic_ctrl_t */
  11772     BCM_IF_ERROR_RETURN(soc_td3_mmu_traffic_ctrl_wb_restore(unit, &scache_ptr));
  11773 
  11774 
  11775     /* PFC Deadlock recovery should be initialized
  11776        irrespective of scache version to handle
  11777        upgrades */
  11778     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  11779         BCM_IF_ERROR_RETURN(_bcm_pfc_deadlock_init(unit));
  11780     }
  11781 
  11782     /* Recover PFC Deadlock recovery information from scache */
  11783     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  11784         pfc_deadlock_control = _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit);
  11785         if (pfc_deadlock_control == NULL) {
  11786             return BCM_E_INIT;
  11787         }
  11788         alloc_size = sizeof(_bcm_hx5_pfc_deadlock_control_t);
  11789         sal_memcpy(pfc_deadlock_control, scache_ptr, alloc_size);
  11790         scache_ptr += alloc_size;
  11791         /* Re-set the Hardware Registers/Memory info */
  11792         BCM_IF_ERROR_RETURN(_bcm_hx5_pfc_deadlock_hw_res_init(unit));
  11793         BCM_IF_ERROR_RETURN(_bcm_hx5_pfc_deadlock_reinit(unit));
  11794         BCM_IF_ERROR_RETURN(_bcm_hx5_pfc_deadlock_recovery_reset(unit));
  11795         pfc_deadlock_control->cosq_inv_mapping_get = _bcm_hx5_cosq_inv_mapping_get;
  11796     }
  11797 
  11798 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB)
  11799     if (soc_feature(unit, soc_feature_tcb)){
  11800         _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info;
  11801         BCM_IF_ERROR_RETURN(bcm_hx5_cosq_tcb_reinit(unit));
  11802 
  11803         tcb_unit_info = TCB_UNIT_CONTROL(unit);
  11804         TCB_INIT(unit);
  11805 
  11806         alloc_size = sizeof(uint16);
  11807         sal_memcpy(&tcb_unit_info->tcb_config_init_bmp, scache_ptr, alloc_size);
  11808         scache_ptr += alloc_size;
  11809     }
  11810 #else
  11811     scache_ptr += sizeof(uint16);
  11812 #endif
  11813 
  11814     /* Retriving _bcm_hx5_wred_resolution_tbl value */
  11815     u32_scache_ptr = (uint32 *) scache_ptr;
  11816     for (i = 0; i < _BCM_HX5_NUM_WRED_RESOLUTION_TABLE; i++) {
  11817         _bcm_hx5_wred_resolution_tbl[i] = *u32_scache_ptr++;
  11818     }
  11819 
  11820     return BCM_E_NONE;
  11821 }
  11822 
  11823 int
  11824 bcm_hx5_cosq_sync(int unit)
  11825 {
  11826     soc_scache_handle_t scache_handle;
  11827     uint8 *scache_ptr;
  11828     int *int_scache_ptr;
  11829     _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
  11830     int size = 0;
  11831     _bcm_hx5_cosq_cpu_cosq_config_t **cpu_cosq_config_p;
  11832     int ii;
  11833     int rv = BCM_E_NONE, ref_count;
  11834     uint16 *u16_scache_ptr;
  11835     uint32 *u32_scache_ptr;
  11836     _bcm_hx5_pfc_deadlock_control_t *pfc_deadlock_control = NULL;
  11837 
  11838     cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit];
  11839     if (cpu_port_info == NULL) {
  11840         return BCM_E_INIT;
  11841     }
  11842 
  11843     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
  11844     BCM_IF_ERROR_RETURN
  11845         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
  11846                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL));
  11847 
  11848     /* Cache _bcm_hx5_cosq_cpu_port_info_t structure */
  11849     size = sizeof(_bcm_hx5_cosq_cpu_port_info_t);
  11850     sal_memcpy(scache_ptr, cpu_port_info, size);
  11851     scache_ptr += size/sizeof(uint8);
  11852 
  11853     /* Cache _bcm_hx5_ifp_cos_map_profile reference count */
  11854     u16_scache_ptr = (uint16 *)scache_ptr;
  11855     for (ii = 0;
  11856          ii < (SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _HX5_MMU_NUM_INT_PRI);
  11857          ii++) {
  11858         rv = soc_profile_mem_ref_count_get(unit,
  11859                                            _bcm_hx5_ifp_cos_map_profile[unit],
  11860                                            ii * _HX5_MMU_NUM_INT_PRI,
  11861                                            &ref_count);
  11862         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  11863             return rv;
  11864         }
  11865         *u16_scache_ptr++ = (uint16)(ref_count & 0xffff);
  11866     }
  11867     scache_ptr = (uint8*) u16_scache_ptr;
  11868 
  11869     /* Sync CPU Queue info */
  11870     cpu_cosq_config_p = _bcm_hx5_cosq_cpu_cosq_config[unit];
  11871     size = (SOC_HX5_NUM_CPU_QUEUES * sizeof(_bcm_hx5_cosq_cpu_cosq_config_t));
  11872     sal_memcpy(scache_ptr, *cpu_cosq_config_p, size);
  11873     scache_ptr += (size / sizeof(uint8));
  11874 
  11875     /* Sync num_cos value */
  11876     int_scache_ptr = (int*) scache_ptr;
  11877     *int_scache_ptr++ = _BCM_HX5_NUM_COS(unit);
  11878     scache_ptr = (uint8 *)int_scache_ptr;
  11879 
  11880     /* Sync _soc_td3_mmu_traffic_ctrl_t */
  11881     BCM_IF_ERROR_RETURN(soc_td3_mmu_traffic_ctrl_wb_sync(unit, &scache_ptr));
  11882 
  11883    
  11884     /* Sync PFC Deadlock Control info */
  11885     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  11886         pfc_deadlock_control = _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit);
  11887         if (pfc_deadlock_control == NULL) {
  11888             return BCM_E_INIT;
  11889         }
  11890         size = sizeof(_bcm_hx5_pfc_deadlock_control_t);
  11891         sal_memcpy(scache_ptr, pfc_deadlock_control, size);
  11892         scache_ptr += (size / sizeof(uint8));
  11893     }
  11894 
  11895 
  11896 #if defined (BCM_TCB_SUPPORT) && defined (INCLUDE_TCB)
  11897     if (soc_feature(unit, soc_feature_tcb)){
  11898         _bcm_cosq_tcb_unit_ctrl_t *tcb_unit_info;
  11899         tcb_unit_info = TCB_UNIT_CONTROL(unit);
  11900         TCB_INIT(unit);
  11901 
  11902         u16_scache_ptr = (uint16*) scache_ptr;
  11903         size = sizeof(uint16);
  11904         sal_memcpy(u16_scache_ptr, &tcb_unit_info->tcb_config_init_bmp, size);
  11905         u16_scache_ptr ++;
  11906     }
  11907 #else
  11908     u16_scache_ptr = (uint16*) scache_ptr;
  11909     u16_scache_ptr ++;
  11910 #endif
  11911     u32_scache_ptr = (uint32*) u16_scache_ptr;
  11912 
  11913     for (ii = 0; ii < _BCM_HX5_NUM_WRED_RESOLUTION_TABLE; ii++) {
  11914         *u32_scache_ptr++ = _bcm_hx5_wred_resolution_tbl[ii];
  11915     }
  11916 
  11917     scache_ptr = (uint8 *)u32_scache_ptr;
  11918 
  11919     return BCM_E_NONE;
  11920 }
  11921 #endif
  11922 
  11923 
  11924 /*
  11925  * Function:
  11926  *     bcm_hx5_cosq_init
  11927  * Purpose:
  11928  *     Initialize (clear) all COS schedule/mapping state.
  11929  * Parameters:
  11930  *     unit - (IN) unit number
  11931  * Returns:
  11932  *     BCM_E_XXX
  11933  */
  11934 int
  11935 bcm_hx5_cosq_init(int unit)
  11936 {
  11937     int i, alloc_size = 0, numq = 0, pipe = -1;
  11938     int rv = BCM_E_NONE;
  11939     soc_mem_t mem = INVALIDm;
  11940     soc_reg_t reg = INVALIDr;
  11941     int entry_words[9];
  11942     int phy_port, mmu_port;
  11943     int min_index, max_index;
  11944     bcm_port_t port;
  11945     uint64 rval64s[16], *prval64s[1];
  11946     _bcm_hx5_cosq_cpu_cosq_config_t *cpu_cosq_config_p = NULL;
  11947     soc_mem_t wred_config_mem = INVALIDm;
  11948     _bcm_bst_device_handlers_t bst_callbks;
  11949     soc_info_t *si = &SOC_INFO(unit);
  11950 
  11951     static soc_mem_t wred_mems[9] = {
  11952         MMU_WRED_DROP_CURVE_PROFILE_0m, MMU_WRED_DROP_CURVE_PROFILE_1m,
  11953         MMU_WRED_DROP_CURVE_PROFILE_2m, MMU_WRED_DROP_CURVE_PROFILE_3m,
  11954         MMU_WRED_DROP_CURVE_PROFILE_4m, MMU_WRED_DROP_CURVE_PROFILE_5m,
  11955         MMU_WRED_DROP_CURVE_PROFILE_6m, MMU_WRED_DROP_CURVE_PROFILE_7m,
  11956         MMU_WRED_DROP_CURVE_PROFILE_8m
  11957     };
  11958     
  11959     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
  11960     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
  11961     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
  11962     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
  11963     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
  11964     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
  11965     mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green;
  11966     mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow;
  11967     mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red;
  11968     void *entries[9];
  11969     uint32 profile_index;
  11970     int ii, wred_prof_count;
  11971 
  11972     numq = soc_property_get(unit, spn_BCM_NUM_COS, _BCM_HX5_COS_DEFAULT);
  11973     if (numq < 1) {
  11974         numq = 1;
  11975     } else if (numq > _BCM_HX5_COS_DEFAULT) {
  11976         numq = _BCM_HX5_COS_DEFAULT;
  11977     }
  11978 
  11979     /* Create Port Information structure */
  11980     alloc_size = sizeof(_bcm_hx5_cosq_port_info_t) * (_BCM_HX5_NUM_PORTS);
  11981     if (_bcm_hx5_cosq_port_info[unit] == NULL) {
  11982         _bcm_hx5_cosq_port_info[unit] =
  11983             sal_alloc(alloc_size, "_bcm_hx5_cosq_port_info");
  11984             if (_bcm_hx5_cosq_port_info[unit] == NULL) {
  11985                 return BCM_E_MEMORY;
  11986             }
  11987     }
  11988     sal_memset(_bcm_hx5_cosq_port_info[unit], 0, alloc_size);
  11989 
  11990     /* Create HG Port Information structure */
  11991     alloc_size = sizeof(_bcm_hx5_cosq_st_port_info_t) * (_BCM_HX5_NUM_ST_PORTS);
  11992     if (_bcm_hx5_cosq_st_port_info[unit] == NULL) {
  11993         _bcm_hx5_cosq_st_port_info[unit] =
  11994             sal_alloc(alloc_size, "_bcm_hx5_cosq_st_port_info");
  11995             if (_bcm_hx5_cosq_st_port_info[unit] == NULL) {
  11996                 return BCM_E_MEMORY;
  11997             }
  11998     }
  11999     sal_memset(_bcm_hx5_cosq_st_port_info[unit], 0, alloc_size);
  12000 
  12001     /* Create CPU Port Information structure */
  12002     alloc_size = sizeof(_bcm_hx5_cosq_cpu_port_info_t);
  12003     if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) {
  12004         _bcm_hx5_cosq_cpu_port_info[unit] =
  12005             sal_alloc(alloc_size, "_bcm_hx5_cosq_cpu_port_info");
  12006         if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) {
  12007             _bcm_hx5_cosq_cleanup(unit);
  12008             return BCM_E_MEMORY;
  12009         }
  12010     }
  12011     sal_memset(_bcm_hx5_cosq_cpu_port_info[unit], 0, alloc_size);
  12012 
  12013     /* Create MMU Port Information structure */
  12014     alloc_size = sizeof(_bcm_hx5_mmu_info_t);
  12015     if (_bcm_hx5_mmu_info[unit] == NULL) {
  12016         _bcm_hx5_mmu_info[unit] =
  12017             sal_alloc(alloc_size, "_bcm_hx5_mmu_info");
  12018         if (_bcm_hx5_mmu_info[unit] == NULL) {
  12019             _bcm_hx5_cosq_cleanup(unit);
  12020             return BCM_E_MEMORY;
  12021         }
  12022     }
  12023     sal_memset(_bcm_hx5_mmu_info[unit], 0, alloc_size);
  12024     _BCM_HX5_MMU_INFO(unit)->_bcm_hx5_port_info =
  12025             _bcm_hx5_cosq_port_info[unit];
  12026     _BCM_HX5_MMU_INFO(unit)->_bcm_hx5_cpu_port_info =
  12027             _bcm_hx5_cosq_cpu_port_info[unit];
  12028     _BCM_HX5_MMU_INFO(unit)->_bcm_hx5_st_port_info =
  12029             _bcm_hx5_cosq_st_port_info[unit];
  12030 
  12031     /* Create profile for PORT_COS_MAP table */
  12032     if (_bcm_hx5_cos_map_profile[unit] == NULL) {
  12033         _bcm_hx5_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
  12034                                                   "COS_MAP Profile Mem");
  12035         if (_bcm_hx5_cos_map_profile[unit] == NULL) {
  12036             _bcm_hx5_cosq_cleanup(unit);
  12037             return BCM_E_MEMORY;
  12038         }
  12039         soc_profile_mem_t_init(_bcm_hx5_cos_map_profile[unit]);
  12040     }
  12041     mem = PORT_COS_MAPm;
  12042     min_index = soc_mem_index_min(unit, PORT_COS_MAPm);
  12043     max_index = soc_mem_index_max(unit, PORT_COS_MAPm) / 2;
  12044     entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32);
  12045 
  12046     /* create an cos_map profile with max index of 64,
  12047      * because cos_map_sel being an 2 bit we can able to 
  12048      * maintain up to 4 profiles.
  12049      */
  12050     rv = soc_profile_mem_index_create(unit, &mem, entry_words,
  12051                                  &min_index, &max_index, NULL, 1,
  12052                                 _bcm_hx5_cos_map_profile[unit]);
  12053     if (rv != SOC_E_NONE) {
  12054         _bcm_hx5_cosq_cleanup(unit);
  12055         return rv;
  12056     }
  12057 
  12058     /* Create profile for IFP_COS_MAP table */
  12059     if (_bcm_hx5_ifp_cos_map_profile[unit] == NULL) {
  12060         _bcm_hx5_ifp_cos_map_profile[unit]
  12061             = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem");
  12062         if (_bcm_hx5_ifp_cos_map_profile[unit] == NULL) {
  12063             _bcm_hx5_cosq_cleanup(unit);
  12064             return BCM_E_MEMORY;
  12065         }
  12066         soc_profile_mem_t_init(_bcm_hx5_ifp_cos_map_profile[unit]);
  12067     }
  12068     mem = IFP_COS_MAPm;
  12069     entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32);
  12070 
  12071     rv = soc_profile_mem_create(unit, &mem, entry_words, 1,
  12072             _bcm_hx5_ifp_cos_map_profile[unit]);
  12073     if (rv != SOC_E_NONE) {
  12074         _bcm_hx5_cosq_cleanup(unit);
  12075         return rv;
  12076     }
  12077 
  12078     /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */
  12079     if (_bcm_hx5_wred_profile[unit] == NULL) {
  12080         _bcm_hx5_wred_profile[unit] =
  12081             sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem");
  12082         if (_bcm_hx5_wred_profile[unit] == NULL) {
  12083             _bcm_hx5_cosq_cleanup(unit);
  12084             return BCM_E_MEMORY;
  12085         }
  12086         soc_profile_mem_t_init(_bcm_hx5_wred_profile[unit]);
  12087     }
  12088 
  12089     entry_words[0] =
  12090         sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32);
  12091     entry_words[1] =
  12092         sizeof(mmu_wred_drop_curve_profile_1_entry_t) / sizeof(uint32);
  12093     entry_words[2] =
  12094         sizeof(mmu_wred_drop_curve_profile_2_entry_t) / sizeof(uint32);
  12095     entry_words[3] =
  12096         sizeof(mmu_wred_drop_curve_profile_3_entry_t) / sizeof(uint32);
  12097     entry_words[4] =
  12098         sizeof(mmu_wred_drop_curve_profile_4_entry_t) / sizeof(uint32);
  12099     entry_words[5] =
  12100         sizeof(mmu_wred_drop_curve_profile_5_entry_t) / sizeof(uint32);
  12101     entry_words[6] =
  12102         sizeof(mmu_wred_drop_curve_profile_6_entry_t) / sizeof(uint32);
  12103     entry_words[7] =
  12104         sizeof(mmu_wred_drop_curve_profile_7_entry_t) / sizeof(uint32);
  12105     entry_words[8] =
  12106         sizeof(mmu_wred_drop_curve_profile_8_entry_t) / sizeof(uint32);
  12107 
  12108     rv = soc_profile_mem_create(unit, wred_mems, entry_words, 9,
  12109                                 _bcm_hx5_wred_profile[unit]);
  12110     if (rv != SOC_E_NONE) {
  12111         _bcm_hx5_cosq_cleanup(unit);
  12112         return rv;
  12113     }
  12114 
  12115     /* Create profile for PRIO2COS_PROFILE register */
  12116     if (_bcm_hx5_prio2cos_profile[unit] == NULL) {
  12117         _bcm_hx5_prio2cos_profile[unit] =
  12118             sal_alloc(sizeof(soc_profile_reg_t), "PRIO2COS_PROFILE Profile Reg");
  12119         if (_bcm_hx5_prio2cos_profile[unit] == NULL) {
  12120             _bcm_hx5_cosq_cleanup(unit);
  12121             return BCM_E_MEMORY;
  12122         }
  12123         soc_profile_reg_t_init(_bcm_hx5_prio2cos_profile[unit]);
  12124     }
  12125     reg = PRIO2COS_PROFILE_64r;
  12126     rv = soc_profile_reg_create(unit, &reg, 1, _bcm_hx5_prio2cos_profile[unit]);
  12127     if (rv != SOC_E_NONE) {
  12128         _bcm_hx5_cosq_cleanup(unit);
  12129         return rv;
  12130     }
  12131 
  12132     if (_bcm_hx5_cosq_cpu_cosq_config[unit][0] == NULL) {
  12133         cpu_cosq_config_p = sal_alloc(SOC_HX5_NUM_CPU_QUEUES *
  12134                 sizeof(_bcm_hx5_cosq_cpu_cosq_config_t), "CPU Cosq Config");
  12135         if (cpu_cosq_config_p == NULL) {
  12136             _bcm_hx5_cosq_cleanup(unit);
  12137             return BCM_E_MEMORY;
  12138         }
  12139         if (NUM_CPU_COSQ(unit) > SOC_HX5_NUM_CPU_QUEUES) {
  12140             /* Invalid CPU Queues */
  12141             if (cpu_cosq_config_p != NULL) {
  12142                 sal_free(cpu_cosq_config_p);
  12143                 cpu_cosq_config_p = NULL;
  12144             }
  12145             _bcm_hx5_cosq_cleanup(unit);
  12146             return BCM_E_INIT;
  12147         }
  12148         for (i = 0; i < NUM_CPU_COSQ(unit); i++) {
  12149             _bcm_hx5_cosq_cpu_cosq_config[unit][i] = cpu_cosq_config_p + i;
  12150         }
  12151     }
  12152 
  12153     if (soc_feature(unit, soc_feature_helix5_ecn)) {
  12154         rv = _bcm_hx5_ecn_init(unit);
  12155         if (rv != BCM_E_NONE) {
  12156             if (cpu_cosq_config_p != NULL) {
  12157                 sal_free(cpu_cosq_config_p);
  12158                 cpu_cosq_config_p = NULL;
  12159             }
  12160             _bcm_hx5_cosq_cleanup(unit);
  12161             return rv;
  12162         }
  12163     }
  12164 
  12165 #if defined(INCLUDE_PSTATS)
  12166     if (soc_feature(unit, soc_feature_pstats)) {
  12167         rv = _bcm_pstats_init(unit);
  12168         if (rv != BCM_E_NONE) {
  12169             if (cpu_cosq_config_p != NULL) {
  12170                 sal_free(cpu_cosq_config_p);
  12171                 cpu_cosq_config_p = NULL;
  12172             }
  12173             _bcm_hx5_cosq_cleanup(unit);
  12174             return rv;
  12175         }
  12176     }
  12177 #endif /* INCLUDE_PSTATS */
  12178 
  12179 #if defined (INCLUDE_TCB) && defined (BCM_TCB_SUPPORT)
  12180     if (soc_feature(unit, soc_feature_tcb)) {
  12181         rv = bcm_hx5_cosq_tcb_init(unit);
  12182     }
  12183     if (rv != SOC_E_NONE) {
  12184         if (cpu_cosq_config_p != NULL) {
  12185             sal_free(cpu_cosq_config_p);
  12186             cpu_cosq_config_p = NULL;
  12187         }
  12188         _bcm_hx5_cosq_cleanup(unit);
  12189         return rv;
  12190     }
  12191 #endif
  12192 
  12193 #ifdef BCM_WARM_BOOT_SUPPORT
  12194     if (SOC_WARM_BOOT(unit)) {
  12195         rv = bcm_hx5_cosq_reinit(unit);
  12196         if (rv != BCM_E_NONE) {
  12197             if (cpu_cosq_config_p != NULL) {
  12198                 sal_free(cpu_cosq_config_p);
  12199                 cpu_cosq_config_p = NULL;
  12200             }
  12201             _bcm_hx5_cosq_cleanup(unit);
  12202         }
  12203     /*
  12204      * COVERITY
  12205      *
  12206      * This checker will not be True.
  12207      * cpu_cosq_config_p pointer is assigned to
  12208      * _bcm_hx5_cosq_cpu_cosq_config global data
  12209      * structure.
  12210      */
  12211     /* coverity[resource_leak] */
  12212         return rv;
  12213     } else {
  12214         rv = _bcm_hx5_cosq_wb_alloc(unit);
  12215         if (rv != BCM_E_NONE) {
  12216             if (cpu_cosq_config_p != NULL) {
  12217                 sal_free(cpu_cosq_config_p);
  12218                 cpu_cosq_config_p = NULL;
  12219             }
  12220             _bcm_hx5_cosq_cleanup(unit);
  12221             return rv;
  12222         }
  12223     }
  12224 #endif /* BCM_WARM_BOOT_SUPPORT */
  12225 
  12226     /* Assign default init values for CPU info */
  12227     for (i = 0; i < NUM_CPU_COSQ(unit); i++) {
  12228         if (_bcm_hx5_cosq_cpu_cosq_config[unit][i] == NULL) {
  12229             if (cpu_cosq_config_p != NULL) {
  12230                 sal_free(cpu_cosq_config_p);
  12231                 cpu_cosq_config_p = NULL;
  12232             }
  12233             _bcm_hx5_cosq_cleanup(unit);
  12234             return BCM_E_MEMORY;
  12235         }
  12236         sal_memset(_bcm_hx5_cosq_cpu_cosq_config[unit][i], 0,
  12237                    sizeof(_bcm_hx5_cosq_cpu_cosq_config_t));
  12238         _bcm_hx5_cosq_cpu_cosq_config[unit][i]->enable = 1;
  12239     }
  12240 
  12241     /* Add default entries for PORT_COS_MAP memory profile */
  12242     rv = bcm_hx5_cosq_config_set(unit, numq);
  12243     if (rv != BCM_E_NONE) {
  12244         if (cpu_cosq_config_p != NULL) {
  12245             sal_free(cpu_cosq_config_p);
  12246             cpu_cosq_config_p = NULL;
  12247         }
  12248         _bcm_hx5_cosq_cleanup(unit);
  12249         return rv;
  12250     }
  12251 
  12252     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  12253         /* Clear the WRED memories pointing to WRED profiles */
  12254         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_WRED_CONFIGm)[pipe];
  12255         rv = soc_mem_clear(unit, mem, COPYNO_ALL, 1);
  12256         if (rv != SOC_E_NONE) {
  12257             if (cpu_cosq_config_p != NULL) {
  12258                 sal_free(cpu_cosq_config_p);
  12259                 cpu_cosq_config_p = NULL;
  12260             }
  12261             _bcm_hx5_cosq_cleanup(unit);
  12262             return rv;
  12263         }
  12264     }
  12265 	
  12266     /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */
  12267     sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green));
  12268     sal_memset(&entry_tcp_yellow,0, sizeof(entry_tcp_yellow));
  12269     sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red));
  12270     sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green));
  12271     sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow));
  12272     sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red));
  12273     sal_memset(&entry_ecn_green, 0, sizeof(entry_ecn_green));
  12274     sal_memset(&entry_ecn_yellow,0, sizeof(entry_ecn_yellow));
  12275     sal_memset(&entry_ecn_red, 0, sizeof(entry_ecn_red));
  12276     entries[0] = &entry_tcp_green;
  12277     entries[1] = &entry_tcp_yellow;
  12278     entries[2] = &entry_tcp_red;
  12279     entries[3] = &entry_nontcp_green;
  12280     entries[4] = &entry_nontcp_yellow;
  12281     entries[5] = &entry_nontcp_red;
  12282     entries[6] = &entry_ecn_green;
  12283     entries[7] = &entry_ecn_yellow;
  12284     entries[8] = &entry_ecn_red;
  12285 
  12286     for (ii = 0; ii < HX5_WRED_PROFILE_NUM; ii++) {
  12287         soc_mem_field32_set(unit, wred_mems[ii], entries[ii],
  12288                             MIN_THDf, 0xffff);
  12289         soc_mem_field32_set(unit, wred_mems[ii], entries[ii],
  12290                             MAX_THDf, 0xffff);
  12291     }
  12292     profile_index = 0xffffffff;
  12293     wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_WRED_CONFIGm)[0];
  12294     wred_prof_count = soc_mem_index_count(unit, wred_config_mem);
  12295 
  12296     /* In HX5 Profile table duplicate across all pipes.
  12297         * Ref count needs to be updated too */
  12298     wred_prof_count *= NUM_PIPE(unit);
  12299     while(wred_prof_count) {
  12300         if (profile_index == 0xffffffff) {
  12301             rv = soc_profile_mem_add(unit, _bcm_hx5_wred_profile[unit],
  12302                                      entries, 1, &profile_index);
  12303         } else {
  12304             rv = soc_profile_mem_reference(unit, _bcm_hx5_wred_profile[unit],
  12305                                            profile_index, 0);
  12306         }
  12307         if (rv != SOC_E_NONE) {
  12308             if (cpu_cosq_config_p != NULL) {
  12309                 sal_free(cpu_cosq_config_p);
  12310                 cpu_cosq_config_p = NULL;
  12311             }
  12312             _bcm_hx5_cosq_cleanup(unit);
  12313             return rv;
  12314         }
  12315         wred_prof_count -= 1;
  12316     }
  12317 
  12318     /* Add default entries for PRIO2COS_PROFILE register profile */
  12319     sal_memset(rval64s, 0, sizeof(rval64s));
  12320     prval64s[0] = rval64s;
  12321     profile_index = 0xffffffff;
  12322     PBMP_ALL_ITER(unit, port) {
  12323         if (IS_CPU_PORT(unit, port) || IS_FAE_PORT(unit, port)) {
  12324             continue;
  12325         }
  12326         if (profile_index == 0xffffffff) {
  12327             rv = soc_profile_reg_add(unit, _bcm_hx5_prio2cos_profile[unit],
  12328                                      prval64s, 16, &profile_index);
  12329         } else {
  12330             rv = soc_profile_reg_reference(unit, _bcm_hx5_prio2cos_profile[unit],
  12331                                            profile_index, 0);
  12332         }
  12333         if (rv != SOC_E_NONE) {
  12334             if (cpu_cosq_config_p != NULL) {
  12335                 sal_free(cpu_cosq_config_p);
  12336                 cpu_cosq_config_p = NULL;
  12337             }
  12338             _bcm_hx5_cosq_cleanup(unit);
  12339             return rv;
  12340         }
  12341     }
  12342 
  12343     /* Create default gport tree */
  12344     _BCM_HX5_MMU_INFO(unit)->gport_tree_created = FALSE;
  12345     PBMP_ALL_ITER(unit, port) {
  12346         phy_port = si->port_l2p_mapping[port];
  12347         mmu_port = si->port_p2m_mapping[phy_port];
  12348         if (IS_LB_PORT(unit, port) || 
  12349                  IS_FAE_PORT(unit, port) ) {
  12350             continue;
  12351         }
  12352         if(IS_CPU_PORT(unit, port)){
  12353             rv = _bcm_hx5_cosq_cpu_tree_create(unit, port);
  12354             if (rv != BCM_E_NONE) {
  12355                 if (cpu_cosq_config_p != NULL) {
  12356                     sal_free(cpu_cosq_config_p);
  12357                     cpu_cosq_config_p = NULL;
  12358                 }
  12359                 _bcm_hx5_cosq_cleanup(unit);
  12360                 return rv;
  12361             }
  12362         }else if (_HX5_IS_ST_PORT(unit, mmu_port)) {
  12363             rv = _bcm_hx5_cosq_st_gport_tree_create(unit, port);
  12364             if (rv != BCM_E_NONE) {
  12365                 if (cpu_cosq_config_p != NULL) {
  12366                     sal_free(cpu_cosq_config_p);
  12367                     cpu_cosq_config_p = NULL;
  12368                 }
  12369                 _bcm_hx5_cosq_cleanup(unit);
  12370                 return rv;
  12371             }
  12372         } else {
  12373             rv = _bcm_hx5_cosq_gport_tree_create(unit, port);
  12374             if (rv != BCM_E_NONE) {
  12375                 if (cpu_cosq_config_p != NULL) {
  12376                     sal_free(cpu_cosq_config_p);
  12377                     cpu_cosq_config_p = NULL;
  12378                 }
  12379                 _bcm_hx5_cosq_cleanup(unit);
  12380                 return rv;
  12381             }
  12382         }
  12383     }
  12384     _BCM_HX5_MMU_INFO(unit)->gport_tree_created = TRUE;
  12385 
  12386     rv = _bcm_hx5_cosq_gport_default_config(unit);
  12387     if (rv != BCM_E_NONE) {
  12388         if (cpu_cosq_config_p != NULL) {
  12389             sal_free(cpu_cosq_config_p);
  12390             cpu_cosq_config_p = NULL;
  12391         }
  12392         _bcm_hx5_cosq_cleanup(unit);
  12393         return rv;
  12394     }
  12395 
  12396     /* BST INIT */
  12397     sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t));
  12398     bst_callbks.resolve_index = &_bcm_hx5_bst_index_resolve;
  12399     bst_callbks.reverse_resolve_index = &_bcm_hx5_cosq_bst_map_resource_to_gport_cos;
  12400     rv = _bcm_bst_attach(unit, &bst_callbks);
  12401     if (rv != BCM_E_NONE) {
  12402         if (cpu_cosq_config_p != NULL) {
  12403             sal_free(cpu_cosq_config_p);
  12404             cpu_cosq_config_p = NULL;
  12405         }
  12406         _bcm_hx5_cosq_cleanup(unit);
  12407         return rv;
  12408     }
  12409 
  12410     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  12411         rv = _bcm_pfc_deadlock_init(unit);
  12412         if (rv != BCM_E_NONE) {
  12413             if (cpu_cosq_config_p != NULL) {
  12414                 sal_free(cpu_cosq_config_p);
  12415                 cpu_cosq_config_p = NULL;
  12416             }
  12417             _bcm_hx5_cosq_cleanup(unit);
  12418             return rv;
  12419         }
  12420     }
  12421     sal_memset(hx5_time_domain_info, 0x0, sizeof(hx5_time_domain_info));
  12422     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  12423         mmu_wred_config_entry_t entry;
  12424         uint32 time_id = 0;
  12425         uint32 wred_mem_count = 0;
  12426 
  12427         wred_config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_WRED_CONFIGm)[pipe];
  12428         wred_mem_count = soc_mem_index_count(unit, wred_config_mem);
  12429         if (INVALIDm != wred_config_mem) {
  12430             for (i = 0; i< wred_mem_count; i++){ 
  12431                 BCM_IF_ERROR_RETURN
  12432                     (soc_mem_read(unit, wred_config_mem, MEM_BLOCK_ALL, i,
  12433                                   &entry));
  12434                 time_id = soc_mem_field32_get(unit, wred_config_mem, &entry,
  12435                         TIME_DOMAIN_SELf);
  12436                 if(time_id < _BCM_HX5_NUM_TIME_DOMAIN) {
  12437                     hx5_time_domain_info[unit][time_id].ref_count ++;
  12438                 }
  12439             }
  12440         }
  12441     }
  12442 
  12443     for (i = 0; i < _BCM_HX5_NUM_WRED_RESOLUTION_TABLE; i++) {
  12444         if (i == 0) {
  12445             _bcm_hx5_wred_resolution_tbl[i] = 1;
  12446         } else {
  12447             _bcm_hx5_wred_resolution_tbl[i] = 0;
  12448         }
  12449     }
  12450 
  12451 
  12452 
  12453 
  12454     return BCM_E_NONE;
  12455 }
  12456 
  12457 /*
  12458  * Function:
  12459  *     bcm_hx5_cosq_port_attach
  12460  * Purpose:
  12461  *     Initialize Cosq for newly added port
  12462  * Parameters:
  12463  *     unit    - (IN) unit number
  12464  *     port    - (IN) Logical port.
  12465  * Returns:
  12466  *     BCM_E_XXX
  12467  */
  12468 int
  12469 bcm_hx5_cosq_port_attach(int unit, bcm_port_t port)
  12470 {
  12471     int default_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN, default_weight = 1;
  12472     uint64 rval64s[16], *prval64s[1];
  12473     uint32 profile_index;
  12474     int phy_port, mmu_port;
  12475     soc_info_t *si = &SOC_INFO(unit);
  12476 
  12477 
  12478     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
  12479         IS_MANAGEMENT_PORT(unit, port)) {
  12480         return BCM_E_PARAM;
  12481     }
  12482 
  12483     phy_port = si->port_l2p_mapping[port];
  12484     mmu_port = si->port_p2m_mapping[phy_port];
  12485     /* Increase the reference of default PRIO2COS_PROFILE */
  12486     sal_memset(rval64s, 0, sizeof(rval64s));
  12487     prval64s[0] = rval64s;
  12488     BCM_IF_ERROR_RETURN
  12489         (soc_profile_reg_add(unit, _bcm_hx5_prio2cos_profile[unit],
  12490                               prval64s, 16, &profile_index));
  12491 
  12492     /* Create gport tree */
  12493     _BCM_HX5_MMU_INFO(unit)->gport_tree_created = FALSE;
  12494     if (_HX5_IS_ST_PORT(unit, mmu_port)) {
  12495         BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_st_gport_tree_create(unit, port));
  12496     } else {
  12497         BCM_IF_ERROR_RETURN(_bcm_hx5_cosq_gport_tree_create(unit, port));
  12498     }
  12499     _BCM_HX5_MMU_INFO(unit)->gport_tree_created = TRUE;
  12500 
  12501     /* Set Default Scheduler Configuration on the ports */
  12502     BCM_IF_ERROR_RETURN
  12503         (_bcm_hx5_cosq_sched_config_port(unit, port, default_mode,
  12504                                          default_weight));
  12505 
  12506     return BCM_E_NONE;
  12507 }
  12508 
  12509 /*
  12510  * Function:
  12511  *     bcm_hx5_cosq_port_detach
  12512  * Purpose:
  12513  *     Clear cosq configuration of port
  12514  * Parameters:
  12515  *     unit    - (IN) unit number
  12516  *     port    - (IN) Logical port.
  12517  * Returns:
  12518  *     BCM_E_XXX
  12519  */
  12520 int
  12521 bcm_hx5_cosq_port_detach(int unit, bcm_port_t port)
  12522 {
  12523     _bcm_hx5_cosq_port_info_t *port_info = NULL;
  12524     _bcm_hx5_cosq_st_port_info_t *stport_info = NULL;
  12525     int phy_port, mmu_port, index;
  12526     uint32 rval, profile_index;
  12527 
  12528     soc_info_t *si = &SOC_INFO(unit);
  12529 
  12530     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
  12531         IS_MANAGEMENT_PORT(unit, port)) {
  12532         return BCM_E_PARAM;
  12533     }
  12534 
  12535     phy_port = si->port_l2p_mapping[port];
  12536     mmu_port = si->port_p2m_mapping[phy_port];
  12537     _HX5_PORT_INDEX_GET(unit, mmu_port, index); 
  12538 
  12539     /* Destroy cosq gport tree on port */
  12540     if (_HX5_IS_ST_PORT(unit, mmu_port)) {
  12541         stport_info = &_bcm_hx5_cosq_st_port_info[unit][index]; 
  12542         sal_memset(stport_info, 0, sizeof(_bcm_hx5_cosq_st_port_info_t));
  12543     } else {
  12544         port_info = &_bcm_hx5_cosq_port_info[unit][index];
  12545         sal_memset(port_info, 0, sizeof(_bcm_hx5_cosq_port_info_t));
  12546     }
  12547 
  12548     /* Decrease the reference of defalt PRIO2COS_PROFILE */
  12549     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, PORT_LLFC_CFGr, port, 0, &rval));
  12550     profile_index = soc_reg_field_get(unit, PORT_LLFC_CFGr, rval,
  12551                                       PROFILE_INDEXf) * 16;
  12552     BCM_IF_ERROR_RETURN
  12553         (soc_profile_reg_delete(unit, _bcm_hx5_prio2cos_profile[unit],
  12554                                 profile_index));
  12555 
  12556     /* Clear cosq */
  12557     si->port_num_cosq[port] = 0;
  12558     si->port_cosq_base[port] = 0;
  12559     si->port_num_uc_cosq[port] = 0;
  12560     si->port_uc_cosq_base[port] = 0;
  12561     si->port_num_ext_cosq[port] = 0;
  12562 
  12563     return BCM_E_NONE;
  12564 }
  12565 
  12566 /*
  12567  * Function:
  12568  *     _bcm_hx5_port_enqueue_set
  12569  * Purpose:
  12570  *     Enable or Disable enqueing packets to the port
  12571  * Parameters:
  12572  *     unit       - (IN) unit number
  12573  *     gport      - (IN) gport of the port
  12574  *     enable     - (IN) TRUE to enable
  12575  *                       FALSE to disable
  12576  * Returns:
  12577  *     BCM_E_XXX
  12578  */
  12579 
  12580 int
  12581 _bcm_hx5_port_enqueue_set(int unit, bcm_port_t gport, int enable)
  12582 {
  12583     bcm_port_t local_port = -1;
  12584 
  12585     BCM_IF_ERROR_RETURN
  12586         (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
  12587 
  12588     SOC_IF_ERROR_RETURN(
  12589         soc_td3_port_mmu_tx_enable_set(unit, local_port, enable));
  12590     SOC_IF_ERROR_RETURN(
  12591         soc_td3_port_mmu_rx_enable_set(unit, local_port, enable));
  12592 
  12593     return BCM_E_NONE;
  12594 }
  12595 
  12596 /*
  12597  * Function:
  12598  *     _bcm_hx5_port_enqueue_get
  12599  * Purpose:
  12600  *     Get the enqueing state of the port
  12601  * Parameters:
  12602  *     unit       - (IN) unit number
  12603  *     gport      - (IN) gport of the port
  12604  *     enable     - (IN) TRUE for both rx and tx are enable
  12605  *                       FALSE for rx/tx is disable
  12606  * Returns:
  12607  *     BCM_E_XXX
  12608  */
  12609 
  12610 int
  12611 _bcm_hx5_port_enqueue_get(int unit, bcm_port_t gport,
  12612                           int *enable)
  12613 {
  12614     bcm_port_t local_port = -1;
  12615     int rx_enable = 0, tx_enable = 0;
  12616 
  12617     if (enable == NULL) {
  12618         return BCM_E_INTERNAL;
  12619     }
  12620 
  12621     BCM_IF_ERROR_RETURN(
  12622         _bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
  12623 
  12624     SOC_IF_ERROR_RETURN(
  12625         soc_td3_port_mmu_tx_enable_get(unit, local_port, &tx_enable));
  12626     SOC_IF_ERROR_RETURN(
  12627         soc_td3_port_mmu_rx_enable_get(unit, local_port, &rx_enable));
  12628 
  12629     if (rx_enable && tx_enable) {
  12630         *enable = TRUE;
  12631     } else {
  12632         *enable = FALSE;
  12633     }
  12634 
  12635     return BCM_E_NONE;
  12636 }
  12637 /*
  12638  * Function:
  12639  *     bcm_hx5_cosq_cpu_cosq_enable_get
  12640  * Purpose:
  12641  *     To get enable/disable status on Rx of packets on the specified CPU cosq.
  12642  * Parameters:
  12643  *     unit    - (IN) unit number
  12644  *     cosq    - (IN) CPU Cosq ID
  12645  *     enable  - (IN) Enable/Disable
  12646  * Returns:
  12647  *     BCM_E_XXX
  12648  */
  12649 int
  12650 bcm_hx5_cosq_cpu_cosq_enable_get(int unit, bcm_cos_queue_t cosq, int *enable)
  12651 {
  12652     uint32 entry[SOC_MAX_MEM_WORDS];
  12653     int index, hw_enable;
  12654     _bcm_hx5_cosq_cpu_cosq_config_t *cpu_cosq;
  12655     soc_info_t *si;
  12656     soc_mem_t thdm_mem = MMU_THDM_DB_QUEUE_CONFIG_PIPE0m;
  12657     soc_field_t min_limit, shared_limit, limit_enable, dynamic_enable;
  12658 
  12659     si = &SOC_INFO(unit);
  12660 
  12661     if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) {
  12662         return BCM_E_PARAM;
  12663     }
  12664 
  12665     cpu_cosq = _bcm_hx5_cosq_cpu_cosq_config[unit][cosq];
  12666 
  12667     if (!cpu_cosq) {
  12668         return BCM_E_INTERNAL;
  12669     }
  12670 
  12671     /* CPU Port (0) - MC cosq's range from 1290 - 1337. */
  12672     index = si->port_cosq_base[CMIC_PORT(unit)] + cosq;
  12673     hw_enable = 1;
  12674 
  12675     /* Sync up software record with hardware status. */
  12676     BCM_IF_ERROR_RETURN(soc_mem_read(unit, thdm_mem, MEM_BLOCK_ALL, index,
  12677                                      &entry));
  12678     min_limit = soc_mem_field32_get(unit, thdm_mem, &entry, Q_MIN_LIMITf);
  12679     shared_limit = soc_mem_field32_get(unit, thdm_mem, &entry, Q_SHARED_LIMITf);
  12680     limit_enable = soc_mem_field32_get(unit, thdm_mem, &entry, Q_LIMIT_ENABLEf);
  12681     dynamic_enable = soc_mem_field32_get(unit, thdm_mem, &entry, Q_LIMIT_DYNAMICf);
  12682 
  12683     if ((limit_enable != 0) && (dynamic_enable == 0) &&
  12684         (min_limit == 0) && (shared_limit == 0)) {
  12685         hw_enable = 0;
  12686     }
  12687     cpu_cosq->enable = hw_enable;
  12688 
  12689     *enable = cpu_cosq->enable;
  12690     return BCM_E_NONE;
  12691 
  12692     return BCM_E_NONE;
  12693 }
  12694 /*
  12695  * Function:
  12696  *     bcm_hx5_cosq_cpu_cosq_enable_set
  12697  * Purpose:
  12698  *     To enable/disable Rx of packets on the specified CPU cosq.
  12699  * Parameters:
  12700  *     unit    - (IN) unit number
  12701  *     cosq    - (IN) CPU Cosq ID
  12702  *     enable  - (IN) Enable/Disable
  12703  * Returns:
  12704  *     BCM_E_XXX
  12705  */
  12706 int
  12707 bcm_hx5_cosq_cpu_cosq_enable_set(int unit, bcm_cos_queue_t cosq, int enable)
  12708 {
  12709     uint32 entry[SOC_MAX_MEM_WORDS];
  12710     int i, index, enable_status;
  12711     _bcm_hx5_cosq_cpu_cosq_config_t *cpu_cosq_config;
  12712     soc_info_t *si;
  12713     soc_mem_t thdm_mem[] = {
  12714         MMU_THDM_DB_QUEUE_CONFIG_PIPE0m,
  12715         MMU_THDM_MCQE_QUEUE_CONFIG_PIPE0m
  12716     };
  12717 
  12718     si = &SOC_INFO(unit);
  12719 
  12720     if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) {
  12721         return BCM_E_PARAM;
  12722     }
  12723 
  12724     cpu_cosq_config = _bcm_hx5_cosq_cpu_cosq_config[unit][cosq];
  12725 
  12726     if (!cpu_cosq_config) {
  12727         return BCM_E_INTERNAL;
  12728     }
  12729 
  12730     BCM_IF_ERROR_RETURN(bcm_hx5_cosq_cpu_cosq_enable_get(unit, cosq,
  12731                         &enable_status));
  12732     if (enable == enable_status) {
  12733         return BCM_E_NONE;
  12734     }
  12735 
  12736     /* CPU Port (0) - MC cosq's range from 1290 - 1337. */
  12737     index = si->port_cosq_base[CMIC_PORT(unit)] + cosq;
  12738 
  12739     /* To set DB and QE entries */
  12740     for (i = 0; i < 2; i++) {
  12741         BCM_IF_ERROR_RETURN
  12742             (soc_mem_read(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry));
  12743 
  12744         /* When enabled, restore the Min and Shared from the cached value */
  12745         if (!enable) {
  12746             cpu_cosq_config->q_min_limit[i] = soc_mem_field32_get(unit,
  12747                                                 thdm_mem[i], &entry,
  12748                                                 Q_MIN_LIMITf);
  12749             cpu_cosq_config->q_shared_limit[i] = soc_mem_field32_get(unit,
  12750                                                     thdm_mem[i], &entry,
  12751                                                     Q_SHARED_LIMITf);
  12752             cpu_cosq_config->q_limit_dynamic[i] = soc_mem_field32_get(unit,
  12753                                                     thdm_mem[i], &entry,
  12754                                                     Q_LIMIT_DYNAMICf);
  12755             cpu_cosq_config->q_limit_enable[i] = soc_mem_field32_get(unit,
  12756                                                     thdm_mem[i], &entry,
  12757                                                     Q_LIMIT_ENABLEf);
  12758             cpu_cosq_config->q_color_limit_enable[i] = soc_mem_field32_get(unit,
  12759                                                         thdm_mem[i], &entry,
  12760                                                         Q_COLOR_LIMIT_ENABLEf);
  12761         }
  12762         soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_LIMIT_DYNAMICf,
  12763                             enable ? cpu_cosq_config->q_limit_dynamic[i] : 0);
  12764         soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_LIMIT_ENABLEf,
  12765                             enable ? cpu_cosq_config->q_limit_enable[i] : 1);
  12766         soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_COLOR_LIMIT_ENABLEf,
  12767                             enable ? cpu_cosq_config->q_color_limit_enable[i] :1);
  12768         soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_MIN_LIMITf,
  12769                             enable ? cpu_cosq_config->q_min_limit[i] : 0);
  12770         soc_mem_field32_set(unit, thdm_mem[i], &entry, Q_SHARED_LIMITf,
  12771                             enable ? cpu_cosq_config->q_shared_limit[i] : 0);
  12772         cpu_cosq_config->enable = enable;
  12773         BCM_IF_ERROR_RETURN
  12774             (soc_mem_write(unit, thdm_mem[i], MEM_BLOCK_ALL, index, &entry));
  12775     }
  12776 
  12777     return BCM_E_NONE;
  12778 }
  12779 
  12780 /*
  12781  * Function:
  12782  *     bcm_hx5_cosq_field_classifier_get
  12783  * Purpose:
  12784  *     Get classifier type information.
  12785  * Parameters:
  12786  *     unit          - (IN) unit number
  12787  *     classifier_id - (IN) Classifier ID
  12788  *     classifier    - (OUT) Classifier info
  12789  * Returns:
  12790  *     BCM_E_XXX
  12791  */
  12792 int
  12793 bcm_hx5_cosq_field_classifier_get(int unit, int classifier_id,
  12794                                   bcm_cosq_classifier_t *classifier)
  12795 {
  12796     if (classifier == NULL) {
  12797         return BCM_E_PARAM;
  12798     }
  12799     sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t));
  12800 
  12801     if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
  12802         classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD;
  12803     }
  12804 
  12805     return BCM_E_NONE;
  12806 }
  12807 
  12808 /*
  12809  * Function:
  12810  *     bcm_hx5_cosq_field_classifier_id_create
  12811  * Purpose:
  12812  *     Create a cosq classifier.
  12813  * Parameters:
  12814  *     unit          - (IN) unit number
  12815  *     classifier    - (IN) Classifier attributes
  12816  *     classifier_id - (OUT) Classifier ID
  12817  * Returns:
  12818  *     BCM_E_XXX
  12819  */
  12820 int
  12821 bcm_hx5_cosq_field_classifier_id_create(int unit, bcm_cosq_classifier_t
  12822                                         *classifier, int *classifier_id)
  12823 {
  12824     int rv;
  12825     int ref_count = 0;
  12826     int ent_per_set = _HX5_MMU_NUM_INT_PRI;
  12827     int i;
  12828 
  12829     if (NULL == classifier || NULL == classifier_id) {
  12830         return BCM_E_PARAM;
  12831     }
  12832 
  12833     for (i = 0; i < SOC_MEM_SIZE(unit, IFP_COS_MAPm); i += ent_per_set) {
  12834         rv = soc_profile_mem_ref_count_get(
  12835                 unit, _bcm_hx5_ifp_cos_map_profile[unit], i, &ref_count);
  12836         if (SOC_FAILURE(rv)) {
  12837             return rv;
  12838         }
  12839         if (0 == ref_count) {
  12840             break;
  12841         }
  12842     }
  12843 
  12844     if (i >= SOC_MEM_SIZE(unit, IFP_COS_MAPm) && ref_count != 0) {
  12845         *classifier_id = 0;
  12846         return BCM_E_RESOURCE;
  12847     }
  12848 
  12849     _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set));
  12850 
  12851     return BCM_E_NONE;
  12852 }
  12853 
  12854 /*
  12855  * Function:
  12856  *      bcm_hx5_cosq_field_classifier_id_destroy
  12857  * Purpose:
  12858  *      Free resource associated with this field classifier id.
  12859  * Parameters:
  12860  *      unit          - (IN) Unit number.
  12861  *      classifier_id - (IN) Classifier ID
  12862  * Returns:
  12863  *      BCM_E_xxx
  12864  */
  12865 int
  12866 bcm_hx5_cosq_field_classifier_id_destroy(int unit, int classifier_id)
  12867 {
  12868     return BCM_E_NONE;
  12869 }
  12870 
  12871 /*
  12872  * Function:
  12873  *     bcm_hx5_cosq_field_classifier_map_set
  12874  * Purpose:
  12875  *     Set internal priority to ingress field processor CoS queue override
  12876  *     mapping.
  12877  * Parameters:
  12878  *     unit           - (IN) unit number
  12879  *     classifier_id  - (OUT) Classifier ID
  12880  *     count          - (IN) Number of elements in priority_array and cosq_array
  12881  *     priority_array - (IN) Array of internal priorities
  12882  *     cosq_array     - (IN) Array of COS queues
  12883  * Returns:
  12884  *     BCM_E_XXX
  12885  * Notes:
  12886  *      Supported count value is [0-16] and 48
  12887  *      When count = [0-16]
  12888  *          Array Index [15-0] : Maps Prio[15-0] to UC, MC, HG and RQE cos[15-0]
  12889  *      When count = 48
  12890  *      Prio Array Index Map
  12891  *          Array Index [15-0] : Maps Prio[15-0] to UC and HG cos[15-0] 
  12892  *          Array Index [31-16] : Maps Prio[15-0] to MC and HG  cos[15-0]
  12893  *          Array Index [47-32] : Maps Prio[15-0] to RQE cos[15-0]
  12894  */
  12895 int
  12896 bcm_hx5_cosq_field_classifier_map_set(int unit, int classifier_id, int count,
  12897                         bcm_cos_t *priority_array, bcm_cos_queue_t *cosq_array)
  12898 {
  12899     int rv;
  12900     int i;
  12901     int max_entries = _HX5_MMU_NUM_INT_PRI;
  12902     uint32 index, new_index;
  12903     void *entries[1];
  12904     ifp_cos_map_entry_t ent_buf[_HX5_MMU_NUM_INT_PRI];
  12905     soc_field_t field = -1;
  12906     soc_field_t field1 = -1;
  12907 
  12908     /* Input parameter check. */
  12909     if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
  12910         return BCM_E_PARAM;
  12911     }
  12912 
  12913     if (NULL == priority_array || NULL == cosq_array) {
  12914         return BCM_E_PARAM;
  12915     }
  12916 
  12917     if ((count > max_entries) && (count != (max_entries * 3))) {
  12918         return BCM_E_PARAM;
  12919     }
  12920 
  12921     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries);
  12922     entries[0] = ent_buf;
  12923 
  12924     if (count != (max_entries * 3)) {
  12925         for (i = 0; i < count; i++) {
  12926             if (priority_array[i] < max_entries) {
  12927                 /* When count != max_entries * 3
  12928                    We program the same mapping for all three
  12929                    fields UC/MC/RQE/HG queues.
  12930                    Hence cos_array[i] cannot have value more than
  12931                    equal to 26 */
  12932                 if ((cosq_array[i] < 0) ||
  12933                     (cosq_array[i] >= SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT)) {
  12934                     return BCM_E_PARAM;
  12935                 }
  12936                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
  12937                                     IFP_MC_COSf, cosq_array[i]);
  12938                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
  12939                                     IFP_UC_COSf, cosq_array[i]);
  12940                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
  12941                                     IFP_HG_COSf, cosq_array[i]);
  12942                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
  12943                                     IFP_RQE_Q_NUMf, 
  12944                                     (cosq_array[i] > _HX5_MMU_NUM_RQE_QUEUES) ? _HX5_MMU_NUM_RQE_QUEUES : cosq_array[i]);
  12945             }
  12946         }
  12947     } else {
  12948         for (i = 0; i < count; i++) {
  12949             field = field1 = -1;
  12950             if (priority_array[i] < max_entries) {
  12951                 if (i < max_entries) {
  12952                     /* Number of UCAST queue per port = 26 */
  12953                     if ((cosq_array[i] < 0) ||
  12954                         (cosq_array[i] >= SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT)) {
  12955                         return BCM_E_PARAM;
  12956                     }
  12957                     field = IFP_UC_COSf;
  12958                     field1 = IFP_HG_COSf;
  12959                 } else if (i < (max_entries * 2)) {
  12960                     /* Number of MCAST queue per port = 26 */
  12961                     if ((cosq_array[i] < 0) ||
  12962                         (cosq_array[i] >= SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT)) {
  12963                         return BCM_E_PARAM;
  12964                     }
  12965                     field = IFP_MC_COSf;
  12966                     field1 = IFP_HG_COSf;
  12967                 } else {
  12968                     if ((cosq_array[i] < 0) ||
  12969                         (cosq_array[i] >= SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT)) {
  12970                         return BCM_E_PARAM;
  12971                     }
  12972                     /* Number of RQE queue per unit = 11 */
  12973                     if (cosq_array[i] > _HX5_MMU_NUM_RQE_QUEUES) {
  12974                        cosq_array[i] = _HX5_MMU_NUM_RQE_QUEUES;
  12975                     }
  12976                     field = IFP_RQE_Q_NUMf;
  12977                 }
  12978                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
  12979                         field, cosq_array[i]);
  12980                 if (field1 != -1) {
  12981                     soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
  12982                             field1, cosq_array[i]);
  12983                 }
  12984             }
  12985         }
  12986     }
  12987 
  12988     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  12989 
  12990     rv = soc_profile_mem_delete(unit, _bcm_hx5_ifp_cos_map_profile[unit],
  12991                                 index * max_entries);
  12992 
  12993     /* If rv = SOC_E_NONE means that there exists a
  12994      * mapping for given classifier_id which is now
  12995      * successfully deleted and we can overwrite.
  12996      * rv = SOC_E_NOT_FOUND means there was no mapping
  12997      * for given classifier_id and we can create a new mapping
  12998      * Otherwise there is something else wrong and we return
  12999      * the error value returned by soc_profile_mem_delete()
  13000      */
  13001     if ((rv != SOC_E_NONE) && (rv != SOC_E_NOT_FOUND)) {
  13002         return rv;
  13003     }
  13004 
  13005     SOC_IF_ERROR_RETURN
  13006         (soc_profile_mem_add(unit, _bcm_hx5_ifp_cos_map_profile[unit],
  13007                              entries, max_entries, &new_index));
  13008 
  13009     /* If we get (index == new_index / max_entries) means we have
  13010      * a successful mapping operation.
  13011      * But if they are not equal which means there already exists
  13012      * a similar mapping associated with other classifier_id hence
  13013      * we return BCM_E_EXISTS.
  13014      */
  13015 
  13016     if (index != (new_index / max_entries)) {
  13017         SOC_IF_ERROR_RETURN
  13018             (soc_profile_mem_delete(unit, _bcm_hx5_ifp_cos_map_profile[unit],
  13019                                     new_index));
  13020         return BCM_E_EXISTS;
  13021     }
  13022 
  13023     return BCM_E_NONE;
  13024 }
  13025 
  13026 /*
  13027  * Function:
  13028  *      bcm_hx5_cosq_field_classifier_map_get
  13029  * Purpose:
  13030  *      Get internal priority to ingress field processor CoS queue
  13031  *      override mapping information.
  13032  * Parameters:
  13033  *      unit           - (IN) Unit number.
  13034  *      classifier_id  - (IN) Classifier ID
  13035  *      array_max      - (IN) Size of priority_array and cosq_array
  13036  *      priority_array - (IN) Array of internal priorities
  13037  *      cosq_array     - (OUT) Array of COS queues
  13038  *      array_count    - (OUT) Size of cosq_array
  13039  * Returns:
  13040  *      BCM_E_xxx
  13041  * Notes:
  13042  *      Supported array_max = [0-16] and 48
  13043  *      When array_max = [0-16]
  13044  *          Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0]
  13045  *      When array_max = 48
  13046  *      Prio Array Index Map
  13047  *          Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0]
  13048  *          Array Index [31-16] : Maps Prio[15-0] to MC cos[15-0]
  13049  *          Array Index [47-32] : Maps Prio[15-0] to RQE cos[15-0]
  13050  */
  13051 int
  13052 bcm_hx5_cosq_field_classifier_map_get(int unit, int classifier_id, int array_max,
  13053     bcm_cos_t *priority_array, bcm_cos_queue_t *cosq_array, int *array_count)
  13054 {
  13055     int rv;
  13056     int i;
  13057     int ent_per_set = _HX5_MMU_NUM_INT_PRI;
  13058     uint32 index;
  13059     void *entries[1];
  13060     ifp_cos_map_entry_t ent_buf[_HX5_MMU_NUM_INT_PRI];
  13061     soc_field_t field = -1;
  13062 
  13063     /* Input parameter check. */
  13064     if (NULL == priority_array || NULL == cosq_array || NULL == array_count) {
  13065         return BCM_E_PARAM;
  13066     }
  13067 
  13068     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set);
  13069     entries[0] = ent_buf;
  13070 
  13071     /* Get profile table entry set base index. */
  13072     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  13073 
  13074     /* Read out entries from profile table into allocated buffer. */
  13075     rv = soc_profile_mem_get(unit, _bcm_hx5_ifp_cos_map_profile[unit],
  13076                              index * ent_per_set, ent_per_set, entries);
  13077     if (SOC_FAILURE(rv)) {
  13078         return rv;
  13079     }
  13080 
  13081     if (array_max <= ent_per_set) {
  13082         *array_count = array_max;
  13083     } else if ((array_max > ent_per_set) && (array_max < (ent_per_set * 3))) {
  13084         return BCM_E_PARAM;
  13085     } else {
  13086         *array_count = ent_per_set * 3;
  13087     }
  13088         /* Copy values into API OUT parameters. */
  13089     for (i = 0; i < *array_count; i++) {
  13090         if (priority_array[i % 16] >= _HX5_MMU_NUM_INT_PRI) {
  13091             return BCM_E_PARAM;
  13092         }
  13093         if (i < ent_per_set) {
  13094             field = IFP_UC_COSf;
  13095         } else if (i < (ent_per_set * 2)) {
  13096             field = IFP_MC_COSf;
  13097         } else {
  13098             field = IFP_RQE_Q_NUMf;
  13099         }
  13100         cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm,
  13101                                             &ent_buf[priority_array[i]],
  13102                                             field);
  13103     }
  13104 
  13105     return BCM_E_NONE;
  13106 }
  13107 
  13108 /*
  13109  * Function:
  13110  *      bcm_hx5_cosq_field_classifier_map_clear
  13111  * Purpose:
  13112  *      Delete an internal priority to ingress field processor CoS queue
  13113  *      override mapping profile set.
  13114  * Parameters:
  13115  *      unit          - (IN) Unit number.
  13116  *      classifier_id - (IN) Classifier ID
  13117  * Returns:
  13118  *      BCM_E_xxx
  13119  */
  13120 int
  13121 bcm_hx5_cosq_field_classifier_map_clear(int unit, int classifier_id)
  13122 {
  13123     int ent_per_set = _HX5_MMU_NUM_INT_PRI;
  13124     uint32 index;
  13125 
  13126     /* Get profile table entry set base index. */
  13127     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
  13128 
  13129     /* Delete the profile entries set. */
  13130     SOC_IF_ERROR_RETURN
  13131         (soc_profile_mem_delete(unit,
  13132                                 _bcm_hx5_ifp_cos_map_profile[unit],
  13133                                 index * ent_per_set));
  13134     return BCM_E_NONE;
  13135 }
  13136 
  13137 STATIC int
  13138 _bcm_hx5_cosq_cpu_port_info_dump(int unit)
  13139 {
  13140     _bcm_hx5_cosq_cpu_port_info_t *port_info;
  13141      bcm_port_t port = 0; /* CPU Port */
  13142     _bcm_hx5_cosq_node_t *node;
  13143     int index, new_index;
  13144     soc_hx5_sched_mode_e sched_mode = 0;
  13145     int weight = 0;
  13146 
  13147     char *sched_modes[] = {"X", "SP", "WRR", "WERR"};
  13148 
  13149     if (!SOC_PORT_VALID(unit, port)) {
  13150         return BCM_E_PORT;
  13151     }
  13152     port_info = _bcm_hx5_cosq_cpu_port_info[unit];
  13153     if (port_info == NULL) {
  13154         return BCM_E_INIT;
  13155     }
  13156 
  13157     LOG_CLI((BSL_META_U(unit,
  13158                         "=== CPU PORT ===\n")));
  13159 
  13160     LOG_CLI((BSL_META_U(unit,
  13161                         "Nodes\n")));
  13162     for (index = 0; index < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; index++) {
  13163         /* Node */
  13164         node = &port_info->sched[index];
  13165         BCM_IF_ERROR_RETURN(
  13166                 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, index,
  13167                     &sched_mode, &weight, 0, 0));
  13168         new_index = (index >= 2) ? index - 2 : index;
  13169         LOG_CLI((BSL_META_U(unit,
  13170                         "L%d.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13171                     node->level - 1, new_index, node->gport, node->hw_index,
  13172                     sched_modes[sched_mode], weight));
  13173     }
  13174 
  13175     LOG_CLI((BSL_META_U(unit,
  13176                         "\nMC Queues\n")));
  13177     for (index = 0; index < SOC_HX5_NUM_CPU_QUEUES; index++) {
  13178         int parent_id = 0;
  13179         /* MC Queue */
  13180         node = &port_info->mcast[index];
  13181         BCM_IF_ERROR_RETURN(
  13182                 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, index,
  13183                                                 &sched_mode, &weight, 1, 0));
  13184         BCM_IF_ERROR_RETURN(
  13185             _bcm_hx5_cosq_node_get(unit, node->parent_gport, NULL, NULL,
  13186                                    &parent_id, NULL));
  13187         LOG_CLI((BSL_META_U(unit,
  13188                             "    MC.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d"
  13189                             " PARENT=%d\n"),
  13190                              index, node->gport, node->hw_index,
  13191                              sched_modes[sched_mode], weight,
  13192                              parent_id));
  13193     }
  13194     LOG_CLI((BSL_META_U(unit,
  13195                         "=========== \n")));
  13196 
  13197     return BCM_E_NONE;
  13198 }
  13199 
  13200 STATIC int
  13201 _bcm_hx5_cosq_st_port_info_dump(int unit, bcm_port_t port)
  13202 {
  13203     _bcm_hx5_cosq_st_port_info_t *port_info;
  13204     _bcm_hx5_cosq_node_t *node;
  13205     int index, empty, port_index;
  13206     int l1index = 0, l2index = 0, l3index = 0;
  13207     int l1_max = 0, l2_max = 0, l3_max = 0;
  13208     soc_hx5_sched_mode_e sched_mode = 0;
  13209     int weight = 0;
  13210     char *sched_modes[] = {"X", "SP", "WRR", "WERR"};
  13211     int phy_port, mmu_port;
  13212     soc_info_t *si = &SOC_INFO(unit);
  13213 
  13214 
  13215     phy_port = si->port_l2p_mapping[port];
  13216     mmu_port = si->port_p2m_mapping[phy_port];
  13217     _HX5_PORT_INDEX_GET(unit, mmu_port, port_index);
  13218 
  13219     if (!SOC_PORT_VALID(unit, port)) {
  13220         return BCM_E_PORT;
  13221     }
  13222     port_info = &_bcm_hx5_cosq_st_port_info[unit][port_index];
  13223 
  13224     empty = TRUE;
  13225     for (index = 0; index < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; index++) {
  13226         if (port_info->sched[index].numq > 0) {
  13227             empty = FALSE;
  13228             break;
  13229         }
  13230     }
  13231     if (empty) {
  13232         for (index = 0; index < SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; index++) {
  13233             if (port_info->ucast[index].numq > 0) {
  13234                 empty = FALSE;
  13235                 break;
  13236             }
  13237         }
  13238     }
  13239     if (empty) {
  13240         for (index = 0; index < SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; index++) {
  13241             if (port_info->mcast[index].numq > 0) {
  13242                 empty = FALSE;
  13243                 break;
  13244             }
  13245         }
  13246     }
  13247 
  13248     if (empty == TRUE) {
  13249         return BCM_E_NOT_FOUND;
  13250     }
  13251 
  13252     LOG_CLI((BSL_META_U(unit,
  13253                         "=== PORT %d\n"), port));
  13254 
  13255     for (index = 0; index < 3; index++) {
  13256         /* Node */
  13257         node = &port_info->sched[index];
  13258 
  13259         BCM_IF_ERROR_RETURN(
  13260                 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, index,
  13261                     &sched_mode, &weight, 0, 0));
  13262         LOG_CLI((BSL_META_U(unit,
  13263                         "L0.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13264                     index, node->gport, node->hw_index,
  13265                     sched_modes[sched_mode], weight));
  13266 
  13267         if (index == 0) {
  13268             l1index = 3;
  13269             l1_max = 4;
  13270         } else if(index == 1) {
  13271             l1index = 5;
  13272             l1_max = 5;
  13273         } else {
  13274             l1index = 6;
  13275             l1_max = 6;
  13276         }
  13277         for(; l1index <= l1_max; l1index++) {
  13278             node = &port_info->sched[l1index];
  13279             BCM_IF_ERROR_RETURN(
  13280                     _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l1index,
  13281                         &sched_mode, &weight, 0, 0));
  13282             LOG_CLI((BSL_META_U(unit,
  13283                             "    L1.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13284                         l1index - 3, node->gport, node->hw_index,
  13285                         sched_modes[sched_mode], weight));
  13286 
  13287             if (index == 0) {
  13288                 if (l1index == 3) {
  13289                     l2index = 7;
  13290                     l2_max = l2index + 8;
  13291                     l3index = 8;
  13292                     l3_max = l3index + 8;
  13293                 } else  if(l1index == 4) {
  13294                     l2index = 15;
  13295                     l2_max = l2index + 8;
  13296                     l3index = 16;
  13297                     l3_max = l3index + 8;
  13298                 }
  13299             } else if (index == 1) {
  13300                 l2index = 23;
  13301                 l2_max = l2index + 8;
  13302                 l3index = 16;
  13303                 l3_max = l3index + 8;
  13304             } else {
  13305                 l2index = 31;
  13306                 l2_max = l2index + 2;
  13307                 l3index = 24;
  13308                 l3_max = l3index + 2;
  13309             }
  13310 
  13311 
  13312             for (; l2index < l2_max && l3index < l3_max; l2index++, l3index++) {
  13313                 node = &port_info->sched[l2index];
  13314                 BCM_IF_ERROR_RETURN(
  13315                         _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l2index,
  13316                             &sched_mode, &weight, 0, 0));
  13317                 LOG_CLI((BSL_META_U(unit,
  13318                                 "       L2.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13319                             l2index - 7, node->gport, node->hw_index,
  13320                             sched_modes[sched_mode], weight));
  13321 
  13322                 /* UC Queue */
  13323                 node = &port_info->ucast[l3index];
  13324                 BCM_IF_ERROR_RETURN(
  13325                         _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l3index,
  13326                             &sched_mode, &weight, 0, 0));
  13327                 LOG_CLI((BSL_META_U(unit,
  13328                                 "           UC.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13329                             l3index, node->gport, node->hw_index,
  13330                             sched_modes[sched_mode], weight));
  13331 
  13332                 /* MC Queue */
  13333                 node = &port_info->mcast[l3index];
  13334                 BCM_IF_ERROR_RETURN(
  13335                         _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l3index,
  13336                             &sched_mode, &weight, 1, 0));
  13337                 LOG_CLI((BSL_META_U(unit,
  13338                                 "           MC.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13339                             l3index, node->gport, node->hw_index,
  13340                             sched_modes[sched_mode], weight));
  13341             }
  13342         }
  13343     }
  13344     LOG_CLI((BSL_META_U(unit,
  13345                         "=========== \n")));
  13346 
  13347     return BCM_E_NONE;
  13348 }
  13349 
  13350 STATIC int
  13351 _bcm_hx5_cosq_port_info_dump(int unit, bcm_port_t port)
  13352 {
  13353     _bcm_hx5_cosq_port_info_t *port_info;
  13354     _bcm_hx5_cosq_node_t *node;
  13355     int index = 0, empty;
  13356     int l1index, l2index, l3index;
  13357     soc_hx5_sched_mode_e sched_mode = 0;
  13358     int weight = 0, port_index;
  13359     char *sched_modes[] = {"X", "SP", "WRR", "WERR"};
  13360     int phy_port, mmu_port;
  13361     soc_info_t *si = &SOC_INFO(unit);
  13362 
  13363 
  13364     phy_port = si->port_l2p_mapping[port];
  13365     mmu_port = si->port_p2m_mapping[phy_port];
  13366     _HX5_PORT_INDEX_GET(unit, mmu_port, port_index);
  13367 
  13368     if (!SOC_PORT_VALID(unit, port)) {
  13369         return BCM_E_PORT;
  13370     }
  13371     port_info = &_bcm_hx5_cosq_port_info[unit][port_index];
  13372 
  13373     empty = TRUE;
  13374     for (index = 0; index < SOC_HX5_NUM_SCHEDULER_PER_PORT; index++) {
  13375         if (port_info->sched[index].numq > 0) {
  13376             empty = FALSE;
  13377             break;
  13378         }
  13379     }
  13380     if (empty) {
  13381         for (index = 0; index < SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; index++) {
  13382             if (port_info->ucast[index].numq > 0) {
  13383                 empty = FALSE;
  13384                 break;
  13385             }
  13386         }
  13387     }
  13388     if (empty) {
  13389         for (index = 0; index < SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; index++) {
  13390             if (port_info->mcast[index].numq > 0) {
  13391                 empty = FALSE;
  13392                 break;
  13393             }
  13394         }
  13395     }
  13396 
  13397     if (empty == TRUE) {
  13398         return BCM_E_NOT_FOUND;
  13399     }
  13400 
  13401     LOG_CLI((BSL_META_U(unit,
  13402                         "=== PORT %d\n"), port));
  13403 
  13404     node = &port_info->sched[index];
  13405 
  13406     BCM_IF_ERROR_RETURN(
  13407             _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, index,
  13408                 &sched_mode, &weight, 0, 0));
  13409     LOG_CLI((BSL_META_U(unit,
  13410                     "L0.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13411                 index, node->gport, node->hw_index,
  13412                 sched_modes[sched_mode], weight));
  13413 
  13414     for (l1index = 1; l1index < 3; l1index++) {
  13415         /* Node */
  13416         node = &port_info->sched[l1index];
  13417 
  13418         BCM_IF_ERROR_RETURN(
  13419                 _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l1index,
  13420                     &sched_mode, &weight, 0, 0));
  13421         LOG_CLI((BSL_META_U(unit,
  13422                         "    L1.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13423                     l1index - 1, node->gport, node->hw_index,
  13424                     sched_modes[sched_mode], weight));
  13425 
  13426         l2index = ((l1index - 1) * 8) + 3;
  13427         l3index = ((l1index - 1) * 8);
  13428 
  13429         for (; l2index < ((l1index - 1) * 8) + 11 && l3index < ((l1index - 1) * 8) + 8; l2index++, l3index++) {
  13430             node = &port_info->sched[l2index];
  13431 
  13432             BCM_IF_ERROR_RETURN(
  13433                     _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l2index,
  13434                         &sched_mode, &weight, 0, 0));
  13435             LOG_CLI((BSL_META_U(unit,
  13436                             "       L2.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13437                         l2index - 3, node->gport, node->hw_index,
  13438                         sched_modes[sched_mode], weight));
  13439 
  13440                 /* UC Queue */
  13441                 node = &port_info->ucast[l3index];
  13442                 BCM_IF_ERROR_RETURN(
  13443                         _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l3index,
  13444                             &sched_mode, &weight, 0, 0));
  13445                 LOG_CLI((BSL_META_U(unit,
  13446                                 "          UC.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13447                             l3index, node->gport, node->hw_index,
  13448                             sched_modes[sched_mode], weight));
  13449 
  13450                 /* MC Queue */
  13451                 node = &port_info->mcast[l3index];
  13452                 BCM_IF_ERROR_RETURN(
  13453                         _bcm_hx5_cosq_sched_mode_setget(unit, port, node->level, l3index,
  13454                             &sched_mode, &weight, 1, 0));
  13455                 LOG_CLI((BSL_META_U(unit,
  13456                                 "          MC.%d: GPORT=0x%x HW_INDEX=%d MODE=%s WT=%d\n"),
  13457                             l3index, node->gport, node->hw_index,
  13458                             sched_modes[sched_mode], weight));
  13459         }
  13460     }
  13461     LOG_CLI((BSL_META_U(unit,
  13462                         "=========== \n")));
  13463 
  13464     return BCM_E_NONE;
  13465 }
  13466 
  13467 int
  13468 bcm_hx5_dump_port_hsp(int unit, int port)
  13469 {
  13470     int phy_port, mmu_port;
  13471     soc_info_t *si = &SOC_INFO(unit);
  13472     LOG_CLI((BSL_META_U(unit,
  13473                     "\nSW Information COSQ - Unit %d\n"), unit));
  13474     if (!IS_FAE_PORT(unit, port) && !IS_LB_PORT(unit, port)) {
  13475         phy_port = si->port_l2p_mapping[port];
  13476         mmu_port = si->port_p2m_mapping[phy_port];
  13477         if (IS_CPU_PORT(unit, port)) {
  13478             (void)_bcm_hx5_cosq_cpu_port_info_dump(unit);
  13479         }
  13480         if(_HX5_IS_ST_PORT(unit, mmu_port)) {
  13481             (void)_bcm_hx5_cosq_st_port_info_dump(unit, port);
  13482         } else {
  13483             (void)_bcm_hx5_cosq_port_info_dump(unit, port);
  13484         }
  13485     }
  13486     return BCM_E_NONE;
  13487 }
  13488 /*
  13489  * Function:
  13490  *     bcm_hx5_cosq_sw_dump
  13491  * Purpose:
  13492  *     Displays COS Queue information maintained by software.
  13493  * Parameters:
  13494  *     unit - Device unit number
  13495  * Returns:
  13496  *     None
  13497  */
  13498 void
  13499 bcm_hx5_cosq_sw_dump(int unit)
  13500 {
  13501     bcm_port_t port;
  13502     int phy_port, mmu_port;
  13503     soc_info_t *si = &SOC_INFO(unit);
  13504     LOG_CLI((BSL_META_U(unit,
  13505                         "\nSW Information COSQ - Unit %d\n"), unit));
  13506 
  13507     PBMP_ALL_ITER(unit, port) {
  13508         phy_port = si->port_l2p_mapping[port];
  13509         mmu_port = si->port_p2m_mapping[phy_port];
  13510         if (IS_CPU_PORT(unit, port)) {
  13511             (void)_bcm_hx5_cosq_cpu_port_info_dump(unit);
  13512         }
  13513         if(_HX5_IS_ST_PORT(unit, mmu_port)) {
  13514             (void)_bcm_hx5_cosq_st_port_info_dump(unit, port);
  13515         } else {
  13516             (void)_bcm_hx5_cosq_port_info_dump(unit, port);
  13517         }
  13518     }
  13519     return;
  13520 }
  13521 
  13522 int
  13523 bcm_hx5_hgcos_select_port_control_set(int unit,  bcm_port_t port,
  13524                                       bcm_port_control_t type, int value)
  13525 {
  13526     soc_info_t *si;
  13527     int phy_port, mmu_port;
  13528     uint64 rval64, rval64_tmp, rval64_reset_tmp;
  13529     uint32 rval;
  13530     soc_reg_t reg = UC_HG_QUEUE_MODEr;
  13531     soc_field_t field = QUEUE_MODEf;
  13532     soc_reg_t reg1 = COS_MODE_SPLIT0r;
  13533     si = &SOC_INFO(unit);
  13534     phy_port = si->port_l2p_mapping[port];
  13535     mmu_port = si->port_p2m_mapping[phy_port];
  13536 
  13537     if ((value < 0) || (value > 1)) {
  13538         return BCM_E_PARAM;
  13539     }
  13540     COMPILER_64_ZERO(rval64);
  13541     COMPILER_64_ZERO(rval64_tmp);
  13542     COMPILER_64_ZERO(rval64_reset_tmp);
  13543 
  13544     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
  13545         IS_FAE_PORT(unit, port) || !_HX5_IS_ST_PORT(unit, mmu_port)) {
  13546         return BCM_E_PARAM;
  13547     }
  13548     BCM_IF_ERROR_RETURN
  13549         (soc_reg32_get(unit, reg, port, 0, &rval));
  13550 
  13551     soc_reg_field_set(unit, reg, &rval, field, value);
  13552 
  13553     BCM_IF_ERROR_RETURN
  13554         (soc_reg32_set(unit, reg, port, 0, rval));
  13555 
  13556     SOC_IF_ERROR_RETURN
  13557         (soc_trident3_xpe_reg_get(unit, reg1, -1, si->port_pipe[port],
  13558                                                               0, &rval64));
  13559     COMPILER_64_SET(rval64_tmp, 0, (2 << (mmu_port * 2)));
  13560     COMPILER_64_SET(rval64_reset_tmp, 0, (3 << (mmu_port * 2)));
  13561 
  13562     if (value) {
  13563         COMPILER_64_OR(rval64, rval64_tmp);
  13564     } else {
  13565         COMPILER_64_NOT(rval64_reset_tmp);
  13566         COMPILER_64_AND(rval64, rval64_reset_tmp);
  13567 
  13568     }
  13569     SOC_IF_ERROR_RETURN
  13570         (soc_trident3_xpe_reg_set(unit, reg1, -1, si->port_pipe[port],
  13571                                                               0, rval64));
  13572    return BCM_E_NONE;
  13573 }
  13574 
  13575 int 
  13576 bcm_hx5_hgcos_select_port_control_get(int unit,  bcm_port_t port,
  13577                                       bcm_port_control_t type, int *value)
  13578 {
  13579     soc_info_t *si;
  13580     int phy_port, mmu_port;
  13581     uint32 rval;
  13582     soc_reg_t reg = UC_HG_QUEUE_MODEr;
  13583     soc_field_t field = QUEUE_MODEf;
  13584     si = &SOC_INFO(unit);
  13585     phy_port = si->port_l2p_mapping[port];
  13586     mmu_port = si->port_p2m_mapping[phy_port];
  13587 
  13588     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
  13589         IS_FAE_PORT(unit, port) || !_HX5_IS_ST_PORT(unit, mmu_port)) {
  13590         return BCM_E_PARAM;
  13591     }
  13592 
  13593     BCM_IF_ERROR_RETURN
  13594         (soc_reg32_get(unit, reg, port, 0, &rval));
  13595 
  13596    *value =  soc_reg_field_get(unit, reg, rval, field);
  13597 
  13598    return BCM_E_NONE;
  13599 }
  13600 
  13601 int
  13602 bcm_hx5_cosq_gport_info_get(int unit, bcm_gport_t gport,
  13603                                     bcm_cosq_gport_level_info_t *info)
  13604 {
  13605 
  13606     int phy_port, mmu_port, local_port;
  13607     _bcm_hx5_cosq_node_t *node = NULL;
  13608     soc_info_t *si;
  13609 
  13610     if( NULL == info ) {
  13611         return BCM_E_PARAM;
  13612     }
  13613 
  13614     if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) &&
  13615             !BCM_GPORT_IS_SCHEDULER(gport) &&
  13616             !BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  13617         return BCM_E_PARAM;
  13618     }
  13619 
  13620     BCM_IF_ERROR_RETURN
  13621         (_bcm_hx5_cosq_node_get(unit, gport, NULL,
  13622                                 &local_port, NULL, &node));
  13623 
  13624     si = &SOC_INFO(unit);
  13625     phy_port = si->port_l2p_mapping[local_port];
  13626     mmu_port = si->port_p2m_mapping[phy_port];
  13627 
  13628     info->parent_port_type = (mmu_port < 16) ? BCM_COSQ_UPLINK_GPORT : BCM_COSQ_DOWNLINK_GPORT;
  13629     info->level = node->level;
  13630 
  13631     return BCM_E_NONE;
  13632 }
  13633 /* Routine to perform Inverse mapping for given Queue port back to Port/Priority
  13634  * which was defined by default or through cosq_mapping_set functions
  13635  */
  13636 int
  13637 _bcm_hx5_cosq_inv_mapping_get(int unit, bcm_gport_t gport,
  13638                              bcm_cos_queue_t cosq,
  13639                              uint32 flags, bcm_port_t *ing_port,
  13640                              bcm_cos_t *priority)
  13641 {
  13642     bcm_port_t local_port;
  13643     cos_map_sel_entry_t cos_map_sel_entry;
  13644     void *entries[1];
  13645     int index, ii;
  13646     bcm_cos_queue_t in_cosq = BCM_COS_INVALID, pri_cosq = BCM_COS_INVALID;
  13647     bcm_module_t    modid;
  13648     soc_field_t cos_field = INVALIDf;
  13649     port_cos_map_entry_t cos_map_entries[_HX5_MMU_NUM_INT_PRI];
  13650 
  13651     if ((flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP) &&
  13652        (flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP)) {
  13653         return BCM_E_PARAM;
  13654     }
  13655 
  13656     if ((ing_port == NULL) || (priority == NULL)) {
  13657         return BCM_E_PARAM;
  13658     }
  13659 
  13660     if (BCM_GPORT_IS_SET(gport)) {
  13661         if (!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) &&
  13662             !(BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) {
  13663             return BCM_E_PARAM;
  13664         }
  13665         BCM_IF_ERROR_RETURN
  13666             (_bcm_hx5_cosq_node_get(unit, gport, &modid, &local_port,
  13667                                    &in_cosq, NULL));
  13668     } else {
  13669         BCM_IF_ERROR_RETURN
  13670             (_bcm_hx5_cosq_localport_resolve(unit, gport, &local_port));
  13671         in_cosq = cosq;
  13672     }
  13673 
  13674     if ((cosq < -1) || (cosq >= _HX5_PORT_NUM_COS(unit, local_port))) {
  13675         return BCM_E_PARAM;
  13676     }
  13677 
  13678     if ((IS_CPU_PORT(unit, local_port)) || (IS_LB_PORT(unit, local_port))) {
  13679         return BCM_E_PARAM;
  13680     }
  13681 
  13682     *ing_port = local_port;
  13683 
  13684     if (flags == BCM_COSQ_GPORT_MCAST_QUEUE_GROUP) {
  13685         cos_field = MC_COS1f;
  13686     } else {
  13687         cos_field = UC_COS1f;
  13688     }
  13689 
  13690     if (in_cosq == BCM_COS_INVALID) {
  13691         return BCM_E_PARAM;
  13692     } else {
  13693         in_cosq %= _BCM_HX5_NUM_PFC_CLASS;
  13694     }
  13695 
  13696     entries[0] = &cos_map_entries;
  13697     BCM_IF_ERROR_RETURN
  13698         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
  13699                            &cos_map_sel_entry));
  13700     index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
  13701                                 SELECTf);
  13702     index *= _HX5_MMU_NUM_INT_PRI;
  13703 
  13704     BCM_IF_ERROR_RETURN
  13705         (soc_profile_mem_get(unit, _bcm_hx5_cos_map_profile[unit],
  13706                              index, _HX5_MMU_NUM_INT_PRI, entries));
  13707 
  13708     for (ii = 0; ii < _HX5_MMU_NUM_INT_PRI; ii++) {
  13709         pri_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm,
  13710                                        &cos_map_entries[ii], cos_field);
  13711         if (pri_cosq == in_cosq) {
  13712             /* Required Cosq found. Break as the index is the priority */
  13713             *priority = ii;
  13714             break;
  13715         }
  13716     }
  13717 
  13718     if (ii == _HX5_MMU_NUM_INT_PRI) {
  13719         /* Mapping cannot be found */
  13720         return BCM_E_NOT_FOUND;
  13721     }
  13722 
  13723     return BCM_E_NONE;
  13724 }
  13725 
  13726 int
  13727 bcm_hx5_pfc_deadlock_queue_info_get(int unit, bcm_gport_t gport,
  13728                                     bcm_port_t *mmu_port, bcm_port_t *local_port, int *type, int *split)
  13729 {
  13730     soc_info_t *si;
  13731     int pport = 0, mport = 0, lport = 0, in_cosq = 0;
  13732     bcm_module_t    modid;
  13733     si = &SOC_INFO(unit);
  13734 
  13735     if ((mmu_port == NULL) || (split == NULL) || (local_port == NULL) || (type == NULL)) {
  13736         return BCM_E_PARAM;
  13737     }
  13738 
  13739     if (BCM_GPORT_IS_SET(gport)) {
  13740         if (!(BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) &&
  13741             !(BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport))) {
  13742             return BCM_E_PARAM;
  13743         }
  13744         BCM_IF_ERROR_RETURN
  13745             (_bcm_hx5_cosq_node_get(unit, gport, &modid, &lport,
  13746                                    &in_cosq, NULL));
  13747    }
  13748    pport = si->port_l2p_mapping[lport];
  13749    mport = si->port_p2m_mapping[pport];
  13750 
  13751    *split = (mport > 15) ? 0 : 1;
  13752    *mmu_port = mport;
  13753    *local_port = lport;
  13754    *type = (in_cosq < 8) ? 0 : (in_cosq >= 8 && in_cosq < 16) ? 1 : 2;
  13755 
  13756    return BCM_E_NONE;
  13757 }
  13758 
  13759 int
  13760 bcm_hx5_pfc_deadlock_ignore_pfc_xoff_gen(int unit, int priority,
  13761                                         bcm_port_t port, uint32 *rval32)
  13762 {
  13763     uint32 profile_index, fc_class;
  13764     uint32 rval, uc_cos_bmp;
  13765     uint64 rval64[16], *rval64s[1];
  13766     static const soc_reg_t port_fc_reg = PORT_LLFC_CFGr;
  13767 
  13768     rval64s[0] = rval64;
  13769     BCM_IF_ERROR_RETURN
  13770         (soc_reg32_get(unit, port_fc_reg, port, 0, &rval));
  13771     profile_index = soc_reg_field_get(unit, port_fc_reg, rval, PROFILE_INDEXf) * 16;
  13772 
  13773     BCM_IF_ERROR_RETURN
  13774         (soc_profile_reg_get(unit, _bcm_hx5_prio2cos_profile[unit],
  13775                              profile_index, 16, rval64s));
  13776 
  13777     for (fc_class = 0; fc_class < _BCM_HX5_NUM_PFC_CLASS; ++fc_class ) {
  13778 
  13779         uc_cos_bmp = soc_reg64_field32_get(unit, PRIO2COS_PROFILE_64r, rval64[fc_class],
  13780                                            UC_COS_BMPf);
  13781         if (uc_cos_bmp & (1 << priority)) {
  13782             *rval32 = uc_cos_bmp;
  13783             return BCM_E_NONE;
  13784         }
  13785     }
  13786 
  13787     return BCM_E_NOT_FOUND;
  13788 }
  13789 
  13790 /*
  13791  *  Function:
  13792  *      bcm_hx5_pfc_deadlock_recovery_start
  13793  *  Purpose:
  13794  *      Begin recovery when a Port is deaclared to be in Deadlock by Hardware
  13795  *  Parameters:
  13796  *      unit - unit number
  13797  *      port - port number
  13798  *      priority - priority
  13799  *  Returns:
  13800  *      BCM_E_XXX
  13801  */
  13802 int
  13803 bcm_hx5_pfc_deadlock_recovery_start(int unit, bcm_port_t port, int priority)
  13804 {
  13805     int pipe, split, pos, cos = 0, index;
  13806     uint32 rval = 0, uc_cos_bmp = 0;
  13807     uint64 rval64, temp_mask64, temp_en64;
  13808     _bcm_hx5_pfc_hw_resorces_t *hw_res = NULL; 
  13809     _bcm_hx5_pfc_deadlock_control_t *pfc_deadlock_control = NULL; 
  13810 
  13811     if ((priority < 0) || (priority >= HX5_PFC_DEADLOCK_MAX_COS)) {
  13812         return BCM_E_PARAM;
  13813     }
  13814 
  13815     BCM_IF_ERROR_RETURN(
  13816             _bcm_hx5_cosq_localport_resolve(unit, port, &port));
  13817     if (port >= MAX_PORT(unit)) {
  13818         return BCM_E_PARAM;
  13819     }
  13820 
  13821     pfc_deadlock_control = _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit);
  13822     hw_res = &pfc_deadlock_control->hw_regs_fields;
  13823     SOC_IF_ERROR_RETURN(
  13824             soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos));
  13825 
  13826     BCM_IF_ERROR_RETURN(
  13827             _bcm_hx5_pfc_reg_index_get(unit, port, NULL, &index));
  13828 
  13829     COMPILER_64_ZERO(temp_en64);
  13830     COMPILER_64_ZERO(temp_mask64);
  13831 
  13832     if (pos < 32) {
  13833        COMPILER_64_SET(temp_mask64, 0, (1 << pos));
  13834     } else {
  13835         COMPILER_64_SET(temp_mask64, (1 << (pos - 32)), 0);
  13836     }
  13837 
  13838     COMPILER_64_OR(temp_en64, temp_mask64);
  13839 
  13840     BCM_IF_ERROR_RETURN(
  13841             _bcm_hx5_pfc_deadlock_hw_cos_index_get(unit, priority, &cos));
  13842 
  13843     /* Mask the Intr DD_TIMER_MASK by setting 1 (pbmp) */
  13844     COMPILER_64_ZERO(rval64);
  13845     SOC_IF_ERROR_RETURN(
  13846             soc_trident3_xpe_reg_get(unit, hw_res->timer_mask[split], -1, pipe,
  13847                 cos, &rval64));
  13848     COMPILER_64_OR(rval64, temp_mask64);
  13849     SOC_IF_ERROR_RETURN(
  13850             soc_trident3_xpe_reg_set(unit, hw_res->timer_mask[split], -1, pipe,
  13851                 cos, rval64));
  13852 
  13853     SOC_IF_ERROR_RETURN(
  13854             soc_reg32_get(unit, hw_res->port_config[index], port, 0, &rval));
  13855     priority = pfc_deadlock_control->pfc_cos2pri[cos];
  13856 
  13857     rval = _bcm_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, port,
  13858             &uc_cos_bmp);
  13859     if (rval != BCM_E_NONE) {
  13860         rval = 0;
  13861         rval |= (1 << priority);
  13862     } else {
  13863         rval = 0;
  13864         rval |= uc_cos_bmp;
  13865     }
  13866 
  13867     SOC_IF_ERROR_RETURN(
  13868             soc_reg32_set(unit, hw_res->port_config[index], port, 0, rval));
  13869 
  13870     return BCM_E_NONE;
  13871 }
  13872 
  13873 /*
  13874  * Function:
  13875  *    bcm_hx5_pfc_deadlock_recovery_exit
  13876  * Purpose:
  13877  *      Reset recovery state of a port and config port back in original state
  13878  * Parameters:
  13879  *      unit - unit number
  13880  *      port - port number
  13881  *      priority - priority
  13882  * Returns:
  13883  *      BCM_E_XXX
  13884  */
  13885     int
  13886 bcm_hx5_pfc_deadlock_recovery_exit(int unit, bcm_port_t port, int priority)
  13887 {
  13888     int pipe, split, pos, cos = 0, index;
  13889     uint32 rval = 0, uc_cos_bmp = 0;
  13890     uint64 rval64, temp_mask64, temp_en64;
  13891     _bcm_hx5_pfc_hw_resorces_t *hw_res = NULL;
  13892     _bcm_hx5_pfc_deadlock_control_t *pfc_deadlock_control = NULL;
  13893 
  13894     if ((priority < 0) || (priority >= HX5_PFC_DEADLOCK_MAX_COS)) {
  13895         return BCM_E_PARAM;
  13896     }
  13897 
  13898     BCM_IF_ERROR_RETURN(
  13899             _bcm_hx5_cosq_localport_resolve(unit, port, &port));
  13900     if (port >= MAX_PORT(unit)) {
  13901         return BCM_E_PARAM;
  13902     }
  13903 
  13904     pfc_deadlock_control = _BCM_HX5_UNIT_PFC_DEADLOCK_CONTROL(unit);
  13905     hw_res = &pfc_deadlock_control->hw_regs_fields;
  13906     SOC_IF_ERROR_RETURN(
  13907             soc_td3_mmu_bmp_reg_pos_get(unit, port, &pipe, &split, &pos));
  13908 
  13909     COMPILER_64_ZERO(temp_en64);
  13910     COMPILER_64_ZERO(temp_mask64);
  13911 
  13912     if (pos < 32) {
  13913         COMPILER_64_SET(temp_mask64, 0, (1 << pos));
  13914     } else {
  13915         COMPILER_64_SET(temp_mask64, (1 << (pos - 32)), 0);
  13916     }
  13917 
  13918     COMPILER_64_OR(temp_en64, temp_mask64);
  13919 
  13920     BCM_IF_ERROR_RETURN(
  13921             _bcm_hx5_pfc_deadlock_hw_cos_index_get(unit, priority, &cos));
  13922 
  13923     BCM_IF_ERROR_RETURN(
  13924             _bcm_hx5_pfc_reg_index_get(unit, port, NULL, &index));
  13925     /* For that port, set ignore_pfc_xoff = 0 (per port reg) */
  13926     SOC_IF_ERROR_RETURN(
  13927             soc_reg32_get(unit, hw_res->port_config[index], port, 0, &rval));
  13928 
  13929     rval = _bcm_pfc_deadlock_ignore_pfc_xoff_gen(unit, priority, port,
  13930             &uc_cos_bmp);
  13931     if (rval != BCM_E_NONE) {
  13932         rval = 0;
  13933         rval &= ~(1 << priority);
  13934     } else {
  13935         rval = 0;
  13936         rval &= ~uc_cos_bmp;
  13937     }
  13938 
  13939     SOC_IF_ERROR_RETURN(
  13940             soc_reg32_set(unit, hw_res->port_config[index], port, 0, rval));
  13941 
  13942     /* Mask the Intr DD_TIMER_MASK by setting 0 (pbmp) */
  13943     COMPILER_64_ZERO(rval64);
  13944     SOC_IF_ERROR_RETURN(
  13945             soc_trident3_xpe_reg_get(unit, hw_res->timer_mask[split], -1, pipe,
  13946                 cos, &rval64));
  13947     COMPILER_64_NOT(temp_mask64);
  13948     COMPILER_64_AND(rval64, temp_mask64);
  13949     SOC_IF_ERROR_RETURN(
  13950             soc_trident3_xpe_reg_set(unit, hw_res->timer_mask[split], -1, pipe,
  13951                 cos, rval64));
  13952 
  13953     /* Turn timer on DD_TIMER_ENABLE  by setting 1 (pbmp) */
  13954     COMPILER_64_ZERO(rval64);
  13955     SOC_IF_ERROR_RETURN(
  13956             soc_trident3_xpe_reg_get(unit, hw_res->timer_en[split], -1, pipe,
  13957                 cos, &rval64));
  13958     COMPILER_64_OR(rval64, temp_en64);
  13959     SOC_IF_ERROR_RETURN(
  13960             soc_trident3_xpe_reg_set(unit, hw_res->timer_en[split], -1, pipe,
  13961                 cos, rval64));
  13962 
  13963     return BCM_E_NONE;
  13964 }
  13965 
  13966 
  13967 
  13968 /* Function:
  13969  *      bcmi_hx5_port_cosmap_update
  13970  *  Purpose:
  13971  *     called during flexport during port attach/detach
  13972  *     to update the cos_map profile for the port
  13973  *  Parameters:
  13974  *      unit   - unit number
  13975  *      port   - port number
  13976  *      enable - add/delete
  13977  *  Returns:
  13978  *      BCM_E_XXX
  13979  */
  13980 
  13981 int
  13982 bcmi_hx5_port_cosmap_update(int unit, pbmp_t pbm, int enable)
  13983 {
  13984     port_cos_map_entry_t cos_map_entries[16];
  13985     cos_map_sel_entry_t cos_map_sel_entry;
  13986     void *entries[1];
  13987     uint32 index, old_index;
  13988     bcm_port_t port;
  13989     int cos, prio, numq, rv;
  13990     soc_mem_t mem = PORT_COS_MAPm;
  13991     uint32 i;
  13992 
  13993     numq = _BCM_HX5_NUM_COS(unit);
  13994 
  13995     SOC_PBMP_ITER(pbm, port) {
  13996         prio = 0;
  13997         sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
  13998         entries[0] = &cos_map_entries;
  13999 
  14000         if (enable) {
  14001             /*
  14002              * Distribute first 8 internal priority levels into the specified number
  14003              * of cosq, map remaining internal priority levels to highest priority
  14004              * cosq
  14005  */
  14006             sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
  14007             entries[0] = &cos_map_entries;
  14008 
  14009             for (cos = 0; cos < numq; cos++) {
  14010                 for (i = 8 / numq + (cos < 8 % numq ? 1 : 0); i > 0; i--) {
  14011                     soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
  14012                             UC_COS1f, cos);
  14013                     soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
  14014                             MC_COS1f, cos);
  14015                     soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
  14016                             HG_COSf, _HX5_NUM_COS_MAP_ENTRY + cos);
  14017                     prio++;
  14018                 }
  14019             }
  14020             for (prio = 8; prio < 16; prio++) {
  14021                 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f,
  14022                         numq - 1);
  14023                 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f,
  14024                         numq - 1);
  14025                 soc_mem_field32_set(unit, mem, &cos_map_entries[prio], HG_COSf,
  14026                         _HX5_NUM_COS_MAP_ENTRY + (numq - 1));
  14027             }
  14028 
  14029             SOC_IF_ERROR_RETURN
  14030                 (soc_profile_mem_add(unit, _bcm_hx5_cos_map_profile[unit], entries, 16,
  14031                                      &index));
  14032             BCM_IF_ERROR_RETURN(bcm_hx5_wireless_cos_map_update(unit, numq));
  14033             BCM_IF_ERROR_RETURN
  14034                 (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
  14035                                         index / 16));
  14036 
  14037         } else {
  14038             BCM_IF_ERROR_RETURN
  14039                 (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, port, &cos_map_sel_entry));
  14040             old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
  14041                     SELECTf);
  14042             old_index *= 16;
  14043 
  14044             rv = soc_profile_mem_delete(unit, _bcm_hx5_cos_map_profile[unit],
  14045                     old_index);
  14046 
  14047             if (BCM_FAILURE(rv)) {
  14048                 return rv;
  14049             }
  14050         }
  14051     }
  14052     return BCM_E_NONE;
  14053 }
  14054 
  14055 /*
  14056  * Function:
  14057  *    bcm_cosq_gport_traverse_by_port
  14058  * Purpose:
  14059  *     Walks through the valid COSQ GPORTs belong to a port and calls
  14060  *     the user supplied callback function for each entry.
  14061  * Parameters:
  14062  *     unit       - (IN) unit number
  14063  *     port       - (IN) port number or GPORT identifier
  14064  *     trav_fn    - (IN) Callback function.
  14065  *     user_data  - (IN) User data to be passed to callback function
  14066  * Returns:
  14067  *     BCM_E_NONE - Success.
  14068  *     BCM_E_XXX
  14069  */
  14070 
  14071 int
  14072 bcm_hx5_cosq_gport_traverse_by_port(int unit, bcm_gport_t port,
  14073                             bcm_cosq_gport_traverse_cb cb,
  14074                             void *user_data)
  14075 {
  14076     _bcm_hx5_cosq_port_info_t *port_info = NULL;
  14077     _bcm_hx5_cosq_st_port_info_t *stport_info = NULL;
  14078     _bcm_hx5_cosq_cpu_port_info_t *cpu_port_info = NULL;
  14079     bcm_module_t my_modid, modid_out;
  14080     bcm_port_t port_out, local_port;
  14081     bcm_gport_t gport;
  14082     int id, rv = SOC_E_NONE;
  14083     int phy_port, mmu_port, index;
  14084 
  14085     soc_info_t *si = &SOC_INFO(unit);
  14086 
  14087     if (_bcm_hx5_cosq_port_info[unit] == NULL) {
  14088         return BCM_E_INIT;
  14089     }
  14090     if (_bcm_hx5_cosq_st_port_info[unit] == NULL) {
  14091         return BCM_E_INIT;
  14092     }
  14093     if (_bcm_hx5_cosq_cpu_port_info[unit] == NULL) {
  14094         return BCM_E_INIT;
  14095     }
  14096 
  14097     if (BCM_GPORT_IS_SET(port) &&
  14098             (!BCM_GPORT_IS_LOCAL(port) &&
  14099              !BCM_GPORT_IS_DEVPORT(port) &&
  14100              !BCM_GPORT_IS_MODPORT(port))) {
  14101         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  14102                         "Invalid gport type\n")));
  14103         return BCM_E_PARAM;
  14104     }
  14105 
  14106     BCM_IF_ERROR_RETURN
  14107         (_bcm_hx5_cosq_localport_resolve(unit, port, &local_port));
  14108 
  14109 
  14110     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
  14111     BCM_IF_ERROR_RETURN
  14112         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, my_modid,  port,
  14113                                  &modid_out, &port_out));
  14114     BCM_GPORT_MODPORT_SET(gport, modid_out, port_out);
  14115 
  14116     phy_port = si->port_l2p_mapping[local_port];
  14117     mmu_port = si->port_p2m_mapping[phy_port];
  14118     _HX5_PORT_INDEX_GET(unit, mmu_port, index);
  14119     if (IS_CPU_PORT(unit, local_port)) {
  14120         cpu_port_info = _bcm_hx5_cosq_cpu_port_info[unit];
  14121     } else {
  14122         if(_HX5_IS_ST_PORT(unit, mmu_port)) {
  14123             stport_info = &_bcm_hx5_cosq_st_port_info[unit][index];
  14124         }else {
  14125             port_info = &_bcm_hx5_cosq_port_info[unit][index];
  14126         }
  14127     }
  14128 
  14129     if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) {
  14130         for (id = 0; id < SOC_HX5_NUM_UCAST_QUEUE_PER_PORT; id++) {
  14131             if (port_info->ucast[id].numq == 0) {
  14132                 continue;
  14133             }
  14134             rv = cb(unit, gport, port_info->ucast[id].numq,
  14135                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
  14136                     port_info->ucast[id].gport, user_data);
  14137         }
  14138 #ifdef BCM_CB_ABORT_ON_ERR
  14139         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
  14140             return rv;
  14141         }
  14142 #else
  14143         rv = BCM_E_NONE;
  14144 #endif
  14145     }
  14146 
  14147     if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) {
  14148         for (id = 0; id < SOC_HX5_NUM_UCAST_QUEUE_PER_ST_PORT; id++) {
  14149             if (stport_info->ucast[id].numq == 0) {
  14150                 continue;
  14151             }
  14152             rv = cb(unit, gport, stport_info->ucast[id].numq,
  14153                     BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
  14154                     stport_info->ucast[id].gport, user_data);
  14155         }
  14156 #ifdef BCM_CB_ABORT_ON_ERR
  14157         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
  14158             return rv;
  14159         }
  14160 #else
  14161         rv = BCM_E_NONE;
  14162 #endif
  14163     }
  14164 
  14165     if (IS_CPU_PORT(unit, local_port)) {
  14166         for (id = 0; id < SOC_HX5_NUM_CPU_QUEUES; id++) {
  14167             if (cpu_port_info->mcast[id].numq == 0) {
  14168                 continue;
  14169             }
  14170             rv = cb(unit, gport, cpu_port_info->mcast[id].numq,
  14171                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
  14172                     cpu_port_info->mcast[id].gport, user_data);
  14173 #ifdef BCM_CB_ABORT_ON_ERR
  14174             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
  14175                 return rv;
  14176             }
  14177 #else
  14178             rv = BCM_E_NONE;
  14179 #endif
  14180         }
  14181     }
  14182 
  14183     if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) {
  14184         for (id = 0; id < SOC_HX5_NUM_MCAST_QUEUE_PER_PORT; id++) {
  14185             if (port_info->mcast[id].numq == 0) {
  14186                 continue;
  14187             }
  14188             rv = cb(unit, gport, port_info->mcast[id].numq,
  14189                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
  14190                     port_info->mcast[id].gport, user_data);
  14191         }
  14192 #ifdef BCM_CB_ABORT_ON_ERR
  14193         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
  14194             return rv;
  14195         }
  14196 #else
  14197         rv = BCM_E_NONE;
  14198 #endif
  14199     }
  14200 
  14201 
  14202     if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) {
  14203         for (id = 0; id < SOC_HX5_NUM_MCAST_QUEUE_PER_ST_PORT; id++) {
  14204             if (stport_info->mcast[id].numq == 0) {
  14205                 continue;
  14206             }
  14207             rv = cb(unit, gport, stport_info->mcast[id].numq,
  14208                     BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
  14209                     stport_info->mcast[id].gport, user_data);
  14210         }
  14211 #ifdef BCM_CB_ABORT_ON_ERR
  14212         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
  14213             return rv;
  14214         }
  14215 #else
  14216         rv = BCM_E_NONE;
  14217 #endif
  14218     }
  14219 
  14220 
  14221     if (IS_CPU_PORT(unit, local_port)) {
  14222         for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_CPU_PORT; id++) {
  14223             if (cpu_port_info->sched[id].numq == 0) {
  14224                 continue;
  14225             }
  14226             rv = cb(unit, gport, cpu_port_info->sched[id].numq,
  14227                     BCM_COSQ_GPORT_SCHEDULER,
  14228                     cpu_port_info->sched[id].gport, user_data);
  14229 #ifdef BCM_CB_ABORT_ON_ERR
  14230             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
  14231                 return rv;
  14232             }
  14233 #else
  14234             rv = BCM_E_NONE;
  14235 #endif
  14236         }
  14237     }
  14238 
  14239     if (!IS_CPU_PORT(unit, local_port) && !_HX5_IS_ST_PORT(unit, mmu_port)) {
  14240         for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_PORT; id++) {
  14241             if (port_info->sched[id].numq == 0) {
  14242                 continue;
  14243             }
  14244             rv = cb(unit, gport, port_info->sched[id].numq,
  14245                     BCM_COSQ_GPORT_SCHEDULER,
  14246                     port_info->sched[id].gport, user_data);
  14247         }
  14248 #ifdef BCM_CB_ABORT_ON_ERR
  14249         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
  14250             return rv;
  14251         }
  14252 #else
  14253         rv = BCM_E_NONE;
  14254 #endif
  14255     }
  14256 
  14257 
  14258     if (!IS_CPU_PORT(unit, local_port) && _HX5_IS_ST_PORT(unit, mmu_port)) {
  14259         for (id = 0; id < SOC_HX5_NUM_SCHEDULER_PER_ST_PORT; id++) {
  14260             if (stport_info->sched[id].numq == 0) {
  14261                 continue;
  14262             }
  14263             rv = cb(unit, gport, stport_info->sched[id].numq,
  14264                     BCM_COSQ_GPORT_SCHEDULER,
  14265                     stport_info->sched[id].gport, user_data);
  14266         }
  14267 #ifdef BCM_CB_ABORT_ON_ERR
  14268         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
  14269             return rv;
  14270         }
  14271 #else
  14272         rv = BCM_E_NONE;
  14273 #endif
  14274     }
  14275 
  14276     return rv;
  14277 
  14278 }
  14279 #endif /* BCM_HELIX5_SUPPORT */