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


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