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


      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_TOMAHAWK3_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/tomahawk3.h>
     22 #include <soc/dma.h>
     23 #include <soc/mmu_config.h>
     24 #include <soc/init/tomahawk3_idb_init.h>
     25 #include <soc/pfc.h>
     26 #include <soc/uc.h>
     27 #include <soc/shared/qcm.h>
     28 #include <soc/scache_dictionary.h>
     29 
     30 #include <bcm/debug.h>
     31 #include <bcm/error.h>
     32 #include <bcm/cosq.h>
     33 #include <bcm_int/esw/mbcm.h>
     34 #include <bcm_int/esw/stack.h>
     35 #include <bcm_int/esw/cosq.h>
     36 #include <bcm_int/esw/virtual.h>
     37 #include <bcm_int/esw/tomahawk3.h>
     38 #include <bcm_int/esw/ecn.h>
     39 #include <bcm_int/esw/oob.h>
     40 #if defined(INCLUDE_PSTATS)
     41 #include <bcm_int/esw/pstats.h>
     42 #endif /* INCLUDE_PSTATS */
     43 #include <bcm_int/esw/pfc_deadlock.h>
     44 #include <bcm_int/bst.h>
     45 #include <bcm_int/esw_dispatch.h>
     46 #include <bcm_int/bst.h>
     47 #ifdef BCM_WARM_BOOT_SUPPORT
     48 #include <bcm_int/esw/switch.h>
     49 #endif /* BCM_WARM_BOOT_SUPPORT */
     50 #ifdef BCM_CMICM_SUPPORT
     51 #include <soc/cmicm.h>
     52 #endif /* BCM_CMICM_SUPPORT*/
     53 
     54 /*Local defines*/
     55 #define _BCM_TH3_NUM_QSCHED_PROFILES 8
     56 #define _BCM_TH3_NUM_PG_PROP_PROFILES 8
     57 #define _BCM_TH3_NUM_INTPRI_PG_MAP_PROFILES 8
     58 #define _BCM_TH3_NUM_PFC_CLASS_PROFILES 8
     59 #define _BCM_TH3_NUM_OOB_EGRQUEUE_MAP_PROFILES 4
     60 #define _BCM_TH3_NUM_WRED_PROFILES 9
     61 #define _BCM_TH3_QSCHED_MIN_WEIGHT 0
     62 #define _BCM_TH3_QSCHED_MAX_WEIGHT 127
     63 
     64 #define _TH3_ITMS_PER_DEV 2
     65 #define _BCM_TH3_COS_DEFAULT 12
     66 #define _BCM_TH3_COS_MAX  12
     67 #define _BCM_TH3_MCQ_MODE_DEFAULT 2
     68 #define _BCM_TH3_MMU_INFO(unit) _bcm_th3_mmu_info[(unit)]
     69 #define _BCM_TH3_NUM_SCHEDULER_PER_PORT 12
     70 #define _BCM_TH3_MAX_QUEUE_PER_PORT 12
     71 #define _BCM_TH3_MAX_NUM_UCAST_QUEUE_PER_PORT 12
     72 #define _BCM_TH3_MAX_NUM_MCAST_QUEUE_PER_PORT 6
     73 #define _BCM_TH3_MAX_NUM_QUEUE_PER_PORT 12
     74 #define _BCM_TH3_NUM_CPU_MCAST_QUEUE 48
     75 
     76 /* Number of COSQs configured for this unit */
     77 #define _TH3_NUM_COS(unit) NUM_COS(unit)
     78 
     79 #define _TH3_PORT_NUM_COS(unit, port) \
     80     ((IS_CPU_PORT(unit, port)) ? NUM_CPU_COSQ(unit) : \
     81         (IS_LB_PORT(unit, port)) ? 12 : _TH3_NUM_COS(unit))
     82 
     83 
     84 #define _BCM_TH3_NUM_TIME_DOMAIN    4
     85 
     86 typedef struct _bcm_th3_cosq_time_info_s {
     87     uint32 ref_count;
     88 } _bcm_th3_cosq_time_info_t;
     89 
     90 /* WRED can be enabled at per UC queue / port / service pool basis
     91 MMU_WRED_AVG_QSIZE used entry: (20*12 + 20*4 + 4) = 324
     92 */
     93 
     94 STATIC _bcm_th3_cosq_time_info_t th3_time_domain_info[BCM_MAX_NUM_UNITS][_BCM_TH3_NUM_TIME_DOMAIN] = {
     95   {
     96     {324}, /* Default all entries are pointing to TIME_0*/
     97     {0},
     98     {0},
     99     {0}
    100   }
    101 };
    102 
    103 #define TH3_WRED_CELL_FIELD_MAX       0x7ffff
    104 #define TH3_WRED_PROFILE_INDEX_INVALID    0xffffffff
    105 #define TH3_WRED_DROP_PROB_MAX_INDEX    14
    106 
    107 /*
    108  * index: degree, value: contangent(degree) * 100
    109  * max value is 0x7ffff (19-bit) at 0 degree
    110  */
    111 STATIC int
    112 _bcm_th3_cotangent_lookup_table[] =
    113 {
    114     /*  0.. 5 */ 262143, 5728, 2863, 1908, 1430, 1143,
    115     /*  6..11 */    951,  814,  711,  631,  567,  514,
    116     /* 12..17 */    470,  433,  401,  373,  348,  327,
    117     /* 18..23 */    307,  290,  274,  260,  247,  235,
    118     /* 24..29 */    224,  214,  205,  196,  188,  180,
    119     /* 30..35 */    173,  166,  160,  153,  148,  142,
    120     /* 36..41 */    137,  132,  127,  123,  119,  115,
    121     /* 42..47 */    111,  107,  103,  100,   96,   93,
    122     /* 48..53 */     90,   86,   83,   80,   78,   75,
    123     /* 54..59 */     72,   70,   67,   64,   62,   60,
    124     /* 60..65 */     57,   55,   53,   50,   48,   46,
    125     /* 66..71 */     44,   42,   40,   38,   36,   34,
    126     /* 72..77 */     32,   30,   28,   26,   24,   23,
    127     /* 78..83 */     21,   19,   17,   15,   14,   12,
    128     /* 84..89 */     10,    8,    6,    5,    3,    1,
    129     /* 90     */      0
    130 };
    131 
    132 /*
    133  * Given a slope (angle in degrees) from 0 to 90, return the number of cells
    134  * in the range from 0% drop probability to 100% drop probability.
    135  * Same as TD2.
    136  */
    137 STATIC int
    138 _bcm_th3_angle_to_cells(int angle)
    139 {
    140     return (_bcm_th3_cotangent_lookup_table[angle]);
    141 }
    142 
    143 /*
    144  * Given a number of packets in the range from 0% drop probability
    145  * to 100% drop probability, return the slope (angle in degrees).
    146  * Same as TD2.
    147  */
    148 STATIC int
    149 _bcm_th3_cells_to_angle(int packets)
    150 {
    151     int angle;
    152 
    153     for (angle = 90; angle >= 0 ; angle--) {
    154         if (packets <= _bcm_th3_cotangent_lookup_table[angle]) {
    155             break;
    156         }
    157     }
    158     return angle;
    159 }
    160 
    161 
    162 
    163 /*
    164  *  Convert HW drop probability to percent value
    165  *  Same as TH2.
    166  */
    167 STATIC int
    168 _bcm_th3_hw_drop_prob_to_percent[] = {
    169     0,     /* 0  */
    170     1,     /* 1  */
    171     2,     /* 2  */
    172     3,     /* 3  */
    173     4,     /* 4  */
    174     5,     /* 5  */
    175     6,     /* 6  */
    176     7,     /* 7  */
    177     8,     /* 8  */
    178     9,     /* 9  */
    179     10,    /* 10 */
    180     25,    /* 11 */
    181     50,    /* 12 */
    182     75,    /* 13 */
    183     100,   /* 14 */
    184     -1     /* 15 */
    185 };
    186 
    187 STATIC int
    188 _bcm_th3_percent_to_drop_prob(int percent)
    189 {
    190    int i;
    191 
    192    for (i = TH3_WRED_DROP_PROB_MAX_INDEX; i > 0 ; i--) {
    193       if (percent >= _bcm_th3_hw_drop_prob_to_percent[i]) {
    194           break;
    195       }
    196    }
    197    return i;
    198 }
    199 
    200 STATIC int
    201 _bcm_th3_drop_prob_to_percent(int drop_prob) {
    202    return (_bcm_th3_hw_drop_prob_to_percent[drop_prob]);
    203 }
    204 
    205 /* WRED resolution table */
    206 #define _BCM_TH3_NUM_WRED_RESOLUTION_TABLE   4
    207 STATIC uint32 _bcm_th3_wred_resolution_tbl[_BCM_TH3_NUM_WRED_RESOLUTION_TABLE] = {
    208     1,
    209     0,
    210     0,
    211     0,
    212 };
    213 
    214 typedef struct _bcm_th3_cosq_node_s {
    215     bcm_gport_t gport;
    216     int numq;
    217     int level;
    218     int hw_index;
    219     int in_use;
    220     bcm_gport_t parent_gport;
    221     int cos;
    222     int strict_priority; /* port->L0 */
    223     /* int strict_priority_p;*/ /* L0->L1 */
    224     int fc_is_uc_only;
    225 } _bcm_th3_cosq_node_t;
    226 
    227 typedef struct _bcm_th3_cosq_cpu_cosq_config_s {
    228     int q_min_limit;
    229     int q_shared_limit;
    230     uint8 q_limit_dynamic;
    231     uint8 q_limit_enable;
    232     uint8 q_color_limit_enable;
    233     uint8 enable;
    234 } _bcm_th3_cosq_cpu_cosq_config_t;
    235 
    236 typedef struct _bcm_th3_cosq_port_info_s {
    237     _bcm_th3_cosq_node_t ucast[_BCM_TH3_MAX_NUM_UCAST_QUEUE_PER_PORT];
    238     _bcm_th3_cosq_node_t mcast[_BCM_TH3_MAX_NUM_MCAST_QUEUE_PER_PORT];
    239     _bcm_th3_cosq_node_t sched[_BCM_TH3_NUM_SCHEDULER_PER_PORT];
    240 } _bcm_th3_cosq_port_info_t;
    241 
    242 typedef struct _bcm_th3_cosq_cpu_port_info_s {
    243     _bcm_th3_cosq_node_t sched[_BCM_TH3_NUM_SCHEDULER_PER_PORT];
    244     _bcm_th3_cosq_node_t mcast[_BCM_TH3_NUM_CPU_MCAST_QUEUE];
    245 } _bcm_th3_cosq_cpu_port_info_t;
    246 
    247 typedef struct _bcm_th3_mmu_info_s {
    248     int gport_tree_created; /* FALSE: No GPORT tree exists */
    249     _bcm_th3_cosq_port_info_t *_bcm_th3_port_info;
    250     _bcm_th3_cosq_cpu_port_info_t *_bcm_th3_cpu_port_info;
    251     int shared_limit[_TH3_ITMS_PER_DEV];
    252 } _bcm_th3_mmu_info_t;
    253 
    254 
    255 STATIC _bcm_th3_mmu_info_t *_bcm_th3_mmu_info[BCM_MAX_NUM_UNITS]; /* MMU info */
    256 STATIC _bcm_th3_cosq_port_info_t *_bcm_th3_cosq_port_info[BCM_MAX_NUM_UNITS];
    257 STATIC _bcm_th3_cosq_cpu_port_info_t *_bcm_th3_cosq_cpu_port_info[BCM_MAX_NUM_UNITS];
    258 STATIC soc_profile_mem_t *_bcm_th3_cos_map_profile[BCM_MAX_NUM_UNITS];
    259 STATIC soc_profile_mem_t *_bcm_th3_wred_profile[BCM_MAX_NUM_UNITS];
    260 STATIC soc_profile_reg_t *_bcm_th3_prio2cos_profile[BCM_MAX_NUM_UNITS];
    261 STATIC soc_profile_mem_t *_bcm_th3_ifp_cos_map_profile[BCM_MAX_NUM_UNITS];
    262 STATIC _bcm_th3_cosq_cpu_cosq_config_t
    263             *_bcm_th3_cosq_cpu_cosq_config[BCM_MAX_NUM_UNITS][SOC_TH3_NUM_CPU_QUEUES];
    264 
    265 /* Warmboot */
    266 #ifdef BCM_WARM_BOOT_SUPPORT
    267 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    268 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
    269 #define BCM_WB_VERSION_1_2                SOC_SCACHE_VERSION(1,2)
    270 #define BCM_WB_VERSION_1_3                SOC_SCACHE_VERSION(1,3)
    271 #define BCM_WB_VERSION_1_4                SOC_SCACHE_VERSION(1,4)
    272 #define BCM_WB_VERSION_1_5                SOC_SCACHE_VERSION(1,5)
    273 #define BCM_WB_VERSION_1_6                SOC_SCACHE_VERSION(1,6)
    274 #define BCM_WB_VERSION_1_7                SOC_SCACHE_VERSION(1,7)
    275 #define BCM_WB_VERSION_1_8                SOC_SCACHE_VERSION(1,8)
    276 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
    277 
    278 STATIC int
    279 _bcm_th3_cosq_wb_alloc(int unit)
    280 {
    281     _bcm_th3_mmu_info_t *mmu_info = NULL;
    282     soc_scache_handle_t scache_handle;
    283     uint8 *scache_ptr = NULL;
    284     int rv, alloc_size = 0, max_size = 4096 * 11;
    285     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
    286 
    287     mmu_info = _bcm_th3_mmu_info[unit];
    288     if (mmu_info == NULL) {
    289         return BCM_E_INIT;
    290     }
    291 
    292     cpu_port_info = _bcm_th3_cosq_cpu_port_info[unit];
    293     if (cpu_port_info == NULL) {
    294         return BCM_E_INIT;
    295     }
    296 
    297     /*
    298      * Sync _bcm_th3_mmu_info[unit]->shared_limit
    299      */
    300     alloc_size += 1 * sizeof(int);
    301 
    302     /*
    303      * Sync _bcm_th3_cosq_cpu_port_info structure
    304      */
    305 
    306     alloc_size += sizeof(_bcm_th3_cosq_cpu_port_info_t);
    307 
    308     /*
    309      * Sync the ref_count of IFP_COS_MAPm/COS_MAPm
    310      */
    311     alloc_size += ((SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TH3_MMU_NUM_INT_PRI) - 1) *
    312                    sizeof(uint16);
    313 
    314     /*
    315      * Sync _bcm_th3_cosq_cpu_cosq_config_t structure for all CPU queues
    316      */
    317     alloc_size += (SOC_TH3_NUM_CPU_QUEUES *
    318                    sizeof(_bcm_th3_cosq_cpu_cosq_config_t));
    319     /*
    320      * Sync num_cos value
    321      */
    322     alloc_size += sizeof(int);
    323 
    324     /*
    325      * Sync th3_sched_profile_info struture for all scheduler profiles
    326      */
    327     alloc_size += (SOC_TH3_MAX_NUM_SCHED_PROFILE *
    328                    SOC_TH3_NUM_GP_QUEUES *
    329                    5 * sizeof(int));
    330 
    331     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
    332         alloc_size += (SOC_MAX_NUM_PORTS * 8 * sizeof(uint16));
    333         alloc_size += (SOC_MAX_NUM_PORTS * 8 * sizeof(uint32));
    334     }
    335 
    336    /*
    337      * Added TIME_DOMAIN ref count
    338      */
    339     alloc_size += sizeof(_bcm_th3_cosq_time_info_t);
    340 
    341 #ifdef BCM_TOMAHAWK3_SUPPORT
    342     if (soc_feature(unit, soc_feature_ecn_wred)) {
    343         uint32 scache_size = 0;
    344         BCM_IF_ERROR_RETURN(
    345             bcmi_xgs5_ecn_scache_size_get(unit, &scache_size));
    346         alloc_size += scache_size;
    347     }
    348 #endif
    349 
    350     
    351 
    352     /*
    353      * Sync _bcm_th3_cosq_cpu_cosq_config_t structure for all CPU queues
    354      */
    355     alloc_size += (_BCM_TH3_NUM_WRED_RESOLUTION_TABLE *
    356                    sizeof(uint32));
    357 
    358     /* Reserving some space scache for future usecase (max_size) */
    359     if (alloc_size < max_size) {
    360         alloc_size = max_size;
    361     } else {
    362         /* Required size more than max size allocated for Cosq */
    363         return BCM_E_INIT;
    364     }
    365 
    366     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    367 
    368     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
    369                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
    370 
    371     if (rv == BCM_E_NOT_FOUND) {
    372         rv = BCM_E_NONE;
    373     }
    374 
    375     return rv;
    376 }
    377 #endif /* BCM_WARM_BOOT_SUPPORT */
    378 
    379 
    380 /* Function to Set Default Scheduler Configuration for all the ports */
    381 STATIC int
    382 _bcm_th3_cosq_sched_default_config(int unit)
    383 {
    384     _bcm_th3_cosq_port_info_t *port_info = NULL;
    385     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
    386     bcm_port_t port;
    387     int default_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN, default_weight = 1;
    388     int i;
    389 
    390     port = 0;
    391     cpu_port_info = &_bcm_th3_cosq_cpu_port_info[unit][port];
    392     for (i = 0; i < _BCM_TH3_NUM_SCHEDULER_PER_PORT; i++) {
    393         BCM_IF_ERROR_RETURN
    394             (bcm_th3_cosq_gport_sched_set(unit, cpu_port_info->sched[i].gport,
    395                 -1, default_mode, default_weight));
    396     }
    397     for (i = 0; i < _BCM_TH3_NUM_CPU_MCAST_QUEUE; i++) {
    398         BCM_IF_ERROR_RETURN
    399             (bcm_th3_cosq_gport_sched_set(unit, cpu_port_info->mcast[i].gport,
    400                 -1, default_mode, default_weight));
    401     }
    402 
    403     PBMP_ALL_ITER(unit, port) {
    404         if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) {
    405             continue;
    406         } else {
    407             port_info = &_bcm_th3_cosq_port_info[unit][port];
    408         }
    409         for (i = 0; i < _BCM_TH3_NUM_SCHEDULER_PER_PORT; i++) {
    410             if (!port_info->sched[i].in_use || (port_info->sched[i].numq == 0)) {
    411                 continue;
    412             }
    413             BCM_IF_ERROR_RETURN
    414                 (bcm_th3_cosq_gport_sched_set(unit, port_info->sched[i].gport,
    415                     -1, default_mode, default_weight));
    416         }
    417         for (i = 0; i < _bcm_th3_get_num_ucq(unit); i++) {
    418             if (!port_info->ucast[i].in_use)
    419                 continue;
    420             BCM_IF_ERROR_RETURN
    421                 (bcm_th3_cosq_gport_sched_set(unit, port_info->ucast[i].gport,
    422                     -1, default_mode, default_weight));
    423         }
    424         for (i = 0; i < _bcm_th3_get_num_mcq(unit); i++) {
    425             if (!port_info->mcast[i].in_use)
    426                 continue;
    427             BCM_IF_ERROR_RETURN
    428                 (bcm_th3_cosq_gport_sched_set(unit, port_info->mcast[i].gport,
    429                     -1, default_mode, default_weight));
    430         }
    431     }
    432     return BCM_E_NONE;
    433 }
    434 
    435 STATIC int
    436 _bcm_th3_cosq_gport_default_config(int unit)
    437 {
    438     BCM_IF_ERROR_RETURN
    439         (_bcm_th3_cosq_sched_default_config(unit));
    440 
    441     return BCM_E_NONE;
    442 }
    443 
    444 /*
    445  * Function:
    446  *     _bcm_th3_cosq_node_get
    447  * Purpose:
    448  *     Get internal information of queue group or scheduler type GPORT
    449  * Parameters:
    450  *     unit       - (IN) unit number
    451  *     gport      - (IN) queue group/scheduler GPORT identifier
    452  *     modid      - (OUT) module identifier
    453  *     port       - (OUT) port number
    454  *     id         - (OUT) queue group or scheduler identifier
    455  *     node       - (OUT) node structure for the specified GPORT
    456  * Returns:
    457  *     BCM_E_XXX
    458  */
    459 STATIC int
    460 _bcm_th3_cosq_node_get(int unit, bcm_gport_t gport, bcm_module_t *modid,
    461                       bcm_port_t *port, int *id, _bcm_th3_cosq_node_t **node)
    462 {
    463     _bcm_th3_cosq_port_info_t *port_info = NULL;
    464     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
    465     _bcm_th3_cosq_node_t *node_base = NULL;
    466     bcm_module_t modid_out;
    467     bcm_port_t port_out;
    468     uint32 encap_id;
    469     int index;
    470 
    471     if (_bcm_th3_cosq_port_info[unit] == NULL) {
    472         return BCM_E_INIT;
    473     }
    474     if (_bcm_th3_cosq_cpu_port_info[unit] == NULL) {
    475         return BCM_E_INIT;
    476     }
    477 
    478     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    479         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    480         port_out = BCM_GPORT_UCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
    481     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    482         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    483         port_out = BCM_GPORT_MCAST_QUEUE_GROUP_SYSPORTID_GET(gport);
    484     } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
    485         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid_out));
    486         port_out = BCM_GPORT_SCHEDULER_GET(gport) & 0xff;
    487     } else {
    488         return BCM_E_PORT;
    489     }
    490 
    491     if (!SOC_PORT_VALID(unit, port_out)) {
    492         return BCM_E_PORT;
    493     }
    494     if (IS_CPU_PORT(unit, port_out)) {
    495         cpu_port_info = &_bcm_th3_cosq_cpu_port_info[unit][port_out];
    496     } else {
    497         port_info = &_bcm_th3_cosq_port_info[unit][port_out];
    498     }
    499 
    500     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
    501         encap_id = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(gport);
    502         index = encap_id;
    503         if (index >= _bcm_th3_get_num_ucq(unit)) {
    504             return BCM_E_PORT;
    505         }
    506         node_base = port_info->ucast;
    507     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    508         encap_id = BCM_GPORT_MCAST_QUEUE_GROUP_QID_GET(gport);
    509         index = encap_id;
    510         if (!IS_CPU_PORT(unit, port_out) &&
    511             (index >= _bcm_th3_get_num_mcq(unit))) {
    512             return BCM_E_PORT;
    513         }
    514         if (IS_CPU_PORT(unit, port_out) && (index >= _BCM_TH3_NUM_CPU_MCAST_QUEUE)) {
    515             return BCM_E_PORT;
    516         }
    517         if (IS_CPU_PORT(unit, port_out)) {
    518             node_base = cpu_port_info->mcast;
    519         } else {
    520             node_base = port_info->mcast;
    521         }
    522     } else { /* scheduler */
    523         encap_id = (BCM_GPORT_SCHEDULER_GET(gport) >> 16) & 0x3ff;
    524         index = encap_id;
    525         if (index >= _BCM_TH3_NUM_SCHEDULER_PER_PORT) {
    526             return BCM_E_PORT;
    527         }
    528         if (IS_CPU_PORT(unit, port_out)) {
    529             node_base = cpu_port_info->sched;
    530         } else {
    531             node_base = port_info->sched;
    532         }
    533     }
    534 
    535     if ((node_base == NULL) ||
    536         (node_base[index].numq == 0) ||
    537         (node_base[index].in_use == 0)) {
    538         return BCM_E_NOT_FOUND;
    539     }
    540 
    541     if (modid != NULL) {
    542         *modid = modid_out;
    543     }
    544     if (port != NULL) {
    545         *port = port_out;
    546     }
    547     if (id != NULL) {
    548         *id = encap_id;
    549     }
    550     if (node != NULL) {
    551         *node = &node_base[index];
    552     }
    553 
    554     return BCM_E_NONE;
    555 }
    556 
    557 /*
    558  * Function:
    559  *     _bcm_th3_rqe_q_init
    560  * Purpose:
    561  *     Initialize RQE registers
    562  * Parameters:
    563  *     unit - unit number
    564  * Returns:
    565  *     BCM_E_XXX
    566  */
    567 STATIC int
    568 _bcm_th3_rqe_q_init(int unit)
    569 {
    570     uint32 rval;
    571     uint16 dev_id;
    572     uint8 rev_id;
    573 
    574     soc_cm_get_id(unit, &dev_id, &rev_id);
    575 
    576     rval = 0;
    577     SOC_IF_ERROR_RETURN(READ_CPU_LO_RQE_Q_NUMr(unit, &rval));
    578     if (rev_id == BCM56980_A0_REV_ID) {
    579         soc_reg_field_set(unit, CPU_LO_RQE_Q_NUMr, &rval, RQE_Q_NUMf, _TH3_A0_CPU_LO_RQE_Q_NUM);
    580     } else {
    581         soc_reg_field_set(unit, CPU_LO_RQE_Q_NUMr, &rval, RQE_Q_NUMf, _TH3_CPU_LO_RQE_Q_NUM);
    582     }
    583     SOC_IF_ERROR_RETURN(WRITE_CPU_LO_RQE_Q_NUMr(unit, rval));
    584 
    585     rval = 0;
    586     SOC_IF_ERROR_RETURN(READ_CPU_HI_RQE_Q_NUMr(unit, &rval));
    587     if (rev_id == BCM56980_A0_REV_ID) {
    588         soc_reg_field_set(unit, CPU_HI_RQE_Q_NUMr, &rval, RQE_Q_NUMf, _TH3_A0_CPU_HI_RQE_Q_NUM);
    589     } else {
    590         soc_reg_field_set(unit, CPU_HI_RQE_Q_NUMr, &rval, RQE_Q_NUMf, _TH3_CPU_HI_RQE_Q_NUM);
    591     }
    592     SOC_IF_ERROR_RETURN(WRITE_CPU_HI_RQE_Q_NUMr(unit, rval));
    593 
    594     return BCM_E_NONE;
    595 }
    596 
    597 /*
    598  * Function:
    599  *     _bcm_th3_ecn_init
    600  * Purpose:
    601  *     Initialize (clear) all ECN memories/registers
    602  * Parameters:
    603  *     unit - unit number
    604  * Returns:
    605  *     BCM_E_XXX
    606  */
    607 STATIC int
    608 _bcm_th3_ecn_init(int unit)
    609 {
    610     egr_ip_to_int_cn_mapping_entry_t entry_egr_ip_int_cn;
    611     int count, i;
    612     uint32  fld_val;
    613 
    614     BCM_IF_ERROR_RETURN(_bcm_esw_ecn_init(unit));
    615 
    616     /* Perform additional Tomahawk3 specific ECN initialization */
    617     /* EGR_IP_TO_INT_CN_MAPPING is identical to IP_TO_INT_CN_MAPPING table
    618      */
    619     if (!SOC_WARM_BOOT(unit)) {
    620         count = soc_mem_index_count(unit, EGR_IP_TO_INT_CN_MAPPINGm);
    621         for (i = 0; i < count; i++) {
    622             sal_memset(&entry_egr_ip_int_cn, 0, sizeof(entry_egr_ip_int_cn));
    623             switch (i) {
    624                 case 0:
    625                     fld_val = _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP;
    626                     break;
    627                 case 1:
    628                     fld_val = _BCM_ECN_INT_CN_RESPONSIVE_DROP;
    629                     break;
    630                 case 6:
    631                 case 7:
    632                     fld_val = _BCM_ECN_INT_CN_CONGESTION_MARK_ECN;
    633                     break;
    634                 default:
    635                     fld_val = _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN;
    636                     break;
    637             }
    638             soc_mem_field32_set(unit, EGR_IP_TO_INT_CN_MAPPINGm,
    639                 &entry_egr_ip_int_cn, INT_CNf, fld_val);
    640             SOC_IF_ERROR_RETURN
    641                 (soc_mem_write(unit, EGR_IP_TO_INT_CN_MAPPINGm, MEM_BLOCK_ALL,
    642                                i, (void *)&entry_egr_ip_int_cn));
    643         }
    644     }
    645     return BCM_E_NONE;
    646 }
    647 
    648 /*
    649  * Function:
    650  *     _bcm_th3_cosq_cleanup
    651  * Purpose:
    652  *     Clean resource in case of error during Cosq Init
    653  * Parameters:
    654  *     unit - unit number
    655  * Returns:
    656  *     No return value
    657  */
    658 STATIC void
    659 _bcm_th3_cosq_cleanup(int unit)
    660 {
    661     if (_bcm_th3_cosq_port_info[unit] != NULL) {
    662         sal_free(_bcm_th3_cosq_port_info[unit]);
    663         _bcm_th3_cosq_port_info[unit] = NULL;
    664     }
    665 
    666     if (_bcm_th3_cosq_cpu_port_info[unit] != NULL) {
    667         sal_free(_bcm_th3_cosq_cpu_port_info[unit]);
    668         _bcm_th3_cosq_cpu_port_info[unit] = NULL;
    669     }
    670 
    671     if (_bcm_th3_mmu_info[unit] != NULL) {
    672         sal_free(_bcm_th3_mmu_info[unit]);
    673         _bcm_th3_mmu_info[unit] = NULL;
    674     }
    675 
    676     if (_bcm_th3_cos_map_profile[unit] != NULL) {
    677         soc_profile_mem_destroy(unit, _bcm_th3_cos_map_profile[unit]);
    678         sal_free(_bcm_th3_cos_map_profile[unit]);
    679         _bcm_th3_cos_map_profile[unit] = NULL;
    680     }
    681 
    682     if (_bcm_th3_ifp_cos_map_profile[unit] != NULL) {
    683         soc_profile_mem_destroy(unit, _bcm_th3_ifp_cos_map_profile[unit]);
    684         sal_free(_bcm_th3_ifp_cos_map_profile[unit]);
    685         _bcm_th3_ifp_cos_map_profile[unit] = NULL;
    686     }
    687 
    688     if (_bcm_th3_wred_profile[unit] != NULL) {
    689         soc_profile_mem_destroy(unit, _bcm_th3_wred_profile[unit]);
    690         sal_free(_bcm_th3_wred_profile[unit]);
    691         _bcm_th3_wred_profile[unit] = NULL;
    692     }
    693 
    694     if (_bcm_th3_prio2cos_profile[unit] != NULL) {
    695         soc_profile_reg_destroy(unit, _bcm_th3_prio2cos_profile[unit]);
    696         sal_free(_bcm_th3_prio2cos_profile[unit]);
    697         _bcm_th3_prio2cos_profile[unit] = NULL;
    698     }
    699 
    700 #if defined(INCLUDE_PSTATS)
    701     if (_BCM_PSTATS_UNIT_DRIVER(unit) != NULL) {
    702         _bcm_pstats_deinit(unit);
    703     }
    704 #endif /* INCLUDE_PSTATS */
    705 
    706     (void)_bcm_bst_detach(unit);
    707 
    708 #if defined(BCM_TOMAHAWK3_SUPPORT) && defined(INCLUDE_L3)
    709     bcmi_ecn_map_clean_up(unit);
    710 #endif
    711     (void)_bcm_th3_pfc_deadlock_deinit(unit);
    712 
    713     return;
    714 }
    715 
    716 /*
    717  * Function:
    718  *     bcm_th3_cosq_detach
    719  * Purpose:
    720  *     Discard all COS schedule/mapping state.
    721  * Parameters:
    722  *     unit - unit number
    723  * Returns:
    724  *     BCM_E_XXX
    725  */
    726 int
    727 bcm_th3_cosq_detach(int unit, int software_state_only)
    728 {
    729     _bcm_th3_cosq_cleanup(unit);
    730 
    731     return BCM_E_NONE;
    732 }
    733 
    734 /*
    735  * Function:
    736  *     _bcm_th3_cosq_sched_get
    737  * Purpose:
    738  *     Get scheduling mode setting
    739  * Parameters:
    740  *     unit                - (IN) unit number
    741  *     port                - (IN) port number or GPORT identifier
    742  *     cosq                - (IN) COS queue number
    743  *     mode                - (OUT) scheduling mode (BCM_COSQ_XXX)
    744  *     weight              - (OUT) weight
    745  * Returns:
    746  *     BCM_E_XXX
    747  */
    748 STATIC int
    749 _bcm_th3_cosq_sched_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
    750                        int *mode, int *weight)
    751 {
    752     soc_th3_sched_mode_e sched_mode;
    753     bcm_port_t local_port;
    754     int lvl = SOC_TH3_NODE_LVL_L0, mc = 0;
    755 
    756     if (cosq < 0) {
    757         if (cosq == -1) {
    758             /* caller needs to resolve the wild card value (-1) */
    759             return BCM_E_INTERNAL;
    760         } else { /* reject all other negative value */
    761             return BCM_E_PARAM;
    762         }
    763     }
    764 
    765 
    766     BCM_IF_ERROR_RETURN
    767         (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
    768     if (BCM_GPORT_IS_SCHEDULER(gport)) {
    769         lvl = SOC_TH3_NODE_LVL_L0;
    770     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
    771                BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    772         lvl = SOC_TH3_NODE_LVL_L1;
    773         mc = BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1 : 0;
    774     } else if (IS_CPU_PORT(unit, local_port)) {
    775         lvl = SOC_TH3_NODE_LVL_L1;
    776         mc = 1;
    777     }
    778     BCM_IF_ERROR_RETURN(
    779             soc_th3_cosq_sched_mode_get(unit, local_port, lvl, cosq,
    780                             &sched_mode, weight, mc));
    781     switch(sched_mode) {
    782         case SOC_TH3_SCHED_MODE_STRICT:
    783             *mode = BCM_COSQ_STRICT;
    784         break;
    785         case SOC_TH3_SCHED_MODE_WRR:
    786             *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
    787         break;
    788         case SOC_TH3_SCHED_MODE_WERR:
    789             *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
    790         break;
    791         default:
    792             return BCM_E_INTERNAL;
    793         break;
    794     }
    795     return BCM_E_NONE;
    796 }
    797 
    798 /*
    799  * Function:
    800  *     _bcm_th3_cosq_sched_set
    801  * Purpose:
    802  *     Set scheduling mode
    803  * Parameters:
    804  *     unit                - (IN) unit number
    805  *     port                - (IN) port number or GPORT identifier
    806  *     cosq                - (IN) COS queue number
    807  *     mode                - (IN) scheduling mode (BCM_COSQ_XXX)
    808  *     weight              - (IN) weight
    809  * Returns:
    810  *     BCM_E_XXX
    811  */
    812 STATIC int
    813 _bcm_th3_cosq_sched_set(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
    814                         int mode, int weight)
    815 {
    816     soc_th3_sched_mode_e sched_mode;
    817     bcm_port_t local_port;
    818     int lwts = 1, child_index=0, lvl = SOC_TH3_NODE_LVL_L0, mc = 0;
    819 
    820     if (cosq < 0) {
    821         if (cosq == -1) {
    822             /* caller needs to resolve the wild card value (-1) */
    823             return BCM_E_INTERNAL;
    824         } else { /* reject all other negative value */
    825             return BCM_E_PARAM;
    826         }
    827     }
    828     if ((weight < _BCM_TH3_QSCHED_MIN_WEIGHT) || (weight > _BCM_TH3_QSCHED_MAX_WEIGHT)) {
    829         return BCM_E_PARAM;
    830     }
    831 
    832     switch(mode) {
    833         case BCM_COSQ_STRICT:
    834             sched_mode = SOC_TH3_SCHED_MODE_STRICT;
    835             lwts = 0;
    836             break;
    837         case BCM_COSQ_ROUND_ROBIN:
    838             sched_mode = SOC_TH3_SCHED_MODE_WRR;
    839             lwts = 1;
    840             break;
    841         case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
    842             sched_mode = SOC_TH3_SCHED_MODE_WRR;
    843             lwts = weight;
    844             break;
    845         case BCM_COSQ_DEFICIT_ROUND_ROBIN:
    846             sched_mode = SOC_TH3_SCHED_MODE_WERR;
    847             lwts = weight;
    848             break;
    849         default:
    850             return BCM_E_PARAM;
    851     }
    852 
    853     /* Weight = 0 corresponds to Strict Mode */
    854     if (lwts == 0) {
    855         sched_mode = SOC_TH3_SCHED_MODE_STRICT;
    856     }
    857 
    858     child_index = cosq;
    859     BCM_IF_ERROR_RETURN
    860         (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
    861 
    862     if (BCM_GPORT_IS_SCHEDULER(gport)) {
    863         /* We need to set lvl = L0(schedular node) so that sched mode is set at it's parent */
    864         lvl = SOC_TH3_NODE_LVL_L0;
    865     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
    866                BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
    867         /* We need to set lvl = L1(UC/MC nodes) so that sched mode is set at it's parent */
    868         lvl = SOC_TH3_NODE_LVL_L1;
    869         mc = BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ? 1 : 0;
    870     } else if (IS_CPU_PORT(unit, local_port)) {
    871         lvl = SOC_TH3_NODE_LVL_L1;
    872         mc = 1;
    873     }
    874     BCM_IF_ERROR_RETURN(soc_th3_cosq_sched_mode_set(unit, local_port,
    875                                                    lvl,
    876                                                    child_index,
    877                                                    sched_mode, lwts, mc));
    878 
    879     return BCM_E_NONE;
    880 }
    881 
    882 /*
    883  * Function:
    884  *     bcm_tomahaw3_cosq_port_sched_config_get
    885  * Purpose:
    886  *     Retrieve class-of-service policy and corresponding weights and mode
    887  * Parameters:
    888  *     unit                 - (IN) unit number
    889  *     pbm                  - (IN) port bitmap
    890  *     weight_arr_size      - (IN) Size of weights array
    891  *     mode                 - (OUT) Scheduling mode (BCM_COSQ_XXX)
    892  *     weights              - (OUT) Weights for each COS queue
    893  *     weight_arr_count     - (OUT) Actual size of weights array
    894  * Returns:
    895  *     BCM_E_XXX
    896  */
    897 int
    898 bcm_tomahawk3_cosq_port_sched_config_get(int unit, bcm_pbmp_t pbm, int weight_arr_size,
    899                            int *weights, int *weight_arr_count, int *mode)
    900 {
    901     bcm_port_t port;
    902     int i, num_weights;
    903 
    904     BCM_PBMP_ITER(pbm, port) {
    905         if (IS_CPU_PORT(unit, port) && SOC_PBMP_NEQ(pbm, PBMP_CMIC(unit))) {
    906             continue;
    907         }
    908         if (weights == NULL) {
    909             return BCM_E_PARAM;
    910         }
    911         if (weight_arr_count == NULL) {
    912             return BCM_E_PARAM;
    913         }
    914         if (weight_arr_size > _TH3_NUM_COS(unit)) {
    915             num_weights = _TH3_NUM_COS(unit);
    916         } else {
    917             num_weights = weight_arr_size;
    918         }
    919         *weight_arr_count = num_weights;
    920 
    921         for (i = 0; i < num_weights; i++) {
    922             BCM_IF_ERROR_RETURN(
    923                 _bcm_th3_cosq_sched_get(unit, port, i, mode, &weights[i]));
    924         }
    925     }
    926 
    927     return BCM_E_NONE;
    928 }
    929 
    930 /*
    931  * Function:
    932  *     bcm_tomahawk3_cosq_port_sched_config_set
    933  * Purpose:
    934  *     Set up class-of-service policy and corresponding weights and mode
    935  * Parameters:
    936  *     unit               - (IN) unit number
    937  *     pbm                - (IN) port bitmap
    938  *     mode               - (IN) Scheduling mode (BCM_COSQ_xxx)
    939  *     weight_arr_size    - (IN) Size of the weights array
    940  *     weights            - (IN) Weights for each COS queue
    941  * Returns:
    942  *     BCM_E_XXX
    943  */
    944 int
    945 bcm_tomahawk3_cosq_port_sched_config_set(int unit, bcm_pbmp_t pbm,
    946                            int mode, int weight_arr_size, int *weights)
    947 {
    948     bcm_port_t port;
    949     int num_weights, i;
    950 
    951     BCM_PBMP_ITER(pbm, port) {
    952         if (weight_arr_size > _TH3_NUM_COS(unit)) {
    953             return BCM_E_PARAM;
    954         } else {
    955             num_weights = weight_arr_size;
    956         }
    957 
    958         if (weights == NULL) {
    959             return BCM_E_PARAM;
    960         }
    961         for (i = 0; i < num_weights; i++) {
    962             BCM_IF_ERROR_RETURN
    963                 (_bcm_th3_cosq_sched_set(unit, port, i, mode, weights[i]));
    964         }
    965     }
    966 
    967     return BCM_E_NONE;
    968 }
    969 
    970 /*
    971  * Function:
    972  *      bcm_tomahawk3_cosq_sched_config_set
    973  * Purpose:
    974  *      Set up class-of-service policy and corresponding weights and mode
    975  * Parameters:
    976  *      unit - StrataSwitch unit number.
    977  *      mode - Scheduling mode, one of BCM_COSQ_xxx
    978  *      weight_arr_size - Size of the weights array
    979  *    weights - Weights for each COS queue
    980  *        Unused if mode is BCM_COSQ_STRICT.
    981  *        Indicates number of packets sent before going on to
    982  *        the next COS queue.
    983  * Returns:
    984  *      BCM_E_XXX
    985  */
    986 
    987 int
    988 bcm_tomahawk3_cosq_sched_config_set(int unit, int mode, int weight_arr_size, int *weights)
    989 {
    990     bcm_pbmp_t pbmp;
    991 
    992     if (soc_feature(unit, soc_feature_ets)) {
    993         BCM_PBMP_ASSIGN(pbmp, PBMP_CMIC(unit));
    994     } else {
    995         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
    996     }
    997 
    998     return (bcm_tomahawk3_cosq_port_sched_config_set(unit, pbmp, mode, weight_arr_size,
    999                                                         weights));
   1000 }
   1001 
   1002 /*
   1003  * Function:
   1004  *      bcm_tomahawk3_cosq_sched_config_get
   1005  * Purpose:
   1006  *      Retrieve class-of-service policy and corresponding weights and mode
   1007  * Parameters:
   1008  *      unit - StrataSwitch unit number.
   1009  *      mode_ptr - (output) Scheduling mode, one of BCM_COSQ_xxx
   1010  *    weights - (output) Weights for each COS queue
   1011  *        Unused if mode is BCM_COSQ_STRICT.
   1012  * Returns:
   1013  *      BCM_E_XXX
   1014  */
   1015 
   1016 int
   1017 bcm_tomahawk3_cosq_sched_config_get(int unit, int weight_arr_size,
   1018                                     int *weights, int *weight_arr_count,
   1019                                     int *mode)
   1020 {
   1021     bcm_pbmp_t pbmp;
   1022 
   1023     if (soc_feature(unit, soc_feature_ets)) {
   1024         BCM_PBMP_ASSIGN(pbmp, PBMP_CMIC(unit));
   1025     } else {
   1026         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   1027     }
   1028 
   1029     return (bcm_tomahawk3_cosq_port_sched_config_get(unit, pbmp, weight_arr_size,
   1030                                                  weights, weight_arr_count, mode));
   1031 }
   1032 
   1033 
   1034 /*
   1035  * Function:
   1036  *     bcm_th3_cosq_port_sched_get
   1037  * Purpose:
   1038  *     Retrieve class-of-service policy and corresponding weights and delay
   1039  * Parameters:
   1040  *     unit     - (IN) unit number
   1041  *     pbm      - (IN) port bitmap
   1042  *     mode     - (OUT) Scheduling mode (BCM_COSQ_XXX)
   1043  *     weights  - (OUT) Weights for each COS queue
   1044  *     delay    - This parameter is not used
   1045  * Returns:
   1046  *     BCM_E_XXX
   1047  */
   1048 int
   1049 bcm_th3_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
   1050                            int *mode, int *weights, int *delay)
   1051 {
   1052     return BCM_E_UNAVAIL;
   1053 }
   1054 
   1055 /*
   1056  * Function:
   1057  *     bcm_th3_cosq_port_sched_set
   1058  * Purpose:
   1059  *     Set up class-of-service policy and corresponding weights and delay
   1060  * Parameters:
   1061  *     unit    - (IN) unit number
   1062  *     pbm     - (IN) port bitmap
   1063  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   1064  *     weights - (IN) Weights for each COS queue
   1065  *     delay   - This parameter is not used
   1066  * Returns:
   1067  *     BCM_E_XXX
   1068  */
   1069 int
   1070 bcm_th3_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
   1071                            int mode, const int *weights, int delay)
   1072 {
   1073     return BCM_E_UNAVAIL;
   1074 }
   1075 
   1076 
   1077 
   1078 int
   1079 _bcm_th3_cosq_rx_queue_channel_set(int unit,
   1080                                   bcm_cos_queue_t parent_cos,
   1081                                   bcm_cos_queue_t queue_id,
   1082                                   int enable)
   1083 {
   1084 #if defined(BCM_CMICX_SUPPORT)
   1085 
   1086     if(soc_feature(unit, soc_feature_cmicx)) {
   1087         int pci_cmc = SOC_PCI_CMC(unit);
   1088         int chan_id = -1;
   1089         int start_chan_id = 0;
   1090         uint32 chan_off;
   1091         uint32 reg_addr, reg_val;
   1092         uint32 ix;
   1093         uint32 max_rx_channels;
   1094 
   1095         if ((parent_cos >= 0) && (parent_cos <= 6)) {
   1096             chan_id = parent_cos + 1;
   1097         } else {
   1098             return BCM_E_PARAM;
   1099         }
   1100 
   1101         if (!SHR_BITGET(CPU_ARM_QUEUE_BITMAP(unit, pci_cmc), queue_id)) {
   1102             return BCM_E_PARAM;
   1103         }
   1104 
   1105         soc_dma_max_rx_channels_get(unit, &max_rx_channels);
   1106 
   1107         for (ix = start_chan_id; ix < (start_chan_id + max_rx_channels); ix++) {
   1108             chan_off = ix % max_rx_channels;
   1109             soc_dma_cos_ctrl_reg_addr_get(unit, pci_cmc, chan_off,
   1110                                           queue_id, &reg_addr);
   1111             reg_val = soc_pci_read(unit, reg_addr);
   1112 
   1113             if (enable == 1) {
   1114                 if (ix == (uint32)chan_id) {
   1115                     reg_val |= ((1U) << (queue_id % 32));
   1116                 } else {
   1117                     /* Clear all other channels */
   1118                     reg_val &= ~((1U) << (queue_id % 32));
   1119                 }
   1120             } else {
   1121                 if (ix == (uint32)chan_id) {
   1122                     reg_val &= ~((1U) << (queue_id % 32));
   1123                 }
   1124             }
   1125             /* Incoporate the reserved queues (if any on this device)
   1126              * into the CMIC programming,  */
   1127             reg_val |=
   1128                 CPU_ARM_RSVD_QUEUE_BITMAP(unit, pci_cmc)[queue_id / 32];
   1129             soc_pci_write(unit, reg_addr, reg_val);
   1130         }
   1131     }
   1132 #endif
   1133     return BCM_E_NONE;
   1134 }
   1135 
   1136 /* Function to attach any of the 48 L1 MC Queue to one of the 10 L0 nodes
   1137  */
   1138 STATIC int
   1139 bcm_th3_cosq_cpu_gport_attach(int unit, bcm_gport_t input_gport,
   1140                              bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   1141 {
   1142     bcm_port_t parent_port, input_port;
   1143     _bcm_th3_cosq_node_t *input_node = NULL, *parent_node = NULL;
   1144     int phy_port, mmu_port;
   1145     int input_cos = 0, parent_cos = 0;
   1146     int cpu_sched_base = 0, cpu_mc_base = 0;
   1147     soc_info_t *si = &SOC_INFO(unit);
   1148 
   1149     /* Post Default tree created, expected Input Gport is of MC Gport
   1150      * and expected Parent Gport is new L0 Parent
   1151      */
   1152     if (_BCM_TH3_MMU_INFO(unit)->gport_tree_created == FALSE) {
   1153         if (((BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) &&
   1154              (!BCM_GPORT_IS_SCHEDULER(parent_gport))) ||
   1155             (!(BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport)) &&
   1156              (!BCM_GPORT_IS_SCHEDULER(input_gport)))) {
   1157             return BCM_E_PARAM;
   1158         }
   1159     } else if ((!BCM_GPORT_IS_SCHEDULER(parent_gport)) ||
   1160         (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   1161         return BCM_E_PARAM;
   1162     }
   1163     BCM_IF_ERROR_RETURN
   1164         (_bcm_th3_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   1165                                &input_node));
   1166     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   1167         BCM_IF_ERROR_RETURN
   1168             (_bcm_th3_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL,
   1169                                    &parent_node));
   1170     } else {
   1171         BCM_IF_ERROR_RETURN
   1172             (_bcm_th3_cosq_localport_resolve(unit, parent_gport, &parent_port));
   1173         parent_node = NULL;
   1174     }
   1175 
   1176     if (!IS_CPU_PORT(unit, parent_port)) {
   1177         return BCM_E_PARAM;
   1178     }
   1179 
   1180     /* Return BCM_E_EXISTS when queue to be attached is
   1181        already attached to the given gport */
   1182     if ((_BCM_TH3_MMU_INFO(unit)->gport_tree_created == TRUE) &&
   1183         (input_node->parent_gport == parent_gport)) {
   1184         return BCM_E_EXISTS;
   1185     }
   1186 
   1187     phy_port = si->port_l2p_mapping[input_port];
   1188     mmu_port = si->port_p2m_mapping[phy_port];
   1189     cpu_sched_base = mmu_port * _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   1190     input_cos = cosq % _BCM_TH3_NUM_CPU_MCAST_QUEUE;
   1191     input_node->parent_gport = parent_port;
   1192 
   1193     if (BCM_GPORT_IS_SCHEDULER(parent_gport)) {
   1194         cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   1195         parent_cos = (parent_node->hw_index - cpu_sched_base) %
   1196                      _BCM_TH3_NUM_CPU_MCAST_QUEUE;
   1197         SOC_IF_ERROR_RETURN
   1198             (soc_th3_cosq_cpu_parent_set(unit, input_cos, SOC_TH3_NODE_LVL_L1,
   1199                                         parent_cos));
   1200        /*
   1201         * L0.0 is associated with CMC0 CH1(Rx)
   1202         * L0.1 is associated with CMC0 CH2(Rx)
   1203         * L0.2 is associated with CMC0 CH3(Rx)
   1204         * L0.3 is associated with CMC0 CH4(Rx)
   1205         * L0.4 is associated with CMC0 CH5(Rx)
   1206         * L0.5 is associated with CMC0 CH6(Rx)
   1207         * L0.6 is associated with CMC0 CH7(Rx)
   1208         */
   1209         if ((parent_cos >= 0) && (parent_cos < 7)) {
   1210             BCM_IF_ERROR_RETURN
   1211                 (_bcm_th3_cosq_rx_queue_channel_set(unit, parent_cos, input_cos, 1));
   1212         }
   1213         input_node->parent_gport = parent_node->gport;
   1214         if (_BCM_TH3_MMU_INFO(unit)->gport_tree_created == FALSE) {
   1215             input_node->hw_index = cpu_mc_base + input_cos;
   1216         }
   1217     } else {
   1218         input_node->hw_index = cpu_sched_base + input_cos;
   1219     }
   1220 
   1221     return BCM_E_NONE;
   1222 }
   1223 
   1224 
   1225 int _bcm_th3_queue_is_unicast(int unit, int queue_num)
   1226 {
   1227     int mc_q_mode, num_ucq;
   1228 
   1229     mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, _BCM_TH3_MCQ_MODE_DEFAULT);
   1230     num_ucq = (mc_q_mode == 0) ? 12 : (mc_q_mode == 1) ? 10 :
   1231               (mc_q_mode == 2) ? 8  : (mc_q_mode == 3) ? 6 : 8;
   1232     if (queue_num < num_ucq) {
   1233         return 1;
   1234     } else {
   1235         return 0;
   1236     }
   1237 }
   1238 
   1239 int _bcm_th3_get_num_ucq(int unit)
   1240 {
   1241     int mc_q_mode, num_ucq;
   1242 
   1243     mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, _BCM_TH3_MCQ_MODE_DEFAULT);
   1244     num_ucq = (mc_q_mode == 0) ? 12 : (mc_q_mode == 1) ? 10 :
   1245               (mc_q_mode == 2) ? 8  : (mc_q_mode == 3) ? 6 : 8;
   1246 
   1247     return num_ucq;
   1248 }
   1249 
   1250 int _bcm_th3_get_num_mcq(int unit)
   1251 {
   1252     int mc_q_mode, num_mcq;
   1253 
   1254     mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, _BCM_TH3_MCQ_MODE_DEFAULT);
   1255     num_mcq = (mc_q_mode == 0) ? 0 : (mc_q_mode == 1) ? 2 :
   1256               (mc_q_mode == 2) ? 4 : (mc_q_mode == 3) ? 6 : 4;
   1257 
   1258     return num_mcq;
   1259 }
   1260 
   1261 int
   1262 _bcm_th3_cosq_port_resolve(int unit, bcm_gport_t gport, bcm_module_t *modid,
   1263                           bcm_port_t *port, bcm_trunk_t *trunk_id, int *id,
   1264                           int *qnum)
   1265 {
   1266     _bcm_th3_cosq_node_t *node;
   1267 
   1268     BCM_IF_ERROR_RETURN
   1269         (_bcm_th3_cosq_node_get(unit, gport, modid, port, id, &node));
   1270     *trunk_id = -1;
   1271 
   1272     if (qnum) {
   1273         if (node->hw_index == -1) {
   1274             return BCM_E_PARAM;
   1275         }
   1276         *qnum = node->hw_index;
   1277     }
   1278 
   1279     return BCM_E_NONE;
   1280 }
   1281 
   1282 /*
   1283  * Function:
   1284  *     _bcm_th3_cosq_gport_add_attach
   1285  * Purpose:
   1286  *     Create a cosq gport structure for non CPU Ports
   1287  * Parameters:
   1288  *     unit  - (IN) unit number
   1289  *     port  - (IN) port number
   1290  *     numq  - (IN) number of COS queues
   1291  *     flags - (IN) flags (BCM_COSQ_GPORT_XXX)
   1292  *     gport - (OUT) GPORT identifier
   1293  * Returns:
   1294  *     BCM_E_XXX
   1295  */
   1296 int
   1297 _bcm_th3_cosq_gport_add_attach(int unit, bcm_gport_t port, int numq, uint32 flags)
   1298 {
   1299     _bcm_th3_cosq_port_info_t *port_info = NULL;
   1300     uint32 sched_encap;
   1301     bcm_port_t local_port;
   1302     bcm_gport_t gport;
   1303     bcm_gport_t parent_gport;
   1304     int id, queue_num;
   1305     int modid;
   1306 
   1307     if (_bcm_th3_cosq_port_info[unit] == NULL) {
   1308         return BCM_E_INIT;
   1309     }
   1310 
   1311     BCM_IF_ERROR_RETURN
   1312         (_bcm_th3_cosq_localport_resolve(unit, port, &local_port));
   1313 
   1314     if (local_port < 0 || IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) {
   1315         return BCM_E_PORT;
   1316     }
   1317 
   1318     port_info = &_bcm_th3_cosq_port_info[unit][local_port];
   1319 
   1320     if (flags == BCM_COSQ_GPORT_SCHEDULER) {
   1321         port_info->sched[numq].level = SOC_TH3_NODE_LVL_L0;
   1322         port_info->sched[numq].in_use = th3_cosq_mmu_info[unit]->th3_port_info[local_port].L0[numq].in_use;
   1323         port_info->sched[numq].hw_index = th3_cosq_mmu_info[unit]->th3_port_info[local_port].L0[numq].hw_index;
   1324         port_info->sched[numq].cos = th3_cosq_mmu_info[unit]->th3_port_info[local_port].L0[numq].cos;
   1325         port_info->sched[numq].strict_priority = th3_cosq_mmu_info[unit]->th3_port_info[local_port].L0[numq].sched_policy;
   1326         port_info->sched[numq].fc_is_uc_only = th3_cosq_mmu_info[unit]->th3_port_info[local_port].L0[numq].fc_is_uc_only;
   1327         sched_encap = (numq << 16) | local_port;
   1328         BCM_GPORT_SCHEDULER_SET(gport, sched_encap);
   1329         port_info->sched[numq].gport = gport;
   1330         if (th3_cosq_mmu_info[unit]->th3_port_info[local_port].L0[numq].in_use == 0)
   1331             port_info->sched[numq].numq = 0; /* Number of sub-nodes */
   1332         else if ((th3_cosq_mmu_info[unit]->th3_port_info[local_port].L0[numq].children[0] != NULL) &&
   1333             (th3_cosq_mmu_info[unit]->th3_port_info[local_port].L0[numq].children[1] != NULL))
   1334             port_info->sched[numq].numq = 2; /* Number of sub-nodes */
   1335         else if (th3_cosq_mmu_info[unit]->th3_port_info[local_port].L0[numq].children[0] != NULL)
   1336             port_info->sched[numq].numq = 1; /* Number of sub-nodes */
   1337         else
   1338             port_info->sched[numq].numq = 0; /* Number of sub-nodes */
   1339         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   1340         BCM_GPORT_MODPORT_SET(parent_gport, modid, port);
   1341         port_info->sched[numq].parent_gport = parent_gport;
   1342         LOG_INFO(BSL_LS_BCM_COSQ,
   1343              (BSL_META_U(unit,
   1344              "SCHED add_attach port %d numq %d gport %d sched.numq %d\n"),
   1345              port, numq, port_info->sched[numq].gport, port_info->sched[numq].numq));
   1346     } else {
   1347         id = th3_cosq_mmu_info[unit]->th3_port_info[local_port].mmuq[numq].hw_index;
   1348         if (_bcm_th3_queue_is_unicast(unit, id)) {
   1349             port_info->ucast[id].level = SOC_TH3_NODE_LVL_L2;
   1350             port_info->ucast[id].in_use =
   1351                 th3_cosq_mmu_info[unit]->th3_port_info[local_port].mmuq[numq].in_use;
   1352             if (port_info->ucast[id].in_use) {
   1353                 port_info->ucast[id].hw_index =
   1354                     th3_cosq_mmu_info[unit]->th3_port_info[local_port].mmuq[numq].hw_index;
   1355                 port_info->ucast[id].cos =
   1356                     th3_cosq_mmu_info[unit]->th3_port_info[local_port].mmuq[numq].parent->parent->cos;
   1357                 BCM_GPORT_UCAST_QUEUE_GROUP_SYSQID_SET(gport, local_port, id);
   1358                 port_info->ucast[id].gport = gport;
   1359                 port_info->ucast[id].numq = 1;
   1360                 queue_num =
   1361                     th3_cosq_mmu_info[unit]->th3_port_info[local_port].mmuq[numq].parent->parent->hw_index;
   1362                 sched_encap = (queue_num << 16) | local_port;
   1363                 BCM_GPORT_SCHEDULER_SET(parent_gport, sched_encap);
   1364                 port_info->ucast[id].parent_gport = parent_gport;
   1365                 LOG_INFO(BSL_LS_BCM_COSQ,
   1366                     (BSL_META_U(unit,
   1367                     "UCAST add_attach port %d id %d numq %d gport %d hw_index %d\n"),
   1368                     port, id, numq, port_info->ucast[id].gport, port_info->ucast[id].hw_index));
   1369             } else {
   1370                 port_info->ucast[id].numq = 0;
   1371             }
   1372         } else {
   1373             id = id - _bcm_th3_get_num_ucq(unit);
   1374             port_info->mcast[id].level = SOC_TH3_NODE_LVL_L2;
   1375             port_info->mcast[id].in_use =
   1376                 th3_cosq_mmu_info[unit]->th3_port_info[local_port].mmuq[numq].in_use;
   1377             if (port_info->mcast[id].in_use) {
   1378                 port_info->mcast[id].hw_index =
   1379                     th3_cosq_mmu_info[unit]->th3_port_info[local_port].mmuq[numq].hw_index;
   1380                 port_info->mcast[id].cos =
   1381                     th3_cosq_mmu_info[unit]->th3_port_info[local_port].mmuq[numq].parent->parent->cos;
   1382                 BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(gport, local_port, id);
   1383                 port_info->mcast[id].gport = gport;
   1384                 port_info->mcast[id].numq = 1;
   1385                 queue_num =
   1386                     th3_cosq_mmu_info[unit]->th3_port_info[local_port].mmuq[numq].parent->parent->hw_index;
   1387                 sched_encap = (queue_num << 16) | local_port;
   1388                 BCM_GPORT_SCHEDULER_SET(parent_gport, sched_encap);
   1389                 port_info->mcast[id].parent_gport = parent_gport;
   1390                 LOG_INFO(BSL_LS_BCM_COSQ,
   1391                     (BSL_META_U(unit,
   1392                     "MCAST add_attach port %d id %d numq %d gport %d hw_index %d\n"),
   1393                     port, id, numq, gport, port_info->mcast[id].hw_index));
   1394             } else {
   1395                 port_info->mcast[id].numq = 0;
   1396             }
   1397         }
   1398     }
   1399 
   1400     return BCM_E_NONE;
   1401 }
   1402 
   1403 
   1404 /*
   1405  * Function:
   1406  *     _bcm_th3_cosq_cpu_gport_add_attach
   1407  * Purpose:
   1408  *     Create a cosq gport structure for CPU Ports
   1409  * Parameters:
   1410  *     unit  - (IN) unit number
   1411  *     port  - (IN) port number
   1412  *     numq  - (IN) number of COS queues
   1413  *     flags - (IN) flags (BCM_COSQ_GPORT_XXX)
   1414  *     gport - (OUT) GPORT identifier
   1415  * Returns:
   1416  *     BCM_E_XXX
   1417  */
   1418 int
   1419 _bcm_th3_cosq_cpu_gport_add_attach(int unit, bcm_gport_t port, int numq, uint32 flags)
   1420 {
   1421     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
   1422     uint32 sched_encap;
   1423     bcm_port_t local_port;
   1424     bcm_gport_t gport, parent_gport;
   1425     int queue_num;
   1426     soc_info_t *si = &SOC_INFO(unit);
   1427 
   1428     if (_bcm_th3_cosq_cpu_port_info[unit] == NULL) {
   1429         return BCM_E_INIT;
   1430     }
   1431 
   1432     BCM_IF_ERROR_RETURN
   1433         (_bcm_th3_cosq_localport_resolve(unit, port, &local_port));
   1434 
   1435     if (!IS_CPU_PORT(unit, local_port)) {
   1436         return BCM_E_PORT;
   1437     }
   1438 
   1439     cpu_port_info = &_bcm_th3_cosq_cpu_port_info[unit][local_port];
   1440 
   1441     if (flags == BCM_COSQ_GPORT_SCHEDULER) {
   1442         cpu_port_info->sched[numq].level = SOC_TH3_NODE_LVL_L0;
   1443         cpu_port_info->sched[numq].in_use = th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[numq].in_use;
   1444         cpu_port_info->sched[numq].hw_index = th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[numq].hw_index +
   1445                                                si->port_cosq_base[CMIC_PORT(unit)];
   1446         sched_encap = (numq << 16) | local_port;
   1447         BCM_GPORT_SCHEDULER_SET(gport, sched_encap);
   1448         cpu_port_info->sched[numq].gport = gport;
   1449         cpu_port_info->sched[numq].numq = 4; /* default 4 cos per mmuq*/
   1450         cpu_port_info->sched[numq].parent_gport = port;
   1451         LOG_INFO(BSL_LS_BCM_COSQ,
   1452              (BSL_META_U(unit,
   1453                          "cpu_port_info[%d] sched gport=%x parent_gport=%x\n"),
   1454               numq, cpu_port_info->sched[numq].gport, cpu_port_info->sched[numq].parent_gport));
   1455     } else {
   1456         cpu_port_info->mcast[numq].level = SOC_TH3_NODE_LVL_L1;
   1457         cpu_port_info->mcast[numq].in_use = th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[numq].in_use;
   1458         cpu_port_info->mcast[numq].hw_index = th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[numq].hw_index +
   1459                                                si->port_cosq_base[CMIC_PORT(unit)];
   1460         BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(gport, local_port, numq);
   1461         cpu_port_info->mcast[numq].gport = gport;
   1462         cpu_port_info->mcast[numq].numq = 1;
   1463         queue_num = th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[numq].parent->hw_index;
   1464         sched_encap = (queue_num << 16) | local_port;
   1465         BCM_GPORT_SCHEDULER_SET(parent_gport, sched_encap);
   1466         cpu_port_info->mcast[numq].parent_gport = parent_gport;
   1467         LOG_INFO(BSL_LS_BCM_COSQ,
   1468              (BSL_META_U(unit,
   1469                          "cpu_port_info[%d] mcast gport=%x parent_gport=%x hw_index=%d\n"),
   1470               numq, cpu_port_info->mcast[numq].gport, cpu_port_info->mcast[numq].parent_gport, queue_num));
   1471     }
   1472 
   1473 
   1474     return BCM_E_NONE;
   1475 }
   1476 
   1477 
   1478 /*
   1479  * Function:
   1480  *     bcm_th3_cosq_gport_add
   1481  * Purpose:
   1482  *     Create a cosq gport structure
   1483  * Parameters:
   1484  *     unit  - (IN) unit number
   1485  *     port  - (IN) port number
   1486  *     numq  - (IN) number of COS queues
   1487  *     flags - (IN) flags (BCM_COSQ_GPORT_XXX)
   1488  *     gport - (OUT) GPORT identifier
   1489  * Returns:
   1490  *     BCM_E_XXX
   1491  */
   1492 int
   1493 bcm_th3_cosq_gport_add(int unit, bcm_gport_t port, int numq, uint32 flags,
   1494                       bcm_gport_t *gport)
   1495 {
   1496     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
   1497     _bcm_th3_cosq_node_t *node;
   1498     uint32 sched_encap;
   1499     bcm_port_t local_port;
   1500     int id = 0;
   1501 
   1502     if (gport == NULL) {
   1503         return BCM_E_PARAM;
   1504     }
   1505 
   1506     if (_bcm_th3_cosq_cpu_port_info[unit] == NULL) {
   1507         return BCM_E_INIT;
   1508     }
   1509 
   1510     BCM_IF_ERROR_RETURN
   1511         (_bcm_th3_cosq_localport_resolve(unit, port, &local_port));
   1512 
   1513     if (!IS_CPU_PORT(unit, local_port)) {
   1514         return BCM_E_PORT;
   1515     }
   1516 
   1517     cpu_port_info = &_bcm_th3_cosq_cpu_port_info[unit][local_port];
   1518 
   1519     switch (flags) {
   1520         case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   1521             return BCM_E_PARAM;
   1522         case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   1523             if (numq != 1) {
   1524                 return BCM_E_PARAM;
   1525             }
   1526             if (IS_CPU_PORT(unit, local_port)) {
   1527                 for (id = 0; id < _BCM_TH3_NUM_CPU_MCAST_QUEUE; id++) {
   1528                     if ((cpu_port_info->mcast[id].numq == 0) ||
   1529                         (cpu_port_info->mcast[id].in_use == 0)) {
   1530                         break;
   1531                     }
   1532                 }
   1533                 if (id == _BCM_TH3_NUM_CPU_MCAST_QUEUE) {
   1534                     return BCM_E_RESOURCE;
   1535                 }
   1536             }
   1537             BCM_GPORT_MCAST_QUEUE_GROUP_SYSQID_SET(*gport, local_port, id);
   1538             node = &cpu_port_info->mcast[id];
   1539             node->level = SOC_TH3_NODE_LVL_L1;
   1540             break;
   1541         case BCM_COSQ_GPORT_SCHEDULER:
   1542             if (numq <= 0) {
   1543                 return BCM_E_PARAM;
   1544             }
   1545             for (id = 0; id < _BCM_TH3_NUM_SCHEDULER_PER_PORT; id++) {
   1546                 if (IS_CPU_PORT(unit, local_port)) {
   1547                     if (cpu_port_info->sched[id].numq == 0) {
   1548                         break;
   1549                     }
   1550                 }
   1551             }
   1552             if (id == _BCM_TH3_NUM_SCHEDULER_PER_PORT) {
   1553                 return BCM_E_RESOURCE;
   1554             }
   1555 
   1556             sched_encap = (id << 16) | local_port;
   1557             BCM_GPORT_SCHEDULER_SET(*gport, sched_encap);
   1558             node = &cpu_port_info->sched[id];
   1559             node->level = SOC_TH3_NODE_LVL_L0;
   1560             break;
   1561         default:
   1562             return BCM_E_UNAVAIL;
   1563     }
   1564 
   1565     node->gport = *gport;
   1566     node->numq = numq;
   1567     node->in_use = 1;
   1568 
   1569     return BCM_E_NONE;
   1570 }
   1571 
   1572 int
   1573 _bcm_th3_cosq_gport_hw_delete(int unit, int schedq, int L0)
   1574 {
   1575     soc_reg_t reg = INVALIDr;
   1576     uint32 rval;
   1577 
   1578     reg = MMU_MTRO_CPU_L1_TO_L0_MAPPINGr;
   1579     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, schedq, &rval));
   1580     soc_reg_field_set(unit, reg, &rval, SELECTf, L0);
   1581     SOC_IF_ERROR_RETURN
   1582         (soc_reg32_set(unit, reg, REG_PORT_ANY, schedq, rval));
   1583 
   1584     reg = MMU_QSCH_CPU_L1_TO_L0_MAPPINGr;
   1585     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, schedq, &rval));
   1586     soc_reg_field_set(unit, reg, &rval, SELECTf, L0);
   1587     SOC_IF_ERROR_RETURN
   1588         (soc_reg32_set(unit, reg, REG_PORT_ANY, schedq, rval));
   1589 
   1590     return BCM_E_NONE;
   1591 }
   1592 
   1593 int
   1594 bcm_th3_cosq_gport_delete(int unit, bcm_gport_t gport)
   1595 {
   1596     _bcm_th3_cosq_node_t *node = NULL;
   1597     _bcm_th3_cosq_node_t *child_node = NULL;
   1598     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
   1599     int local_port, i, j;
   1600 
   1601     if (_bcm_th3_cosq_cpu_port_info[unit] == NULL) {
   1602         return BCM_E_INIT;
   1603     }
   1604 
   1605     BCM_IF_ERROR_RETURN
   1606         (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   1607 
   1608     if (!IS_CPU_PORT(unit, local_port)) {
   1609         return BCM_E_PORT;
   1610     }
   1611 
   1612 
   1613     LOG_INFO(BSL_LS_BCM_COSQ,
   1614              (BSL_META_U(unit,
   1615                          "bcm_th3_cosq_gport_delete: unit=%d gport=0x%x\n"),
   1616               unit, gport));
   1617 
   1618     /* Note: currently resets mapping to resetvalue of 0*/
   1619     if (BCM_GPORT_IS_SCHEDULER(gport) ||
   1620           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1621         BCM_IF_ERROR_RETURN
   1622             (_bcm_th3_cosq_node_get(unit, gport, NULL, NULL, NULL, &node));
   1623 
   1624         cpu_port_info = &_bcm_th3_cosq_cpu_port_info[unit][local_port];
   1625         if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   1626             for (i = 0; i < _BCM_TH3_NUM_CPU_MCAST_QUEUE; i++) {
   1627                 if (cpu_port_info->mcast[i].gport == gport) {
   1628                     node = &cpu_port_info->mcast[i];
   1629                     if (node->in_use == 0) {
   1630                         return BCM_E_UNAVAIL;
   1631                     }
   1632                     BCM_IF_ERROR_RETURN
   1633                         (_bcm_th3_cosq_gport_hw_delete(unit, i, 0));
   1634                     node->in_use = 0;
   1635                     node->numq = 0;
   1636                     node->parent_gport = 0;
   1637                 }
   1638             }
   1639         } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1640             for (i = 0; i < _BCM_TH3_NUM_SCHEDULER_PER_PORT; i++) {
   1641                 if (cpu_port_info->sched[i].gport == gport) {
   1642                     node = &cpu_port_info->sched[i];
   1643                     if (node->in_use == 0) {
   1644                         return BCM_E_UNAVAIL;
   1645                     }
   1646                     node->in_use = 0;
   1647                     node->numq = 0;
   1648                     node->parent_gport = 0;
   1649                 }
   1650                 for (j = 0; j < _BCM_TH3_NUM_CPU_MCAST_QUEUE; j++) {
   1651                     if (cpu_port_info->mcast[i].parent_gport == gport) {
   1652                         child_node = &cpu_port_info->mcast[i];
   1653                         child_node->in_use = 0;
   1654                         child_node->numq = 0;
   1655                         child_node->parent_gport = 0;
   1656                         BCM_IF_ERROR_RETURN
   1657                             (_bcm_th3_cosq_gport_hw_delete(unit, j, 0));
   1658                     }
   1659                 }
   1660             }
   1661         }
   1662     } else {
   1663         return BCM_E_PARAM;
   1664     }
   1665 
   1666     return BCM_E_NONE;
   1667 }
   1668 
   1669 /* Function:
   1670  *     bcm_th3_cosq_config_get
   1671  * Purpose:
   1672  *     Get the number of cos queues
   1673  * Parameters:
   1674  *     unit - unit number
   1675  *     numq - (Output) number of cosq
   1676  * Returns:
   1677  *     BCM_E_XXX
   1678  */
   1679 int
   1680 bcm_th3_cosq_config_get(int unit, int *numq)
   1681 {
   1682     int prio, max_cos = 0;
   1683     soc_mem_t mem = PORT_COS_MAPm;
   1684     uint32 entry[SOC_MAX_MEM_WORDS];
   1685 
   1686     if (numq == NULL) {
   1687         return BCM_E_MEMORY;
   1688     }
   1689 
   1690     /* Read profile0 of PORT_COS_MAP to get the max number of COS */
   1691     for (prio = 0; prio < _TH3_MMU_NUM_INT_PRI; prio++) {
   1692         SOC_IF_ERROR_RETURN
   1693             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, prio, entry));
   1694         max_cos = MAX(max_cos, soc_mem_field32_get(unit, mem, entry, UC_COS1f));
   1695 
   1696     }
   1697     *numq = (max_cos + 1);
   1698 
   1699     return BCM_E_NONE;
   1700 }
   1701 
   1702 int
   1703 bcm_th3_cosq_config_set(int unit, int numq)
   1704 {
   1705     port_cos_map_entry_t cos_map_entries[_TH3_MMU_NUM_INT_PRI];
   1706     void *entries[1];
   1707     uint32 index;
   1708     int count, i;
   1709     bcm_port_t port;
   1710     int cos, prio, ref_count = -1;
   1711     soc_mem_t mem = INVALIDm;
   1712     int num_ucq, num_mcq, num_rqe;
   1713     uint16 dev_id;
   1714     uint8 rev_id;
   1715 
   1716     if (numq < 1 || numq > _BCM_TH3_COS_MAX) {
   1717         return BCM_E_PARAM;
   1718     }
   1719 
   1720     num_ucq = _bcm_th3_get_num_ucq(unit);
   1721     if (numq > num_ucq) {
   1722         return BCM_E_PARAM;
   1723     }
   1724     num_mcq = _bcm_th3_get_num_mcq(unit);
   1725 
   1726     soc_cm_get_id(unit, &dev_id, &rev_id);
   1727     if (rev_id == BCM56980_A0_REV_ID) {
   1728         num_rqe = 1;
   1729     } else {
   1730         num_rqe = num_mcq;
   1731     }
   1732 
   1733     index = 0;
   1734     while (index < soc_mem_index_count(unit, PORT_COS_MAPm)) {
   1735         BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit,
   1736                                       _bcm_th3_cos_map_profile[unit],
   1737                                       index, &ref_count));
   1738         if (ref_count > 0) {
   1739             while (ref_count) {
   1740                 if (!soc_profile_mem_delete(unit,
   1741                             _bcm_th3_cos_map_profile[unit], index)) {
   1742                     ref_count -= 1;
   1743                 }
   1744             }
   1745         }
   1746         index += _TH3_MMU_NUM_INT_PRI;
   1747     }
   1748 
   1749     /* Distribute first 8 internal priority levels into the specified number
   1750      * of cosq, map remaining internal priority levels to highest priority
   1751      * cosq */
   1752     sal_memset(cos_map_entries, 0, sizeof(cos_map_entries));
   1753     entries[0] = &cos_map_entries;
   1754     prio = 0;
   1755     mem = PORT_COS_MAPm;
   1756 
   1757     for (cos = 0; cos < numq; cos++) {
   1758         soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
   1759                             UC_COS1f, MIN(cos, num_ucq - 1));
   1760         soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
   1761                             UC_COS2f,  MIN(cos, num_ucq - 1));
   1762         soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
   1763                             MC_COS1f, MIN(cos, num_mcq ? num_mcq - 1 : 0));
   1764         soc_mem_field32_set(unit, mem, &cos_map_entries[prio],
   1765                             RQE_Q_NUMf, MIN(cos, num_rqe ? num_rqe - 1 : 0));
   1766         prio++;
   1767     }
   1768     for (; prio < _TH3_MMU_NUM_INT_PRI; prio++) {
   1769         if (prio < numq) {
   1770             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f,
   1771                             MIN(prio, num_ucq - 1));
   1772             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS2f,
   1773                             MIN(prio, num_ucq - 1));
   1774             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f,
   1775                             MIN(prio, num_mcq ? num_mcq - 1 : 0));
   1776             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], RQE_Q_NUMf,
   1777                             MIN(prio, num_rqe ? num_rqe - 1 : 0));
   1778         }
   1779         else {
   1780             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS1f,
   1781                             MIN(numq - 1, num_ucq - 1));
   1782             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], UC_COS2f,
   1783                             MIN(numq - 1, num_ucq - 1));
   1784             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], MC_COS1f,
   1785                             MIN(numq - 1, num_mcq ? num_mcq - 1 : 0));
   1786             soc_mem_field32_set(unit, mem, &cos_map_entries[prio], RQE_Q_NUMf,
   1787                             MIN(numq - 1, num_rqe ? num_rqe - 1 : 0));
   1788         }
   1789     }
   1790 
   1791     /* Map internal priority levels to CPU CoS queues */
   1792     BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq));
   1793 
   1794     BCM_IF_ERROR_RETURN
   1795         (soc_profile_mem_add(unit, _bcm_th3_cos_map_profile[unit], entries,
   1796                              _TH3_MMU_NUM_INT_PRI, &index));
   1797     count = 0;
   1798     PBMP_ALL_ITER(unit, port) {
   1799         BCM_IF_ERROR_RETURN
   1800             (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf,
   1801                                     index / _TH3_MMU_NUM_INT_PRI));
   1802         count++;
   1803     }
   1804     if (SOC_INFO(unit).cpu_hg_index != -1) {
   1805         BCM_IF_ERROR_RETURN
   1806             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   1807                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   1808                                     index / _TH3_MMU_NUM_INT_PRI));
   1809         count++;
   1810     }
   1811     for (i = 1; i < count; i++) {
   1812         soc_profile_mem_reference(unit, _bcm_th3_cos_map_profile[unit], index,
   1813                               0);
   1814     }
   1815 
   1816     _TH3_NUM_COS(unit) = SOC_TH3_COS_MAX;
   1817 
   1818     return BCM_E_NONE;
   1819 }
   1820 
   1821 /*
   1822  * Function:
   1823  *     bcm_th3_cosq_gport_attach
   1824  * Purpose:
   1825  *     Attach sched_port to the specified index (cosq) of input_port (CPU Port only)
   1826  * Parameters:
   1827  *     unit         - (IN) unit number
   1828  *     input_gport  - (IN) GPORT id, that will attach to parent gport
   1829  *     parent_gport - (IN) Parent Gport to which current gport will be attached
   1830  *     cosq         - (IN) COS queue to attach to (-1 for first available cosq)
   1831  * Returns:
   1832  *     BCM_E_XXX
   1833  */
   1834 int
   1835 bcm_th3_cosq_gport_attach(int unit, bcm_gport_t input_gport,
   1836                          bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   1837 {
   1838     _bcm_th3_cosq_node_t *input_node = NULL;
   1839     bcm_port_t input_port;
   1840 
   1841     LOG_INFO(BSL_LS_BCM_COSQ,
   1842         (BSL_META_U(unit,
   1843         "bcm_th3_cosq_gport_attach: unit=%d parent_gport=0x%x "
   1844         "input_gport=0x%x cosq=%d\n"),
   1845         unit, parent_gport, input_gport, cosq));
   1846 
   1847     if (!(BCM_GPORT_IS_SCHEDULER(input_gport) ||
   1848           BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) ||
   1849           BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   1850         return BCM_E_PARAM;
   1851     }
   1852 
   1853     BCM_IF_ERROR_RETURN
   1854         (_bcm_th3_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   1855                                &input_node));
   1856 
   1857     if (!input_node) {
   1858         return BCM_E_PARAM;
   1859     }
   1860     if (input_port < 0) {
   1861         return BCM_E_PORT;
   1862     }
   1863 
   1864     if (!IS_CPU_PORT(unit, input_port)) {
   1865         return BCM_E_PORT;
   1866     }
   1867     BCM_IF_ERROR_RETURN
   1868         (bcm_th3_cosq_cpu_gport_attach(unit, input_gport,
   1869                                                 parent_gport, cosq));
   1870 
   1871     return BCM_E_NONE;
   1872 }
   1873 
   1874 /* Function to detach any of the 48 L1 MC Queue from its parent 12 L0 nodes
   1875  * Post detach, L1 MC queue is attached to Parent L0.11 node
   1876  */
   1877 STATIC int
   1878 bcm_th3_cosq_cpu_gport_detach(int unit, bcm_gport_t input_gport,
   1879                              bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   1880 {
   1881     bcm_port_t parent_port, input_port;
   1882     _bcm_th3_cosq_node_t *input_node = NULL, *parent_node = NULL;
   1883     int phy_port, mmu_port;
   1884     int input_cos = 0, parent_cos = 0, config_cos = 0;
   1885     int cpu_mc_base = 0, cpu_sched_base = 0;
   1886     soc_info_t *si = &SOC_INFO(unit);
   1887 
   1888     /* Post Default tree created, expected Input Gport is of MC Gport
   1889      * and expected Parent Gport is new L0 Parent
   1890      */
   1891     if ((!BCM_GPORT_IS_SCHEDULER(parent_gport)) ||
   1892         (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   1893         return BCM_E_PARAM;
   1894     }
   1895     BCM_IF_ERROR_RETURN
   1896         (_bcm_th3_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   1897                                &input_node));
   1898     BCM_IF_ERROR_RETURN
   1899         (_bcm_th3_cosq_node_get(unit, parent_gport, NULL, &parent_port, NULL,
   1900                                &parent_node));
   1901 
   1902     if (!IS_CPU_PORT(unit, parent_port)) {
   1903         return BCM_E_PORT;
   1904     }
   1905 
   1906     /* Return BCM_E_PARAM when queue to be detached is
   1907        not attached to the given gport */
   1908     if (input_node->parent_gport != parent_gport) {
   1909         return BCM_E_PARAM;
   1910     }
   1911 
   1912     phy_port = si->port_l2p_mapping[input_port];
   1913     mmu_port = si->port_p2m_mapping[phy_port];
   1914     cpu_sched_base = mmu_port * _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   1915     parent_cos = (parent_node->hw_index - cpu_sched_base) %
   1916                 _BCM_TH3_NUM_CPU_MCAST_QUEUE;
   1917     cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   1918     input_cos = (input_node->hw_index - cpu_mc_base) %
   1919                 _BCM_TH3_NUM_CPU_MCAST_QUEUE;
   1920 
   1921     /* Reset parent to L0.11 */
   1922     SOC_IF_ERROR_RETURN
   1923         (soc_th3_cosq_cpu_parent_get(unit, input_cos, SOC_TH3_NODE_LVL_L1,
   1924                                     &config_cos));
   1925     if (config_cos != parent_cos) {
   1926         /* Error when detaching from wrong Parent (L0 level) */
   1927         return BCM_E_PARAM;
   1928     }
   1929 
   1930     /*
   1931      * L0.0 is associated with CMC0 CH1(Rx)
   1932      * L0.1 is associated with CMC0 CH2(Rx)
   1933      * L0.2 is associated with CMC0 CH3(Rx)
   1934      * L0.3 is associated with CMC0 CH4(Rx)
   1935      * L0.4 is associated with CMC0 CH5(Rx)
   1936      * L0.5 is associated with CMC0 CH6(Rx)
   1937      * L0.6 is associated with CMC0 CH7(Rx)
   1938      */
   1939     if ((parent_cos >= 0) && (parent_cos < 7)) {
   1940         BCM_IF_ERROR_RETURN
   1941             (_bcm_th3_cosq_rx_queue_channel_set(unit, parent_cos, input_cos, 0));
   1942     }
   1943 
   1944     /* Reset parent to L0.11 */
   1945     SOC_IF_ERROR_RETURN
   1946         (soc_th3_cosq_cpu_parent_set(unit, input_cos, SOC_TH3_NODE_LVL_L1,
   1947                                     _BCM_TH3_NUM_SCHEDULER_PER_PORT-1));
   1948     input_node->parent_gport =
   1949         _BCM_TH3_MMU_INFO(unit)->_bcm_th3_cpu_port_info->
   1950             sched[_BCM_TH3_NUM_SCHEDULER_PER_PORT-1].gport;
   1951 
   1952     return BCM_E_NONE;
   1953 }
   1954 
   1955 /*
   1956  * Function:
   1957  *     bcm_th3_cosq_gport_detach
   1958  * Purpose:
   1959  *     Detach sched_port from the specified index (cosq) of input_port (only CPU Port)
   1960  * Parameters:
   1961  *     unit       - (IN) unit number
   1962  *     sched_port - (IN) scheduler GPORT identifier
   1963  *     input_port - (IN) GPORT to detach from
   1964  *     cosq       - (IN) COS queue to detach from
   1965  * Returns:
   1966  *     BCM_E_XXX
   1967  */
   1968 int
   1969 bcm_th3_cosq_gport_detach(int unit, bcm_gport_t input_gport,
   1970                          bcm_gport_t parent_gport, bcm_cos_queue_t cosq)
   1971 {
   1972     _bcm_th3_cosq_node_t *input_node = NULL;
   1973     bcm_port_t input_port;
   1974 
   1975     LOG_INFO(BSL_LS_BCM_COSQ,
   1976              (BSL_META_U(unit,
   1977                          "bcm_th3_cosq_gport_detach: unit=%d input_gport=0x%x "
   1978                          "parent_gport=0x%x cosq=%d\n"),
   1979               unit, input_gport, parent_gport, cosq));
   1980 
   1981     if (!(BCM_GPORT_IS_SCHEDULER(input_gport) ||
   1982           BCM_GPORT_IS_UCAST_QUEUE_GROUP(input_gport) ||
   1983           BCM_GPORT_IS_MCAST_QUEUE_GROUP(input_gport))) {
   1984         return BCM_E_PARAM;
   1985     }
   1986 
   1987     BCM_IF_ERROR_RETURN
   1988         (_bcm_th3_cosq_node_get(unit, input_gport, NULL, &input_port, NULL,
   1989                                &input_node));
   1990 
   1991     if (!input_node) {
   1992         return BCM_E_PARAM;
   1993     }
   1994 
   1995     if (!IS_CPU_PORT(unit, input_port)) {
   1996         return BCM_E_PORT;
   1997     }
   1998 
   1999     if (_BCM_TH3_MMU_INFO(unit)->gport_tree_created == TRUE) {
   2000         return bcm_th3_cosq_cpu_gport_detach(unit, input_gport,
   2001                                             parent_gport, cosq);
   2002     } else {
   2003         return BCM_E_INIT;
   2004     }
   2005 
   2006 }
   2007 
   2008 /*
   2009  * Function:
   2010  *      bcm_th3_cosq_gport_child_get
   2011  * Purpose:
   2012  *      Get the child node GPORT atatched to N-th index (cosq). Only CPu PORT
   2013  *      of the scheduler GPORT.
   2014  * Parameters:
   2015  *      unit       - (IN)  Unit number.
   2016  *      in_gport   - (IN)  Scheduler GPORT ID.
   2017  *      cosq       - (IN)  COS queue attached to.
   2018  *      out_gport  - (OUT) child GPORT ID.
   2019  * Returns:
   2020  *      BCM_E_XXX
   2021  * Notes:
   2022  */
   2023 int
   2024 bcm_th3_cosq_gport_child_get(int unit, bcm_gport_t in_gport,
   2025                             bcm_cos_queue_t cosq,
   2026                             bcm_gport_t *out_gport)
   2027 {
   2028     _bcm_th3_cosq_node_t *tmp_node = NULL;
   2029     bcm_port_t local_port = -1;
   2030     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
   2031     _bcm_th3_cosq_port_info_t *port_info = NULL;
   2032     int index = -1, cpu_mc_base = 0;
   2033     soc_info_t *si = &SOC_INFO(unit);
   2034 
   2035     if (out_gport == NULL) {
   2036         return BCM_E_PARAM;
   2037     }
   2038 
   2039     BCM_IF_ERROR_RETURN
   2040         (_bcm_th3_cosq_localport_resolve(unit, in_gport, &local_port));
   2041 
   2042     if (!SOC_PORT_VALID(unit, local_port)) {
   2043         return BCM_E_PORT;
   2044     }
   2045 
   2046     if (IS_CPU_PORT(unit, local_port)) {
   2047         if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) {
   2048             return BCM_E_PARAM;
   2049         }
   2050 
   2051         if (_bcm_th3_cosq_cpu_port_info[unit] == NULL) {
   2052             return BCM_E_INIT;
   2053         }
   2054 
   2055         cpu_port_info = _bcm_th3_cosq_cpu_port_info[unit];
   2056         cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   2057 
   2058         if (BCM_GPORT_IS_SCHEDULER(in_gport)) {
   2059             for (index = 0; index < _BCM_TH3_NUM_CPU_MCAST_QUEUE; index++) {
   2060                 if (cpu_port_info->mcast[index].parent_gport == in_gport) {
   2061                     if (cosq == ((cpu_port_info->mcast[index].hw_index - cpu_mc_base) %
   2062                                  _BCM_TH3_NUM_CPU_MCAST_QUEUE)) {
   2063                         tmp_node = &cpu_port_info->mcast[index];
   2064                         *out_gport = tmp_node->gport;
   2065                         goto exit;
   2066                     }
   2067                 }
   2068             }
   2069         } else {
   2070             return BCM_E_PARAM;
   2071         }
   2072 
   2073         if (tmp_node == NULL) {
   2074             return BCM_E_NOT_FOUND;
   2075         }
   2076 
   2077     } else { /* Non-CPU port */
   2078         if (_bcm_th3_cosq_port_info[unit] == NULL) {
   2079             return BCM_E_INIT;
   2080         }
   2081         if ((cosq < 0) || (cosq >= _BCM_TH3_COS_MAX)) {
   2082             return BCM_E_PARAM;
   2083         }
   2084         port_info = &_bcm_th3_cosq_port_info[unit][local_port];
   2085 
   2086         if (BCM_GPORT_IS_SCHEDULER(in_gport)) {
   2087             for (index = 0; index < _BCM_TH3_MAX_NUM_UCAST_QUEUE_PER_PORT; index++) {
   2088                 if (port_info->ucast[index].parent_gport == in_gport) {
   2089                     if (cosq == (port_info->ucast[index].cos %
   2090                                  _BCM_TH3_COS_MAX)) {
   2091                         tmp_node = &port_info->ucast[index];
   2092                         *out_gport = tmp_node->gport;
   2093                         goto exit;
   2094                     }
   2095                 }
   2096             }
   2097             if (tmp_node == NULL) {
   2098                 for (index = 0; index < _BCM_TH3_MAX_NUM_MCAST_QUEUE_PER_PORT; index++) {
   2099                     if (port_info->mcast[index].parent_gport == in_gport) {
   2100                         if (cosq == (port_info->mcast[index].cos  %
   2101                                      _BCM_TH3_COS_MAX)) {
   2102                             tmp_node = &port_info->mcast[index];
   2103                             *out_gport = tmp_node->gport;
   2104                             goto exit;
   2105                         }
   2106                     }
   2107                 }
   2108             }
   2109         } else {
   2110             return BCM_E_PARAM;
   2111         }
   2112 
   2113         if (tmp_node == NULL) {
   2114             return BCM_E_NOT_FOUND;
   2115         }
   2116     }
   2117 
   2118 exit:
   2119     return BCM_E_NONE;
   2120 }
   2121 
   2122 
   2123 /*
   2124  * Function:
   2125  *     bcm_th3_cosq_gport_sched_get
   2126  * Purpose:
   2127  *     Get COS queue schedular setting
   2128  * Parameters:
   2129  *     unit     - (IN) unit number
   2130  *     gport    - (IN) GPORT identifier
   2131  *     cosq     - (IN) COS queue to get, -1 for any queue
   2132  *     mode     - (OUT) Scheduling mode (BCM_COSQ_XXX)
   2133  *     weights  - (OUT) Weights for queue
   2134  * Returns:
   2135  *     BCM_E_XXX
   2136  */
   2137 int
   2138 bcm_th3_cosq_gport_sched_get(int unit, bcm_gport_t gport,
   2139                             bcm_cos_queue_t cosq, int *mode, int *weight)
   2140 {
   2141     _bcm_th3_cosq_node_t *node = NULL;
   2142     int local_port = -1, cpu_mc_base = 0;
   2143     soc_info_t *si = &SOC_INFO(unit);
   2144 
   2145     if (BCM_GPORT_IS_SET(gport)) {
   2146         if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   2147              BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   2148              BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2149 
   2150             BCM_IF_ERROR_RETURN
   2151                  (_bcm_th3_cosq_node_get(unit, gport, NULL, &local_port, NULL, &node));
   2152 
   2153             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   2154                 /* For Non-CPU and non-LB ports, num UC queues are 10 */
   2155                 cosq = node->hw_index % _BCM_TH3_MAX_NUM_QUEUE_PER_PORT;
   2156             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2157                 /* For Non-CPU ports, num MC queues are 10
   2158                  * For CPU ports, num MC queues are 48
   2159                  */
   2160                 if (IS_CPU_PORT(unit, local_port)) {
   2161                     cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   2162                     cosq = (node->hw_index - cpu_mc_base) %
   2163                            _BCM_TH3_NUM_CPU_MCAST_QUEUE;
   2164                 } else {
   2165                     cosq = node->hw_index % _BCM_TH3_MAX_NUM_QUEUE_PER_PORT;
   2166                 }
   2167             } else {
   2168                 /* For all ports, total scheduler nodes(L0) are 12 */
   2169                 cosq = node->hw_index % _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   2170             }
   2171             BCM_IF_ERROR_RETURN(
   2172                 _bcm_th3_cosq_sched_get(unit, gport, cosq, mode, weight));
   2173             return BCM_E_NONE;
   2174         } else {
   2175             BCM_IF_ERROR_RETURN(_bcm_th3_cosq_localport_resolve(unit, gport,
   2176                                                                &local_port));
   2177 
   2178             if ((cosq < 0) || (cosq >=  _TH3_PORT_NUM_COS(unit, local_port))) {
   2179                 return BCM_E_PARAM;
   2180             }
   2181 
   2182             BCM_IF_ERROR_RETURN(
   2183                 _bcm_th3_cosq_sched_get(unit, local_port, cosq, mode, weight));
   2184             return BCM_E_NONE;
   2185         }
   2186     } else {
   2187         return BCM_E_PORT;
   2188     }
   2189 
   2190     return BCM_E_NOT_FOUND;
   2191 }
   2192 
   2193 /*
   2194  * Function:
   2195  *     bcm_th3_cosq_gport_sched_set
   2196  * Purpose:
   2197  *     Set up class-of-service policy and corresponding weights and delay
   2198  * Parameters:
   2199  *     unit    - (IN) unit number
   2200  *     gport   - (IN) GPORT ID
   2201  *     cosq    - (IN) COS queue to configure
   2202  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   2203  *     weight - (IN) Weight for COS queue
   2204  * Returns:
   2205  *     BCM_E_XXX
   2206  */
   2207 int
   2208 bcm_th3_cosq_gport_sched_set(int unit, bcm_gport_t gport,
   2209                            bcm_cos_queue_t cosq, int mode, int weight)
   2210 {
   2211     _bcm_th3_cosq_node_t *node = NULL;
   2212     soc_info_t *si = &SOC_INFO(unit);
   2213     int local_port = -1, cpu_mc_base = 0;
   2214 
   2215     if (BCM_GPORT_IS_SET(gport)) {
   2216         if (BCM_GPORT_IS_SCHEDULER(gport) ||
   2217             BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   2218             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2219 
   2220             BCM_IF_ERROR_RETURN
   2221                  (_bcm_th3_cosq_node_get(unit, gport, NULL, &local_port,
   2222                                         NULL, &node));
   2223 
   2224             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   2225                 /* For Non-CPU and non-LB ports, num UC queues are 12 */
   2226                 cosq = node->hw_index % _BCM_TH3_MAX_NUM_QUEUE_PER_PORT;
   2227             } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   2228                 /* For Non-CPU ports, num MC queues are 12
   2229                  * For CPU ports, num MC queues are 48
   2230                  */
   2231                 if (IS_CPU_PORT(unit, local_port)) {
   2232                     cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   2233                     cosq = (node->hw_index - cpu_mc_base) %
   2234                            _BCM_TH3_NUM_CPU_MCAST_QUEUE;
   2235                 } else {
   2236                     cosq = node->hw_index % _BCM_TH3_MAX_NUM_QUEUE_PER_PORT;
   2237                 }
   2238             } else {
   2239                 /* For all ports, total scheduler nodes(L0) are 10 */
   2240                 cosq = node->hw_index % _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   2241             }
   2242             BCM_IF_ERROR_RETURN
   2243                 (_bcm_th3_cosq_sched_set(unit, gport, cosq, mode, weight));
   2244             return BCM_E_NONE;
   2245         } else {
   2246             BCM_IF_ERROR_RETURN(_bcm_th3_cosq_localport_resolve(unit, gport,
   2247                                                                &local_port));
   2248 
   2249             if ((cosq < 0) || (cosq >= _TH3_PORT_NUM_COS(unit, local_port))) {
   2250                 return BCM_E_PARAM;
   2251             }
   2252 
   2253             BCM_IF_ERROR_RETURN
   2254                 (_bcm_th3_cosq_sched_set(unit, local_port, cosq, mode, weight));
   2255             return BCM_E_NONE;
   2256         }
   2257     } else {
   2258         return BCM_E_PORT;
   2259     }
   2260 
   2261     return BCM_E_NOT_FOUND;
   2262 }
   2263 
   2264 /*
   2265  * Function:
   2266  *     bcm_th3_cosq_init
   2267  * Purpose:
   2268  *     Initialize (clear) all COS schedule/mapping state.
   2269  * Parameters:
   2270  *     unit - unit number
   2271  * Returns:
   2272  *     BCM_E_XXX
   2273  */
   2274 int
   2275 bcm_th3_cosq_init(int unit)
   2276 {
   2277     STATIC int _th3_max_cosq = -1;
   2278     int i, alloc_size;
   2279     int pipe = -1, itm = -1;
   2280     uint32 pipe_map;
   2281     bcm_port_t port;
   2282     soc_mem_t mem = INVALIDm;
   2283     static soc_mem_t wred_mems[_BCM_TH3_NUM_WRED_PROFILES] = {
   2284         MMU_WRED_DROP_CURVE_PROFILE_0_0m, MMU_WRED_DROP_CURVE_PROFILE_1_0m,
   2285         MMU_WRED_DROP_CURVE_PROFILE_2_0m, MMU_WRED_DROP_CURVE_PROFILE_3_0m,
   2286         MMU_WRED_DROP_CURVE_PROFILE_4_0m, MMU_WRED_DROP_CURVE_PROFILE_5_0m,
   2287         MMU_WRED_DROP_CURVE_PROFILE_6_0m, MMU_WRED_DROP_CURVE_PROFILE_7_0m,
   2288         MMU_WRED_DROP_CURVE_PROFILE_8_0m
   2289     };
   2290     int entry_words[_BCM_TH3_NUM_WRED_PROFILES];
   2291     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   2292     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   2293     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   2294     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   2295     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   2296     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   2297     mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green;
   2298     mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow;
   2299     mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red;
   2300     void *entries[_BCM_TH3_NUM_WRED_PROFILES];
   2301     int wred_prof_count;
   2302     soc_mem_t wred_config_mem = INVALIDm;
   2303     uint32 profile_index;
   2304     uint32 entry[SOC_MAX_MEM_WORDS];
   2305     int min_index, max_index;
   2306     int num_uc_q;
   2307 
   2308     _bcm_bst_device_handlers_t bst_callbks;
   2309 
   2310     _bcm_th3_cosq_cpu_cosq_config_t *cpu_cosq_config_p = NULL;
   2311     int rv = BCM_E_NONE;
   2312 
   2313     if (_th3_max_cosq < 0) {
   2314         _th3_max_cosq = NUM_COS(unit);
   2315         NUM_COS(unit) = 12;
   2316     }
   2317 
   2318     sal_memset(&entry, 0, sizeof(entry));
   2319 
   2320     if (!SOC_WARM_BOOT(unit)) {
   2321         _bcm_th3_cosq_cleanup(unit);
   2322     }
   2323 
   2324 
   2325     /* Create Port Information structure */
   2326     alloc_size = sizeof(_bcm_th3_cosq_port_info_t) * SOC_TH3_MAX_NUM_PORTS;
   2327     if (_bcm_th3_cosq_port_info[unit] == NULL) {
   2328         _bcm_th3_cosq_port_info[unit] =
   2329             sal_alloc(alloc_size, "_bcm_th3_cosq_port_info");
   2330             if (_bcm_th3_cosq_port_info[unit] == NULL) {
   2331                 return BCM_E_MEMORY;
   2332             }
   2333     }
   2334     sal_memset(_bcm_th3_cosq_port_info[unit], 0, alloc_size);
   2335 
   2336     /* Create CPU Port Information structure */
   2337     alloc_size = sizeof(_bcm_th3_cosq_cpu_port_info_t);
   2338     if (_bcm_th3_cosq_cpu_port_info[unit] == NULL) {
   2339         _bcm_th3_cosq_cpu_port_info[unit] =
   2340             sal_alloc(alloc_size, "_bcm_th3_cosq_cpu_port_info");
   2341         if (_bcm_th3_cosq_cpu_port_info[unit] == NULL) {
   2342             _bcm_th3_cosq_cleanup(unit);
   2343             return BCM_E_MEMORY;
   2344         }
   2345     }
   2346     sal_memset(_bcm_th3_cosq_cpu_port_info[unit], 0, alloc_size);
   2347 
   2348     /* Create MMU Port Information structure */
   2349     alloc_size = sizeof(_bcm_th3_mmu_info_t);
   2350     if (_bcm_th3_mmu_info[unit] == NULL) {
   2351         _bcm_th3_mmu_info[unit] =
   2352             sal_alloc(alloc_size, "_bcm_th3_mmu_info");
   2353         if (_bcm_th3_mmu_info[unit] == NULL) {
   2354             _bcm_th3_cosq_cleanup(unit);
   2355             return BCM_E_MEMORY;
   2356         }
   2357     }
   2358     sal_memset(_bcm_th3_mmu_info[unit], 0, alloc_size);
   2359     _BCM_TH3_MMU_INFO(unit)->_bcm_th3_port_info =
   2360             _bcm_th3_cosq_port_info[unit];
   2361     _BCM_TH3_MMU_INFO(unit)->_bcm_th3_cpu_port_info =
   2362             _bcm_th3_cosq_cpu_port_info[unit];
   2363 
   2364     /* Create profile for PORT_COS_MAP table */
   2365     if (_bcm_th3_cos_map_profile[unit] == NULL) {
   2366         _bcm_th3_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   2367                                                   "COS_MAP Profile Mem");
   2368         if (_bcm_th3_cos_map_profile[unit] == NULL) {
   2369             _bcm_th3_cosq_cleanup(unit);
   2370             return BCM_E_MEMORY;
   2371         }
   2372         soc_profile_mem_t_init(_bcm_th3_cos_map_profile[unit]);
   2373     }
   2374     mem = PORT_COS_MAPm;
   2375     entry_words[0] = sizeof(port_cos_map_entry_t) / sizeof(uint32);
   2376 
   2377     rv = soc_profile_mem_create(unit, &mem, entry_words, 1,
   2378                                 _bcm_th3_cos_map_profile[unit]);
   2379     if (rv != SOC_E_NONE) {
   2380         _bcm_th3_cosq_cleanup(unit);
   2381         return rv;
   2382     }
   2383 
   2384     /* Create profile for IFP_COS_MAP table */
   2385     if (_bcm_th3_ifp_cos_map_profile[unit] == NULL) {
   2386         _bcm_th3_ifp_cos_map_profile[unit]
   2387             = sal_alloc(sizeof(soc_profile_mem_t), "IFP_COS_MAP Profile Mem");
   2388         if (_bcm_th3_ifp_cos_map_profile[unit] == NULL) {
   2389             _bcm_th3_cosq_cleanup(unit);
   2390             return BCM_E_MEMORY;
   2391         }
   2392         soc_profile_mem_t_init(_bcm_th3_ifp_cos_map_profile[unit]);
   2393     }
   2394     mem = IFP_COS_MAPm;
   2395     entry_words[0] = sizeof(ifp_cos_map_entry_t) / sizeof(uint32);
   2396 
   2397     min_index = soc_mem_index_min(unit, IFP_COS_MAPm);
   2398     max_index = soc_mem_index_max(unit, IFP_COS_MAPm) - _TH3_MMU_NUM_INT_PRI;
   2399     rv = soc_profile_mem_index_create(unit, &mem, entry_words,
   2400                                 &min_index, &max_index, NULL, 1,
   2401                                 _bcm_th3_ifp_cos_map_profile[unit]);
   2402     if (rv != SOC_E_NONE) {
   2403         _bcm_th3_cosq_cleanup(unit);
   2404         return rv;
   2405     }
   2406 
   2407     /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */
   2408     if (_bcm_th3_wred_profile[unit] == NULL) {
   2409         _bcm_th3_wred_profile[unit] =
   2410                 sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem");
   2411         if (_bcm_th3_wred_profile[unit] == NULL) {
   2412             _bcm_th3_cosq_cleanup(unit);
   2413             return BCM_E_MEMORY;
   2414         }
   2415         soc_profile_mem_t_init(_bcm_th3_wred_profile[unit]);
   2416     }
   2417 
   2418 
   2419     for (i = 0; i < _BCM_TH3_NUM_WRED_PROFILES; i++) {
   2420         entry_words[i] =
   2421             sizeof(mmu_wred_drop_curve_profile_0_entry_t) / sizeof(uint32);
   2422     }
   2423 
   2424     rv = soc_profile_mem_create(unit, wred_mems, entry_words, _BCM_TH3_NUM_WRED_PROFILES,
   2425                                 _bcm_th3_wred_profile[unit]);
   2426     if (rv != SOC_E_NONE) {
   2427         _bcm_th3_cosq_cleanup(unit);
   2428         return rv;
   2429     }
   2430 
   2431     if (_bcm_th3_cosq_cpu_cosq_config[unit][0] == NULL) {
   2432         cpu_cosq_config_p = sal_alloc(
   2433                 SOC_TH3_NUM_CPU_QUEUES * sizeof(_bcm_th3_cosq_cpu_cosq_config_t),
   2434                 "CPU Cosq Config");
   2435         if (cpu_cosq_config_p == NULL) {
   2436             _bcm_th3_cosq_cleanup(unit);
   2437             return BCM_E_MEMORY;
   2438         }
   2439         if (NUM_CPU_COSQ(unit) > SOC_TH3_NUM_CPU_QUEUES) {
   2440             /* Invalid CPU Queues */
   2441             if (cpu_cosq_config_p != NULL) {
   2442                 sal_free(cpu_cosq_config_p);
   2443                 cpu_cosq_config_p = NULL;
   2444             }
   2445             _bcm_th3_cosq_cleanup(unit);
   2446             return BCM_E_INIT;
   2447         }
   2448         for (i = 0; i < NUM_CPU_COSQ(unit); i++) {
   2449             _bcm_th3_cosq_cpu_cosq_config[unit][i] = cpu_cosq_config_p + i;
   2450         }
   2451     }
   2452 
   2453     /* Assign default init values for RQE queue number */
   2454     rv = _bcm_th3_rqe_q_init(unit);
   2455     if (rv != BCM_E_NONE) {
   2456         if (cpu_cosq_config_p != NULL) {
   2457             sal_free(cpu_cosq_config_p);
   2458             cpu_cosq_config_p = NULL;
   2459         }
   2460         _bcm_th3_cosq_cleanup(unit);
   2461         return rv;
   2462     }
   2463 
   2464     /* Requires ECN init to program the default Responsive/Non-responsive
   2465      * settings in Hardware
   2466      */
   2467     if(soc_feature(unit, soc_feature_ecn_wred)) {
   2468         rv = _bcm_th3_ecn_init(unit);
   2469         if (rv != BCM_E_NONE) {
   2470             if (cpu_cosq_config_p != NULL) {
   2471                 sal_free(cpu_cosq_config_p);
   2472                 cpu_cosq_config_p = NULL;
   2473             }
   2474             _bcm_th3_cosq_cleanup(unit);
   2475             return rv;
   2476         }
   2477     }
   2478 
   2479     rv = _bcm_oob_init(unit);
   2480     if (rv != BCM_E_NONE) {
   2481         if (cpu_cosq_config_p != NULL) {
   2482             sal_free(cpu_cosq_config_p);
   2483             cpu_cosq_config_p = NULL;
   2484         }
   2485         _bcm_th3_cosq_cleanup(unit);
   2486         return rv;
   2487     }
   2488 
   2489 #ifdef BCM_WARM_BOOT_SUPPORT
   2490     if (SOC_WARM_BOOT(unit)) {
   2491         rv = bcm_th3_cosq_reinit(unit);
   2492         if (rv != BCM_E_NONE) {
   2493             if (cpu_cosq_config_p != NULL) {
   2494                 sal_free(cpu_cosq_config_p);
   2495                 cpu_cosq_config_p = NULL;
   2496             }
   2497             _bcm_th3_cosq_cleanup(unit);
   2498         }
   2499     /*
   2500      * COVERITY
   2501      *
   2502      * This checker will not be True.
   2503      * cpu_cosq_config_p pointer is assigned to
   2504      * _bcm_th3_cosq_cpu_cosq_config global data
   2505      * structure.
   2506      */
   2507     /* coverity[resource_leak] */
   2508         return rv;
   2509     } else {
   2510         rv = _bcm_th3_cosq_wb_alloc(unit);
   2511         if (rv != BCM_E_NONE) {
   2512             if (cpu_cosq_config_p != NULL) {
   2513                 sal_free(cpu_cosq_config_p);
   2514                 cpu_cosq_config_p = NULL;
   2515             }
   2516             _bcm_th3_cosq_cleanup(unit);
   2517             return rv;
   2518         }
   2519     }
   2520 #endif /* BCM_WARM_BOOT_SUPPORT */
   2521 
   2522     /* Assign default init values for CPU info */
   2523     for (i = 0; i < NUM_CPU_COSQ(unit); i++) {
   2524         if (_bcm_th3_cosq_cpu_cosq_config[unit][i] == NULL) {
   2525             if (cpu_cosq_config_p != NULL) {
   2526                 sal_free(cpu_cosq_config_p);
   2527                 cpu_cosq_config_p = NULL;
   2528             }
   2529             _bcm_th3_cosq_cleanup(unit);
   2530             return BCM_E_MEMORY;
   2531         }
   2532         sal_memset(_bcm_th3_cosq_cpu_cosq_config[unit][i], 0,
   2533                    sizeof(_bcm_th3_cosq_cpu_cosq_config_t));
   2534         _bcm_th3_cosq_cpu_cosq_config[unit][i]->enable = 1;
   2535     }
   2536 
   2537     /* Add default entries for PORT_COS_MAP memory profile */
   2538     num_uc_q = _bcm_th3_get_num_ucq(unit);
   2539     rv = bcm_th3_cosq_config_set(unit, num_uc_q);
   2540     if (rv != BCM_E_NONE) {
   2541         if (cpu_cosq_config_p != NULL) {
   2542             sal_free(cpu_cosq_config_p);
   2543             cpu_cosq_config_p = NULL;
   2544         }
   2545         _bcm_th3_cosq_cleanup(unit);
   2546         return rv;
   2547     }
   2548 
   2549     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
   2550         rv = _bcm_th3_pfc_deadlock_init(unit);
   2551         if (rv != BCM_E_NONE) {
   2552             if (cpu_cosq_config_p != NULL) {
   2553                 sal_free(cpu_cosq_config_p);
   2554                 cpu_cosq_config_p = NULL;
   2555             }
   2556             _bcm_th3_cosq_cleanup(unit);
   2557             return rv;
   2558         }
   2559     }
   2560 
   2561     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   2562         for (itm = 0; itm < SOC_MMU_CFG_ITM_MAX; itm++) {
   2563             soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   2564             if (pipe_map & (1 << pipe)) {
   2565                 mem = MMU_WRED_QUEUE_CONFIGm;
   2566                 rv = soc_mem_clear(unit, mem, COPYNO_ALL, 1);
   2567                 if (rv != SOC_E_NONE) {
   2568                     if (cpu_cosq_config_p != NULL) {
   2569                         sal_free(cpu_cosq_config_p);
   2570                         cpu_cosq_config_p = NULL;
   2571                     }
   2572                     _bcm_th3_cosq_cleanup(unit);
   2573                     return rv;
   2574                 }
   2575             }
   2576         }
   2577     }
   2578 
   2579     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
   2580         for (itm = 0; itm < SOC_MMU_CFG_ITM_MAX; itm++) {
   2581             soc_tomahawk3_pipe_map_get(unit, &pipe_map);
   2582             if (pipe_map & (1 << pipe)) {
   2583                 mem = MMU_WRED_PORTSP_CONFIGm;
   2584                 rv = soc_mem_clear(unit, mem, COPYNO_ALL, 1);
   2585                 if (rv != SOC_E_NONE) {
   2586                     if (cpu_cosq_config_p != NULL) {
   2587                         sal_free(cpu_cosq_config_p);
   2588                         cpu_cosq_config_p = NULL;
   2589                     }
   2590                     _bcm_th3_cosq_cleanup(unit);
   2591                     return rv;
   2592                 }
   2593             }
   2594         }
   2595     }
   2596 
   2597     /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */
   2598     sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green));
   2599     sal_memset(&entry_tcp_yellow,0, sizeof(entry_tcp_yellow));
   2600     sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red));
   2601     sal_memset(&entry_nontcp_green, 0, sizeof(entry_nontcp_green));
   2602     sal_memset(&entry_nontcp_yellow, 0, sizeof(entry_nontcp_yellow));
   2603     sal_memset(&entry_nontcp_red, 0, sizeof(entry_nontcp_red));
   2604     sal_memset(&entry_ecn_green, 0, sizeof(entry_ecn_green));
   2605     sal_memset(&entry_ecn_yellow,0, sizeof(entry_ecn_yellow));
   2606     sal_memset(&entry_ecn_red, 0, sizeof(entry_ecn_red));
   2607     entries[0] = &entry_tcp_green;
   2608     entries[1] = &entry_tcp_yellow;
   2609     entries[2] = &entry_tcp_red;
   2610     entries[3] = &entry_nontcp_green;
   2611     entries[4] = &entry_nontcp_yellow;
   2612     entries[5] = &entry_nontcp_red;
   2613     entries[6] = &entry_ecn_green;
   2614     entries[7] = &entry_ecn_yellow;
   2615     entries[8] = &entry_ecn_red;
   2616 
   2617     for (i = 0; i < _BCM_TH3_NUM_WRED_PROFILES; i++) {
   2618         soc_mem_field32_set(unit, wred_mems[i], entries[i],
   2619                             MIN_THDf, 0x7ffff);
   2620         soc_mem_field32_set(unit, wred_mems[i], entries[i],
   2621                             MAX_THDf, 0x7ffff);
   2622     }
   2623     profile_index = TH3_WRED_PROFILE_INDEX_INVALID;
   2624     wred_config_mem = MMU_WRED_QUEUE_CONFIGm;
   2625     wred_prof_count = soc_mem_index_count(unit, wred_config_mem);
   2626     LOG_INFO(BSL_LS_BCM_COSQ,
   2627         (BSL_META_U(unit, "wred_prof_count: %d\n"),
   2628               wred_prof_count));
   2629 
   2630     
   2631     wred_prof_count *= (2 * NUM_PIPE(unit));
   2632     while(wred_prof_count) {
   2633         if (profile_index == TH3_WRED_PROFILE_INDEX_INVALID) {
   2634             rv = soc_profile_mem_add(unit, _bcm_th3_wred_profile[unit],
   2635                                      entries, 1, &profile_index);
   2636             LOG_INFO(BSL_LS_BCM_COSQ,
   2637                 (BSL_META_U(unit, "1 profile_index: %d\n"),
   2638                     profile_index));
   2639         } else {
   2640             rv = soc_profile_mem_reference(unit, _bcm_th3_wred_profile[unit],
   2641                                            profile_index, 0);
   2642             LOG_INFO(BSL_LS_BCM_COSQ,
   2643                 (BSL_META_U(unit, "2 profile_index: %d\n"),
   2644                     profile_index));
   2645         }
   2646         if (rv != SOC_E_NONE) {
   2647             if (cpu_cosq_config_p != NULL) {
   2648                 sal_free(cpu_cosq_config_p);
   2649                 cpu_cosq_config_p = NULL;
   2650             }
   2651             _bcm_th3_cosq_cleanup(unit);
   2652             return rv;
   2653         }
   2654         wred_prof_count -= 1;
   2655     }
   2656 
   2657     for (i = 0; i < _BCM_TH3_NUM_WRED_RESOLUTION_TABLE; i++) {
   2658         if (i == 0) {
   2659             _bcm_th3_wred_resolution_tbl[i] = 1;
   2660         } else {
   2661             _bcm_th3_wred_resolution_tbl[i] = 0;
   2662         }
   2663     }
   2664 
   2665     _BCM_TH3_MMU_INFO(unit)->gport_tree_created = FALSE;
   2666     PBMP_ALL_ITER(unit, port) {
   2667         if (IS_LB_PORT(unit, port)) {
   2668             continue;
   2669         }
   2670         rv = _bcm_th3_cosq_gport_tree_create(unit, port);
   2671         if (rv != BCM_E_NONE) {
   2672             if (cpu_cosq_config_p != NULL) {
   2673                 sal_free(cpu_cosq_config_p);
   2674                 cpu_cosq_config_p = NULL;
   2675             }
   2676             _bcm_th3_cosq_cleanup(unit);
   2677             return rv;
   2678         }
   2679     }
   2680     _BCM_TH3_MMU_INFO(unit)->gport_tree_created = TRUE;
   2681 
   2682     rv = _bcm_th3_cosq_gport_default_config(unit);
   2683     if (rv != BCM_E_NONE) {
   2684         if (cpu_cosq_config_p != NULL) {
   2685             sal_free(cpu_cosq_config_p);
   2686             cpu_cosq_config_p = NULL;
   2687         }
   2688         _bcm_th3_cosq_cleanup(unit);
   2689         return rv;
   2690     }
   2691 
   2692     /* BST init */
   2693     sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t));
   2694     bst_callbks.resolve_index = &bcm_bst_th3_index_resolve;
   2695     bst_callbks.reverse_resolve_index =
   2696         &_bcm_th3_cosq_bst_map_resource_to_gport_cos;
   2697     rv = _bcm_bst_attach(unit, &bst_callbks);
   2698     /* BST init done */
   2699     if (rv != BCM_E_NONE) {
   2700         if (cpu_cosq_config_p != NULL) {
   2701             sal_free(cpu_cosq_config_p);
   2702             cpu_cosq_config_p = NULL;
   2703         }
   2704         _bcm_th3_cosq_cleanup(unit);
   2705         return rv;
   2706     }
   2707 
   2708 #if defined(INCLUDE_PSTATS)
   2709     if (soc_feature(unit, soc_feature_pstats)) {
   2710         rv = _bcm_pstats_init(unit);
   2711         if (rv != BCM_E_NONE) {
   2712             if (cpu_cosq_config_p != NULL) {
   2713                 sal_free(cpu_cosq_config_p);
   2714                 cpu_cosq_config_p = NULL;
   2715             }
   2716             _bcm_th3_cosq_cleanup(unit);
   2717             return rv;
   2718         }
   2719     }
   2720 #endif /* INCLUDE_PSTATS */
   2721 
   2722     rv = soc_th3_mmu_get_shared_size(unit,
   2723                      _BCM_TH3_MMU_INFO(unit)->shared_limit);
   2724 
   2725     if (rv != SOC_E_NONE) {
   2726         if (cpu_cosq_config_p != NULL) {
   2727             sal_free(cpu_cosq_config_p);
   2728             cpu_cosq_config_p = NULL;
   2729         }
   2730         _bcm_th3_cosq_cleanup(unit);
   2731         return rv;
   2732     }
   2733 
   2734     /* reset time_domain ref_count so that entries can be added upon
   2735      * rc */
   2736     th3_time_domain_info[unit][0].ref_count = 324;
   2737     th3_time_domain_info[unit][1].ref_count = 0;
   2738     th3_time_domain_info[unit][2].ref_count = 0;
   2739     th3_time_domain_info[unit][3].ref_count = 0;
   2740     return BCM_E_NONE;
   2741 }
   2742 
   2743 /*
   2744  * Function:
   2745  *     bcm_tomahawk3_cosq_port_profile_set
   2746  * Purpose:
   2747  *     Set Port to Profile Mapping for Cosq profiles
   2748  * Parameters:
   2749  *     unit         - (IN) unit number
   2750  *     port         - (IN) logical port
   2751  *     profile_type - (IN) Profile type
   2752  *     profile_id   - (IN) profile id
   2753  * Returns:
   2754  *     BCM_E_XXX
   2755  */
   2756 int
   2757 bcm_tomahawk3_cosq_port_profile_set(int unit, bcm_port_t port,
   2758         bcm_cosq_profile_type_t profile_type, int profile_id)
   2759 {
   2760     if (!SOC_PORT_VALID(unit, port)) {
   2761         return BCM_E_PORT;
   2762     }
   2763     switch (profile_type) {
   2764         case bcmCosqProfilePFCAndQueueHierarchy:
   2765             if ((profile_id < 0) || (profile_id >=
   2766                         _BCM_TH3_NUM_QSCHED_PROFILES)) {
   2767                 return BCM_E_PARAM;
   2768             }
   2769             if (!soc_tomahawk3_profile_exists(unit, profile_id)) {
   2770                 return BCM_E_CONFIG;
   2771             }
   2772             BCM_IF_ERROR_RETURN(
   2773                 soc_tomahawk3_sched_profile_attach(unit, port, profile_id));
   2774             BCM_IF_ERROR_RETURN(
   2775                 soc_tomahawk3_l1_to_l0_profile_update_per_port(unit, port, profile_id));
   2776             BCM_IF_ERROR_RETURN(_bcm_th3_cosq_gport_tree_create(unit, port));
   2777             BCM_IF_ERROR_RETURN(soc_th3_pfc_config_profile_id_set(unit, port,
   2778                 socTH3PFCReceiveClass, profile_id));
   2779             break;
   2780         case bcmCosqProfilePGProperties:
   2781             if ((profile_id < 0) || (profile_id >=
   2782                         _BCM_TH3_NUM_PG_PROP_PROFILES)) {
   2783                 return BCM_E_PARAM;
   2784             }
   2785             BCM_IF_ERROR_RETURN(
   2786                 _bcm_th3_cosq_port_pg_profile_set(unit, port, profile_id));
   2787             break;
   2788         case bcmCosqProfileIntPriToPGMap:
   2789             if ((profile_id < 0) || (profile_id >=
   2790                         _BCM_TH3_NUM_INTPRI_PG_MAP_PROFILES)) {
   2791                 return BCM_E_PARAM;
   2792             }
   2793             BCM_IF_ERROR_RETURN(
   2794                 _bcm_th3_cosq_port_inp_pri_to_pg_profile_set(unit, port, profile_id));
   2795             break;
   2796         case bcmCosqProfileOobfcEgressQueueMap:
   2797             if ((profile_id < 0) || (profile_id >=
   2798                         _BCM_TH3_NUM_OOB_EGRQUEUE_MAP_PROFILES)) {
   2799                 return BCM_E_PARAM;
   2800             }
   2801             BCM_IF_ERROR_RETURN(
   2802                     bcm_th3_oob_fx_egress_profile_id_set(unit, port, profile_id));
   2803             break;
   2804         default:
   2805             return SOC_E_PARAM;
   2806             break;
   2807     }
   2808 
   2809     return SOC_E_NONE;
   2810 }
   2811 
   2812 
   2813 /*
   2814  * Function:
   2815  *     bcm_tomahawk3_cosq_port_profile_get
   2816  * Purpose:
   2817  *     Get Port to Profile Mapping for Cosq profiles
   2818  * Parameters:
   2819  *     unit         - (IN) unit number
   2820  *     port         - (IN) logical port
   2821  *     profile_type - (IN) Profile type
   2822  *     profile_id   - (OUT) profile id
   2823  * Returns:
   2824  *     BCM_E_XXX
   2825  */
   2826 int
   2827 bcm_tomahawk3_cosq_port_profile_get(int unit, bcm_port_t port,
   2828         bcm_cosq_profile_type_t profile_type, int *profile_id)
   2829 {
   2830     if (!SOC_PORT_VALID(unit, port)) {
   2831         return BCM_E_PORT;
   2832     }
   2833     if (profile_id == NULL) {
   2834         return BCM_E_PARAM;
   2835     }
   2836     switch (profile_type) {
   2837         case bcmCosqProfilePFCAndQueueHierarchy:
   2838             BCM_IF_ERROR_RETURN(
   2839                 soc_tomahawk3_sched_profile_get(unit, port, profile_id));
   2840             break;
   2841         case bcmCosqProfilePGProperties:
   2842             BCM_IF_ERROR_RETURN(
   2843                 _bcm_th3_cosq_port_pg_profile_get(unit, port, profile_id));
   2844             break;
   2845         case bcmCosqProfileIntPriToPGMap:
   2846             BCM_IF_ERROR_RETURN(
   2847                 _bcm_th3_cosq_port_inp_pri_to_pg_profile_get(unit, port, profile_id));
   2848             break;
   2849         case bcmCosqProfileOobfcEgressQueueMap:
   2850             BCM_IF_ERROR_RETURN(
   2851                     bcm_th3_oob_fx_egress_profile_id_get(unit, port, profile_id));
   2852             break;
   2853         default:
   2854             return SOC_E_PARAM;
   2855             break;
   2856     }
   2857 
   2858     return SOC_E_NONE;
   2859 }
   2860 
   2861 /*
   2862  * Function:
   2863  *     bcm_tomahawk3_cosq_profile_property_dynamic_get
   2864  * Purpose:
   2865  *     Query if a profile can be modified dynamically
   2866  * Parameters:
   2867  *     unit         - (IN) unit number
   2868  *     profile_type - (IN) Profile type
   2869  *     dynamic      - (OUT) Dynamic changeable type
   2870  * Returns:
   2871  *     BCM_E_XXX
   2872  */
   2873 int
   2874 bcm_tomahawk3_cosq_profile_property_dynamic_get(int unit,
   2875         bcm_cosq_profile_type_t profile_type, bcm_cosq_dynamic_setting_type_t
   2876         *dynamic)
   2877 {
   2878     if (dynamic == NULL) {
   2879         return BCM_E_PARAM;
   2880     }
   2881     switch (profile_type) {
   2882         case bcmCosqProfilePFCAndQueueHierarchy:
   2883             *dynamic = bcmCosqDynamicTypeConditional;
   2884             break;
   2885         case bcmCosqProfilePGProperties:
   2886             *dynamic = bcmCosqDynamicTypeFixed;
   2887             break;
   2888         case bcmCosqProfileIntPriToPGMap:
   2889             *dynamic = bcmCosqDynamicTypeFlexible;
   2890             break;
   2891         case bcmCosqProfileOobfcEgressQueueMap:
   2892             *dynamic = bcmCosqDynamicTypeConditional;
   2893             break;
   2894         default:
   2895             return SOC_E_PARAM;
   2896             break;
   2897     }
   2898 
   2899     return SOC_E_NONE;
   2900 }
   2901 
   2902 /*
   2903  * Function:
   2904  *     bcm_tomahawk3_cosq_profile_info_inuse_get
   2905  * Purpose:
   2906  *     Query if a profile id of a profile is in use
   2907  * Parameters:
   2908  *     unit         - (IN) unit number
   2909  *     profile_type - (IN) Profile type
   2910  *     profile_id   - (IN) Profile id
   2911  *     in_use      - (OUT) If a profile is in use
   2912  * Returns:
   2913  *     BCM_E_XXX
   2914  */
   2915 int
   2916 bcm_tomahawk3_cosq_profile_info_inuse_get(int unit,
   2917         bcm_cosq_profile_type_t profile_type, int profile_id, int *in_use)
   2918 {
   2919     int port, ret_profile = -1;
   2920     if (in_use == NULL) {
   2921         return BCM_E_PARAM;
   2922     }
   2923     switch (profile_type) {
   2924         case bcmCosqProfilePFCAndQueueHierarchy:
   2925             if ((profile_id < 0) || (profile_id >=
   2926                         _BCM_TH3_NUM_QSCHED_PROFILES)) {
   2927                 return BCM_E_PARAM;
   2928             }
   2929             break;
   2930         case bcmCosqProfilePGProperties:
   2931             if ((profile_id < 0) || (profile_id >=
   2932                         _BCM_TH3_NUM_PG_PROP_PROFILES)) {
   2933                 return BCM_E_PARAM;
   2934             }
   2935             break;
   2936         case bcmCosqProfileIntPriToPGMap:
   2937             if ((profile_id < 0) || (profile_id >=
   2938                         _BCM_TH3_NUM_INTPRI_PG_MAP_PROFILES)) {
   2939                 return BCM_E_PARAM;
   2940             }
   2941             break;
   2942         case bcmCosqProfileOobfcEgressQueueMap:
   2943             if ((profile_id < 0) || (profile_id >=
   2944                         _BCM_TH3_NUM_OOB_EGRQUEUE_MAP_PROFILES)) {
   2945                 return BCM_E_PARAM;
   2946             }
   2947             break;
   2948         default:
   2949             return BCM_E_PARAM;
   2950             break;
   2951     }
   2952     PBMP_ALL_ITER(unit, port) {
   2953         if (profile_type == bcmCosqProfilePFCAndQueueHierarchy) {
   2954             if (IS_CPU_PORT(unit, port)) {
   2955                 continue;
   2956             }
   2957         }
   2958         BCM_IF_ERROR_RETURN(
   2959             bcm_tomahawk3_cosq_port_profile_get(unit, port, profile_type,
   2960                                                             &ret_profile));
   2961         if (ret_profile == profile_id) {
   2962             *in_use = 1;
   2963             return BCM_E_NONE;
   2964         }
   2965     }
   2966     *in_use = 0;
   2967 
   2968     return BCM_E_NONE;
   2969 }
   2970 
   2971 /*
   2972  * Function:
   2973  *     bcm_tomahawk3_cosq_profile_info_portlist_get
   2974  * Purpose:
   2975  *     Query the list of ports using a specific profile
   2976  * Parameters:
   2977  *     unit         - (IN) unit number
   2978  *     profile_type - (IN) Profile type
   2979  *     profile_id   - (IN) Profile id
   2980  *     port_count   - (OUT) Number of ports using this profile
   2981  *     max_port_count - (OUT) Max Number of ports that can use this profile
   2982  *     port_list    - (OUT) List of ports using this profile
   2983  * Returns:
   2984  *     BCM_E_XXX
   2985  */
   2986 int
   2987 bcm_tomahawk3_cosq_profile_info_portlist_get(int unit,
   2988         bcm_cosq_profile_type_t profile_type, int profile_id, int max_port_count,
   2989          bcm_port_t *port_list, int *port_count)
   2990 {
   2991     int port, ret_profile = -1;
   2992     if (port_count == NULL || port_list == NULL) {
   2993         return BCM_E_PARAM;
   2994     }
   2995     if (max_port_count <= 0 || max_port_count > SOC_TH3_MAX_NUM_PORTS) {
   2996         return BCM_E_PARAM;
   2997     }
   2998     switch (profile_type) {
   2999         case bcmCosqProfilePFCAndQueueHierarchy:
   3000             if ((profile_id < 0) || (profile_id >=
   3001                         _BCM_TH3_NUM_QSCHED_PROFILES)) {
   3002                 return BCM_E_PARAM;
   3003             }
   3004             break;
   3005         case bcmCosqProfilePGProperties:
   3006             if ((profile_id < 0) || (profile_id >=
   3007                         _BCM_TH3_NUM_PG_PROP_PROFILES)) {
   3008                 return BCM_E_PARAM;
   3009             }
   3010             break;
   3011         case bcmCosqProfileIntPriToPGMap:
   3012             if ((profile_id < 0) || (profile_id >=
   3013                         _BCM_TH3_NUM_INTPRI_PG_MAP_PROFILES)) {
   3014                 return BCM_E_PARAM;
   3015             }
   3016             break;
   3017         case bcmCosqProfileOobfcEgressQueueMap:
   3018             if ((profile_id < 0) || (profile_id >=
   3019                         _BCM_TH3_NUM_OOB_EGRQUEUE_MAP_PROFILES)) {
   3020                 return BCM_E_PARAM;
   3021             }
   3022             break;
   3023         default:
   3024             return BCM_E_PARAM;
   3025             break;
   3026     }
   3027     *port_count = 0;
   3028     PBMP_ALL_ITER(unit, port) {
   3029         if (profile_type == bcmCosqProfilePFCAndQueueHierarchy) {
   3030             if (IS_CPU_PORT(unit, port)) {
   3031                 continue;
   3032             }
   3033         }
   3034         BCM_IF_ERROR_RETURN(
   3035             bcm_tomahawk3_cosq_port_profile_get(unit, port, profile_type,
   3036                                                             &ret_profile));
   3037         if (ret_profile == profile_id) {
   3038             port_list[(*port_count)++] = port;
   3039             if((*port_count) == max_port_count) {
   3040                 break;
   3041             }
   3042         }
   3043     }
   3044     return BCM_E_NONE;
   3045 }
   3046 
   3047 /*
   3048  * This function does two things:
   3049  * 1. Tests whether the corresponding COS_BMP bit is set or not.
   3050  * 2. Tests whether the queue corresponding to given cos is
   3051  *     mapped to correct L0 or not.
   3052  *
   3053  * L0.0 is associated with CMC0 CH1(Rx) (pci)
   3054  * L0.1 is associated with CMC0 CH2(Rx) (pci)
   3055  * L0.2 is associated with CMC0 CH3(Rx) (pci)
   3056  * L0.3 is associated with CMC0 CH4(Rx) (pci)
   3057  * L0.4 is associated with CMC0 CH5(Rx) (pci)
   3058  * L0.5 is associated with CMC0 CH6(Rx) (pci)
   3059  * L0.6 is associated with CMC0 CH7(Rx) (pci)
   3060  * L0.7 is associated with CMC1 CHx(Rx) (uc0)
   3061  * L0.8 is associated with CMC1 CHx(Rx) (uC1)
   3062  * L0.11 is reserved
   3063  */
   3064 int
   3065 bcm_th3_rx_queue_channel_set_test(int unit, bcm_cos_queue_t queue_id,
   3066                                   bcm_rx_chan_t chan_id)
   3067 {
   3068 #if defined(BCM_CMICX_SUPPORT)
   3069     if (soc_feature(unit, soc_feature_cmicx)) {
   3070         int pci_cmc = SOC_PCI_CMC(unit);
   3071         uint32 reg_val;
   3072         uint32 bit;
   3073         uint32 max_rx_channels = 0;
   3074         _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
   3075         bcm_gport_t cpu_l0_gport = -1;
   3076         bcm_gport_t parent_gport = -1;
   3077 
   3078         soc_dma_max_rx_channels_get(unit, &max_rx_channels);
   3079 
   3080         if ((chan_id <= 0) || (chan_id >= max_rx_channels)) {
   3081             return BCM_E_PARAM;
   3082         }
   3083 
   3084         if (_bcm_th3_cosq_cpu_port_info[unit] == NULL) {
   3085             return BCM_E_INIT;
   3086         }
   3087 
   3088         cpu_port_info = _bcm_th3_cosq_cpu_port_info[unit];
   3089 
   3090         if ((chan_id > 0) && (chan_id < 8 ))  {
   3091             cpu_l0_gport = cpu_port_info->sched[chan_id - 1].gport;
   3092         }
   3093 
   3094         if (queue_id < 0) { /* All COS Queues */
   3095             for (queue_id = 0; queue_id < NUM_CPU_COSQ(unit); queue_id++) {
   3096                 soc_dma_cos_ctrl_queue_get(unit, pci_cmc, chan_id, queue_id,
   3097                                            &reg_val);
   3098 
   3099                 bit = 1 << (queue_id % 32);
   3100                 if (reg_val & bit) {
   3101                     /* find the parent gport of this queue if parent gport is
   3102                      * not equal to l0 gport for this channel return error */
   3103                     parent_gport = cpu_port_info->mcast[queue_id].parent_gport;
   3104                     if (parent_gport != cpu_l0_gport) {
   3105                         return BCM_E_PARAM;
   3106                     }
   3107                 }
   3108             }
   3109         } else {
   3110             soc_dma_cos_ctrl_queue_get(unit, pci_cmc, chan_id, queue_id,
   3111                                        &reg_val);
   3112             bit = 1 << (queue_id % 32);
   3113             if (reg_val & bit) {
   3114                 /* find the parent gport of this queue if parent gport is not
   3115                  * equal to l0 gport for this channel return error */
   3116                 parent_gport = cpu_port_info->mcast[queue_id].parent_gport;
   3117                 if (parent_gport != cpu_l0_gport) {
   3118                     return BCM_E_PARAM;
   3119                 }
   3120             } else {
   3121                 return BCM_E_PARAM;
   3122             }
   3123         }
   3124     }
   3125 #endif /* BCM_CMICX_SUPPORT */
   3126 
   3127     return BCM_E_NONE;
   3128 }
   3129 
   3130 /*
   3131  * Function:
   3132  *     _bcm_th3_cosq_localport_resolve
   3133  * Purpose:
   3134  *     Resolve GPORT if it is a local port
   3135  * Parameters:
   3136  *     unit       - (IN) unit number
   3137  *     gport      - (IN) GPORT identifier
   3138  *     local_port - (OUT) local port number
   3139  * Returns:
   3140  *     BCM_E_XXX
   3141  */
   3142 int
   3143 _bcm_th3_cosq_localport_resolve(int unit, bcm_gport_t gport,
   3144                                bcm_port_t *local_port)
   3145 {
   3146     bcm_module_t module;
   3147     bcm_port_t port;
   3148     bcm_trunk_t trunk;
   3149     int id, result, rv;
   3150 
   3151     if (!BCM_GPORT_IS_SET(gport)) {
   3152         if (!SOC_PORT_VALID(unit, gport)) {
   3153             return BCM_E_PORT;
   3154         }
   3155         *local_port = gport;
   3156         return BCM_E_NONE;
   3157     }
   3158 
   3159     rv = _bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id);
   3160     if (rv == BCM_E_PORT) {
   3161         /* returning E_PARAM when invalid gport is given as param */
   3162         return BCM_E_PARAM;
   3163     } else if (BCM_FAILURE(rv)) {
   3164         return rv;
   3165     }
   3166 
   3167     BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result));
   3168     if (result == FALSE) {
   3169         return BCM_E_PARAM;
   3170     }
   3171 
   3172     *local_port = port;
   3173 
   3174     return BCM_E_NONE;
   3175 }
   3176 
   3177 int
   3178 _bcm_th3_cosq_egress_sp_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   3179                            int *p_pool_start, int *p_pool_end)
   3180 {
   3181     int local_port;
   3182     int pool;
   3183 
   3184     if (cosq == BCM_COS_INVALID) {
   3185         if (p_pool_start && p_pool_end) {
   3186             *p_pool_start = 0;
   3187             *p_pool_end = 3;
   3188             return BCM_E_NONE;
   3189         } else {
   3190             return BCM_E_PARAM;
   3191         }
   3192     }
   3193 
   3194     BCM_IF_ERROR_RETURN
   3195         (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   3196                                     _BCM_TH3_COSQ_INDEX_STYLE_EGR_POOL,
   3197                                     &local_port, &pool, NULL));
   3198 
   3199     if (p_pool_start) {
   3200         *p_pool_start = pool;
   3201     }
   3202     if (p_pool_end) {
   3203         *p_pool_end = pool;
   3204     }
   3205     return BCM_E_NONE;
   3206 }
   3207 
   3208 /*
   3209  * Function:
   3210  *     _bcm_th3_cosq_index_resolve
   3211  * Purpose:
   3212  *     Find hardware index for the given port/cosq
   3213  * Parameters:
   3214  *     unit       - (IN) unit number
   3215  *     port       - (IN) port number or GPORT identifier
   3216  *     cosq       - (IN) COS queue number
   3217  *     style      - (IN) index style (_BCM_KA_COSQ_INDEX_STYLE_XXX)
   3218  *     local_port - (OUT) local port number
   3219  *     index      - (OUT) result index
   3220  *     count      - (OUT) number of index
   3221  * Returns:
   3222  *     BCM_E_XXX
   3223  */
   3224 int
   3225 _bcm_th3_cosq_index_resolve(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   3226                            _bcm_th3_cosq_index_style_t style,
   3227                            bcm_port_t *local_port, int *index, int *count)
   3228 {
   3229     bcm_port_t resolved_port;
   3230     soc_info_t *si;
   3231     int resolved_index = -1;
   3232     int id, startq, numq = 0;
   3233     int num_uc_q, num_mc_q;
   3234     int pipe;
   3235     int uc_base = 0, mc_base = 0, cpu_mc_base = 0; /* Q base number */
   3236     int chip_mmu_port; /* chip_port_num*/
   3237     _bcm_th3_cosq_node_t *node;
   3238     uint32 entry[SOC_MAX_MEM_WORDS];
   3239     soc_mem_t mem;
   3240 
   3241     si = &SOC_INFO(unit);
   3242 
   3243     if (cosq < -1) {
   3244         return BCM_E_PARAM;
   3245     } else if (cosq == -1) {
   3246         startq = 0;
   3247         numq = _TH3_NUM_COS(unit);
   3248     } else {
   3249         startq = cosq;
   3250         numq = 1;
   3251     }
   3252 
   3253     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   3254         BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   3255         BCM_GPORT_IS_SCHEDULER(port)) {
   3256         BCM_IF_ERROR_RETURN
   3257             (_bcm_th3_cosq_node_get(unit, port, NULL, &resolved_port, &id,
   3258                                    &node));
   3259         if (resolved_port < 0) {
   3260             return BCM_E_PORT;
   3261         }
   3262     } else {
   3263         BCM_IF_ERROR_RETURN
   3264             (_bcm_th3_cosq_localport_resolve(unit, port, &resolved_port));
   3265         if (resolved_port < 0) {
   3266             return BCM_E_PORT;
   3267         }
   3268         node = NULL;
   3269         numq = (IS_CPU_PORT(unit, resolved_port)) ? NUM_CPU_COSQ(unit) : _BCM_TH3_COS_MAX;
   3270     }
   3271     num_uc_q = _bcm_th3_get_num_ucq(unit);
   3272     num_mc_q = _bcm_th3_get_num_mcq(unit);
   3273     mc_base = si->port_cosq_base[resolved_port];
   3274     uc_base = si->port_uc_cosq_base[resolved_port];
   3275 
   3276     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, resolved_port, &pipe));
   3277 
   3278     switch (style) {
   3279         case _BCM_TH3_COSQ_INDEX_STYLE_WRED_DEVICE:
   3280             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3281                 return BCM_E_PARAM;
   3282             }
   3283             if ((port == -1) || (cosq == -1)) {
   3284                 numq = _TH3_MMU_NUM_POOL; /* 4 Global Service Pools */
   3285                 resolved_index = 0;
   3286             } else {
   3287                 BCM_IF_ERROR_RETURN
   3288                     (_bcm_th3_cosq_egress_sp_get(unit, port, cosq,
   3289                                                 &resolved_index,
   3290                                                 NULL));
   3291                 numq = 1;
   3292                 resolved_index += 0;
   3293             }
   3294             break;
   3295         case _BCM_TH3_COSQ_INDEX_STYLE_WRED_PORT:
   3296             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3297                 return BCM_E_PARAM;
   3298             }
   3299             resolved_index = 0;
   3300             if (cosq != -1) {
   3301                 BCM_IF_ERROR_RETURN
   3302                     (_bcm_th3_cosq_egress_sp_get(unit, port, cosq,
   3303                                                 &resolved_index,
   3304                                                 NULL));
   3305             }
   3306             chip_mmu_port = SOC_TH3_MMU_CHIP_PORT(unit, resolved_port);
   3307             resolved_index += (chip_mmu_port * 4); /* resolved_index is chip_port_num, spid.*/
   3308             numq = (cosq == -1) ? 4: 1;
   3309             break;
   3310         case _BCM_TH3_COSQ_INDEX_STYLE_WRED_QUEUE:
   3311             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3312                 return BCM_E_PARAM;
   3313             }
   3314             /* resolved_index = local_mmu_port *  _BCM_TH3_MAX_QUEUE_PER_PORT; */
   3315             resolved_index = uc_base;
   3316             if (cosq != -1) {
   3317                 if (cosq >= _bcm_th3_get_num_ucq(unit)) { /* WRED is only for UCQ*/
   3318                     return BCM_E_PARAM;
   3319                 }
   3320                 resolved_index += cosq;
   3321             }
   3322             numq = (cosq == -1) ? _bcm_th3_get_num_ucq(unit): 1;
   3323             break;
   3324         case _BCM_TH3_COSQ_INDEX_STYLE_EGR_POOL:
   3325             if ((node != NULL) && (!BCM_GPORT_IS_MODPORT(port))) {
   3326                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   3327                     /* regular unicast queue */
   3328                     resolved_index = (uc_base + (node->hw_index %
   3329                                        num_uc_q));
   3330                     mem = MMU_THDO_Q_TO_QGRP_MAPD0m;
   3331                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3332                     if (IS_CPU_PORT(unit, resolved_port)) {
   3333                         cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   3334                         resolved_index = cpu_mc_base +
   3335                                          ((node->hw_index - cpu_mc_base) %
   3336                                            _BCM_TH3_NUM_CPU_MCAST_QUEUE);
   3337                     } else {
   3338                         resolved_index = (mc_base + (node->hw_index %
   3339                                            num_mc_q));
   3340                     }
   3341                     mem = MMU_THDO_Q_TO_QGRP_MAPD0m;
   3342                 } else { /* scheduler */
   3343                     return BCM_E_PARAM;
   3344                 }
   3345             } else { /* node == NULL */
   3346                 numq = si->port_num_cosq[resolved_port] +
   3347                        si->port_num_uc_cosq[resolved_port];
   3348                 if (startq >= numq) {
   3349                     return BCM_E_PARAM;
   3350                 }
   3351                 resolved_index = (IS_CPU_PORT(unit, resolved_port) ? mc_base : uc_base) + startq;
   3352                 mem = MMU_THDO_Q_TO_QGRP_MAPD0m;
   3353             }
   3354             SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, resolved_index,
   3355                                 entry));
   3356             resolved_index = soc_mem_field32_get(unit, mem, entry, SPIDf);
   3357             break;
   3358         case _BCM_TH3_COSQ_INDEX_STYLE_COS:
   3359             if (node) {
   3360                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   3361                      resolved_index = node->hw_index % num_uc_q;
   3362                 } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3363                      if (IS_CPU_PORT(unit, resolved_port)) {
   3364                          cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   3365                          resolved_index = (node->hw_index - cpu_mc_base) %
   3366                                           NUM_CPU_COSQ(unit);
   3367                      } else {
   3368                          resolved_index = node->hw_index % num_mc_q;
   3369                      }
   3370                 } else {
   3371                      resolved_index = node->hw_index %
   3372                                       _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   3373                 }
   3374             } else {
   3375                 resolved_index = startq;
   3376             }
   3377             break;
   3378         case _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE:
   3379             /* Return hw_index for given unicast queue gport */
   3380             if (node) {
   3381                 if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port)) {
   3382                      resolved_index = (uc_base + (node->hw_index % num_uc_q));
   3383                 } else {
   3384                     return BCM_E_PARAM;
   3385                 }
   3386             } else {
   3387                 if (IS_CPU_PORT(unit, resolved_port)) {
   3388                     return BCM_E_PARAM;
   3389                 }
   3390                 if (startq >= num_uc_q) {
   3391                     return BCM_E_PARAM;
   3392                 }
   3393                 resolved_index = uc_base + startq;
   3394             }
   3395             break;
   3396         case _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE:
   3397             /* Return hw_index for given multicast queue gport */
   3398             if (node) {
   3399                 if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(port)) {
   3400                      if (IS_CPU_PORT(unit, resolved_port)) {
   3401                          cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   3402                          resolved_index = cpu_mc_base +
   3403                                           ((node->hw_index - cpu_mc_base) %
   3404                                               _BCM_TH3_NUM_CPU_MCAST_QUEUE);
   3405                      } else {
   3406                          resolved_index = (mc_base + (node->hw_index % num_mc_q));
   3407                      }
   3408                 } else {
   3409                     return BCM_E_PARAM;
   3410                 }
   3411             } else {
   3412                 if (IS_CPU_PORT(unit, resolved_port)) {
   3413                     if (startq >= numq) {
   3414                         return BCM_E_PARAM;
   3415                     }
   3416                     resolved_index = mc_base + startq;
   3417                 } else {
   3418                     if ((startq < num_uc_q) || (startq >= numq)) {
   3419                         return BCM_E_PARAM;
   3420                     }
   3421                     resolved_index = mc_base + (startq - num_uc_q);
   3422                 }
   3423             }
   3424             break;
   3425         default:
   3426             return BCM_E_PARAM;
   3427     }
   3428 
   3429     if (index) {
   3430         *index = resolved_index;
   3431     }
   3432     if (local_port) {
   3433         *local_port = resolved_port;
   3434     }
   3435     if (count) {
   3436         *count = (cosq == -1) ? numq : 1;
   3437     }
   3438 
   3439     return BCM_E_NONE;
   3440 }
   3441 
   3442 
   3443 /*
   3444  * Function:
   3445  *     _bcm_th3_cosq_mapping_set
   3446  * Purpose:
   3447  *     Set COS queue for the specified priority of an ingress port
   3448  * Parameters:
   3449  *     unit     - (IN) unit number
   3450  *     ing_port - (IN) ingress port
   3451  *     gport    - (IN) queue group GPORT identifier
   3452  *     priority - (IN) priority value to map
   3453  *     flags    - (IN) BCM_COSQ_GPORT_XXX_QUEUE_GROUP
   3454  *     gport    - (IN) queue group GPORT identifier
   3455  *     cosq     - (IN) COS queue number
   3456  * Returns:
   3457  *     BCM_E_XXX
   3458  */
   3459 int
   3460 _bcm_th3_cosq_mapping_set(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   3461                          uint32 flags, bcm_gport_t gport, bcm_cos_queue_t cosq1,
   3462                          bcm_cos_queue_t cosq2)
   3463 {
   3464     bcm_port_t local_port, out_port;
   3465     bcm_cos_queue_t hw_cosq[3];
   3466     int rv, idx;
   3467     soc_field_t field[3] = {INVALIDf, INVALIDf, INVALIDf}; /* [0]:UC, [1]:MC cos */
   3468     void *entries[1];
   3469     cos_map_sel_entry_t cos_map_sel_entry;
   3470     port_cos_map_entry_t cos_map_entries[_TH3_MMU_NUM_INT_PRI];
   3471     uint32 old_index, new_index;
   3472     int num_ucq, num_mcq;
   3473 
   3474     num_ucq = _bcm_th3_get_num_ucq(unit);
   3475     num_mcq = _bcm_th3_get_num_mcq(unit);
   3476 
   3477     BCM_IF_ERROR_RETURN
   3478         (_bcm_th3_cosq_localport_resolve(unit, ing_port, &local_port));
   3479 
   3480     if (gport != -1) {
   3481         BCM_IF_ERROR_RETURN(_bcm_th3_cosq_localport_resolve(unit, gport,
   3482                                                            &out_port));
   3483     }
   3484 
   3485     switch (flags) {
   3486         case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   3487             if (gport == -1) {
   3488                 hw_cosq[0] = cosq1;
   3489             } else {
   3490                 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   3491                     return BCM_E_PARAM;
   3492                 }
   3493                 BCM_IF_ERROR_RETURN
   3494                     (_bcm_th3_cosq_index_resolve
   3495                      (unit, gport, cosq1, _BCM_TH3_COSQ_INDEX_STYLE_COS,
   3496                       NULL, &hw_cosq[0], NULL));
   3497             }
   3498             hw_cosq[0] %= num_ucq;
   3499             field[0] = UC_COS1f;
   3500             break;
   3501         case BCM_COSQ_GPORT_ELEPHANT_UCAST_QUEUE_GROUP:
   3502             if (gport == -1) {
   3503                 hw_cosq[0] = cosq1;
   3504             } else {
   3505                 if (!BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   3506                     return BCM_E_PARAM;
   3507                 }
   3508                 BCM_IF_ERROR_RETURN
   3509                     (_bcm_th3_cosq_index_resolve
   3510                      (unit, gport, cosq1, _BCM_TH3_COSQ_INDEX_STYLE_COS,
   3511                       NULL, &hw_cosq[0], NULL));
   3512             }
   3513             hw_cosq[0] %= num_ucq;
   3514             field[0] = UC_COS2f;
   3515             break;
   3516         case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   3517             if (gport == -1) {
   3518                 hw_cosq[0] = cosq1;
   3519             } else {
   3520                 if (!BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   3521                     return BCM_E_PARAM;
   3522                 }
   3523                 BCM_IF_ERROR_RETURN
   3524                     (_bcm_th3_cosq_index_resolve
   3525                      (unit, gport, cosq1, _BCM_TH3_COSQ_INDEX_STYLE_COS,
   3526                       NULL, &hw_cosq[0], NULL));
   3527             }
   3528             hw_cosq[0] %= num_mcq;
   3529             field[0] = MC_COS1f;
   3530             break;
   3531         case (BCM_COSQ_GPORT_UCAST_QUEUE_GROUP |
   3532               BCM_COSQ_GPORT_MCAST_QUEUE_GROUP):
   3533             if (gport == -1) {
   3534                 hw_cosq[0] = cosq1;
   3535                 hw_cosq[1] = cosq2;
   3536             } else {
   3537                 return BCM_E_PARAM;
   3538             }
   3539             /*
   3540             hw_cosq[0] %= _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   3541             hw_cosq[1] %= _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   3542             hw_cosq[2] %= _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   3543             */
   3544             hw_cosq[0] = MIN(hw_cosq[0], num_ucq - 1);
   3545             hw_cosq[1] = MIN(hw_cosq[1], num_mcq ? num_mcq - 1 : 0);
   3546             field[0] = UC_COS1f;
   3547             field[1] = MC_COS1f;
   3548             break;
   3549         default:
   3550             return BCM_E_PARAM;
   3551     }
   3552 
   3553     entries[0] = &cos_map_entries;
   3554 
   3555     BCM_IF_ERROR_RETURN
   3556         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   3557                            &cos_map_sel_entry));
   3558     old_index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   3559                                     SELECTf);
   3560     old_index *= _TH3_MMU_NUM_INT_PRI;
   3561 
   3562     BCM_IF_ERROR_RETURN
   3563         (soc_profile_mem_get(unit, _bcm_th3_cos_map_profile[unit],
   3564                              old_index, _TH3_MMU_NUM_INT_PRI, entries));
   3565 
   3566     for (idx = 0; idx < 3; idx++) {
   3567         if (field[idx] != INVALIDf) {
   3568             soc_mem_field32_set(unit, PORT_COS_MAPm,
   3569                                 &cos_map_entries[priority],
   3570                                 field[idx], hw_cosq[idx]);
   3571         }
   3572     }
   3573 
   3574     soc_mem_lock(unit, PORT_COS_MAPm);
   3575 
   3576     rv = soc_profile_mem_delete(unit, _bcm_th3_cos_map_profile[unit],
   3577                                 old_index);
   3578     if (BCM_FAILURE(rv)) {
   3579         soc_mem_unlock(unit, PORT_COS_MAPm);
   3580         return rv;
   3581     }
   3582 
   3583     rv = soc_profile_mem_add(unit, _bcm_th3_cos_map_profile[unit], entries,
   3584                              _TH3_MMU_NUM_INT_PRI, &new_index);
   3585 
   3586     soc_mem_unlock(unit, PORT_COS_MAPm);
   3587 
   3588     if (BCM_FAILURE(rv)) {
   3589         return rv;
   3590     }
   3591     soc_mem_field32_set(unit, COS_MAP_SELm, &cos_map_sel_entry, SELECTf,
   3592                         new_index / _TH3_MMU_NUM_INT_PRI);
   3593     BCM_IF_ERROR_RETURN
   3594         (WRITE_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   3595                             &cos_map_sel_entry));
   3596 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   3597     if (IS_CPU_PORT(unit, local_port)) {
   3598         BCM_IF_ERROR_RETURN
   3599             (soc_mem_field32_modify(unit, COS_MAP_SELm,
   3600                                     SOC_INFO(unit).cpu_hg_index, SELECTf,
   3601                                     new_index / _TH3_MMU_NUM_INT_PRI));
   3602     }
   3603 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   3604 
   3605     return BCM_E_NONE;
   3606 }
   3607 
   3608 /*
   3609  * Function:
   3610  *     bcm_th3_cosq_mapping_set
   3611  * Purpose:
   3612  *     Set which cosq a given priority should fall into
   3613  * Parameters:
   3614  *     unit     - (IN) unit number
   3615  *     gport    - (IN) queue group GPORT identifier
   3616  *     priority - (IN) priority value to map
   3617  *     cosq     - (IN) COS queue to map to
   3618  * Returns:
   3619  *     BCM_E_XXX
   3620  */
   3621 
   3622 int
   3623 bcm_th3_cosq_mapping_set(int unit, bcm_port_t port, bcm_cos_t priority,
   3624                         bcm_cos_queue_t cosq)
   3625 {
   3626     bcm_pbmp_t pbmp;
   3627     bcm_port_t local_port;
   3628 
   3629     BCM_PBMP_CLEAR(pbmp);
   3630 
   3631     if ((priority < 0) || (priority >= _TH3_MMU_NUM_INT_PRI)) {
   3632         return BCM_E_PARAM;
   3633     }
   3634 
   3635     if (cosq < 0) {
   3636         return BCM_E_PARAM;
   3637     }
   3638 
   3639     if (port == -1) {
   3640         /* port value of -1 will cause the cosq mapping set for
   3641            all types of local ports except Loopback ports.
   3642            So we do the sanity check of cos value with Default Number
   3643            of COS */
   3644         if (cosq >= _TH3_NUM_COS(unit)) {
   3645             return BCM_E_PARAM;
   3646         }
   3647         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   3648     } else {
   3649         if (BCM_GPORT_IS_SET(port)) {
   3650             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   3651                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   3652                 BCM_GPORT_IS_SCHEDULER(port)) {
   3653                 return BCM_E_PARAM;
   3654             } else if (BCM_GPORT_IS_LOCAL(port)) {
   3655                 local_port = BCM_GPORT_LOCAL_GET(port);
   3656             } else if (BCM_GPORT_IS_MODPORT(port)) {
   3657                 BCM_IF_ERROR_RETURN(
   3658                     bcm_esw_port_local_get(unit, port, &local_port));
   3659             } else {
   3660                 return BCM_E_PARAM;
   3661             }
   3662         } else {
   3663             local_port = port;
   3664         }
   3665 
   3666         if (!SOC_PORT_VALID(unit, local_port)) {
   3667             return BCM_E_PORT;
   3668         }
   3669 
   3670         BCM_PBMP_PORT_ADD(pbmp, local_port);
   3671         if (cosq >= _TH3_PORT_NUM_COS(unit, local_port)) {
   3672             return BCM_E_PARAM;
   3673         }
   3674     }
   3675 
   3676     PBMP_ITER(pbmp, local_port) {
   3677         if (IS_LB_PORT(unit, local_port)) {
   3678             continue;
   3679         }
   3680 
   3681         /* If no ETS/gport, map the int prio symmetrically for ucast and
   3682          * mcast */
   3683         BCM_IF_ERROR_RETURN
   3684             (_bcm_th3_cosq_mapping_set(unit, local_port,
   3685                                       priority,
   3686                                       BCM_COSQ_GPORT_UCAST_QUEUE_GROUP |
   3687                                       BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   3688                                       -1, cosq, cosq));
   3689     }
   3690 
   3691     return BCM_E_NONE;
   3692 }
   3693 
   3694 
   3695 /*
   3696  * Function:
   3697  *     _bcm_th3_cosq_mapping_get
   3698  * Purpose:
   3699  *     Determine which COS queue a given priority currently maps to.
   3700  * Parameters:
   3701  *     unit     - (IN) unit number
   3702  *     gport    - (IN) queue group GPORT identifier
   3703  *     priority - (IN) priority value to map
   3704  *     cosq     - (OUT) COS queue to map to
   3705  * Returns:
   3706  *     BCM_E_XXX
   3707  */
   3708 int
   3709 _bcm_th3_cosq_mapping_get(int unit, bcm_port_t ing_port, bcm_cos_t priority,
   3710                          uint32 flags, bcm_gport_t *gport,
   3711                          bcm_cos_queue_t *cosq)
   3712 {
   3713     bcm_port_t local_port;
   3714     cos_map_sel_entry_t cos_map_sel_entry;
   3715     _bcm_th3_cosq_port_info_t *port_info = NULL;
   3716     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
   3717     _bcm_th3_cosq_node_t *node;
   3718     int ii, index, cosq_base = 0;
   3719     void *entry_p;
   3720     bcm_cos_queue_t hw_cosq = BCM_COS_INVALID, node_cosq = BCM_COS_INVALID;
   3721     int numq = -1;
   3722     soc_info_t *si = &SOC_INFO(unit);
   3723     int num_ucq, num_mcq;
   3724 
   3725     if ((flags != BCM_COSQ_GPORT_UCAST_QUEUE_GROUP) &&
   3726         (flags != BCM_COSQ_GPORT_MCAST_QUEUE_GROUP) &&
   3727         (flags != BCM_COSQ_GPORT_ELEPHANT_UCAST_QUEUE_GROUP)) {
   3728         return BCM_E_PARAM;
   3729     }
   3730 
   3731     num_ucq = _bcm_th3_get_num_ucq(unit);
   3732     num_mcq = _bcm_th3_get_num_mcq(unit);
   3733 
   3734     BCM_IF_ERROR_RETURN
   3735         (_bcm_th3_cosq_localport_resolve(unit, ing_port, &local_port));
   3736 
   3737     if (gport) {
   3738         *gport = BCM_GPORT_INVALID;
   3739     }
   3740 
   3741     *cosq = BCM_COS_INVALID;
   3742 
   3743     BCM_IF_ERROR_RETURN
   3744         (READ_COS_MAP_SELm(unit, MEM_BLOCK_ANY, local_port,
   3745                            &cos_map_sel_entry));
   3746     index = soc_mem_field32_get(unit, COS_MAP_SELm, &cos_map_sel_entry,
   3747                                 SELECTf);
   3748     index *= _TH3_MMU_NUM_INT_PRI;
   3749 
   3750     entry_p = SOC_PROFILE_MEM_ENTRY(unit, _bcm_th3_cos_map_profile[unit],
   3751                                     port_cos_map_entry_t *,
   3752                                     index + priority);
   3753     if (IS_CPU_PORT(unit, local_port)) {
   3754         cpu_port_info = &_bcm_th3_cosq_cpu_port_info[unit][local_port];
   3755     } else {
   3756         port_info = &_bcm_th3_cosq_port_info[unit][local_port];
   3757     }
   3758 
   3759     switch (flags) {
   3760         case BCM_COSQ_GPORT_UCAST_QUEUE_GROUP:
   3761             hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p,
   3762                                           UC_COS1f);
   3763             if ((IS_CPU_PORT(unit, local_port) == FALSE) && (gport)) {
   3764                 for (ii = 0; ii < num_ucq; ii++) {
   3765                     node = &port_info->ucast[ii];
   3766                     if (node == NULL) {
   3767                         return BCM_E_NOT_FOUND;
   3768                     }
   3769                     node_cosq = (node->hw_index % num_ucq);
   3770                     if (node && (node_cosq == hw_cosq)) {
   3771                         *gport = node->gport;
   3772                         *cosq = hw_cosq;
   3773                         break;
   3774                     }
   3775                 }
   3776             } else {
   3777                 *cosq = hw_cosq;
   3778             }
   3779             break;
   3780         case BCM_COSQ_GPORT_ELEPHANT_UCAST_QUEUE_GROUP:
   3781             hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p,
   3782                                           UC_COS2f);
   3783             if ((IS_CPU_PORT(unit, local_port) == FALSE) && (gport)) {
   3784                 for (ii = 0; ii < num_ucq; ii++) {
   3785                     node = &port_info->ucast[ii];
   3786                     if (node == NULL) {
   3787                         return BCM_E_NOT_FOUND;
   3788                     }
   3789                     node_cosq = (node->hw_index % num_ucq);
   3790                     if (node && (node_cosq == hw_cosq)) {
   3791                         *gport = node->gport;
   3792                         *cosq = hw_cosq;
   3793                         break;
   3794                     }
   3795                 }
   3796             } else {
   3797                 *cosq = hw_cosq;
   3798             }
   3799             break;
   3800         case BCM_COSQ_GPORT_MCAST_QUEUE_GROUP:
   3801             hw_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p,
   3802                                           MC_COS1f);
   3803             if (gport) {
   3804                 if (IS_CPU_PORT(unit, local_port)) {
   3805                     numq = _BCM_TH3_NUM_CPU_MCAST_QUEUE;
   3806                     cosq_base = si->port_cosq_base[CMIC_PORT(unit)];
   3807                 } else {
   3808                     numq = num_mcq;
   3809                     cosq_base = 0;
   3810                 }
   3811                 for (ii = 0; ii < numq; ii++) {
   3812                     if (IS_CPU_PORT(unit, local_port)) {
   3813                         node = &cpu_port_info->mcast[ii];
   3814                     } else {
   3815                         node = &port_info->mcast[ii];
   3816                     }
   3817                     if (!node) {
   3818                         return BCM_E_NOT_FOUND;
   3819                     }
   3820                     node_cosq = ((node->hw_index - cosq_base) % numq);
   3821                     if (node_cosq == hw_cosq) {
   3822                         *gport = node->gport;
   3823                         *cosq = hw_cosq;
   3824                         break;
   3825                     }
   3826                 }
   3827             } else {
   3828                 *cosq = hw_cosq;
   3829             }
   3830             break;
   3831         /*
   3832          * COVERITY
   3833          *
   3834          * This default is unreachable. It is kept intentionally
   3835          * as a defensive default for future development.
   3836          */
   3837         /* coverity[dead_error_begin] */
   3838         default:
   3839             return BCM_E_PARAM;
   3840     }
   3841     if (((gport &&
   3842         (*gport == BCM_GPORT_INVALID) && (*cosq == BCM_COS_INVALID))) ||
   3843         (*cosq == BCM_COS_INVALID)) {
   3844         return BCM_E_NOT_FOUND;
   3845     }
   3846 
   3847     return BCM_E_NONE;
   3848 }
   3849 
   3850 /*
   3851  * Function:
   3852  *     bcm_th3_cosq_mapping_get
   3853  * Purpose:
   3854  *     Determine which COS queue a given priority currently maps to.
   3855  * Parameters:
   3856  *     unit     - (IN) unit number
   3857  *     gport    - (IN) queue group GPORT identifier
   3858  *     priority - (IN) priority value to map
   3859  *     cosq     - (OUT) COS queue to map to
   3860  * Returns:
   3861  *     BCM_E_XXX
   3862  */
   3863 int
   3864 bcm_th3_cosq_mapping_get(int unit, bcm_port_t port, bcm_cos_t priority,
   3865                         bcm_cos_queue_t *cosq)
   3866 {
   3867     bcm_port_t local_port;
   3868     bcm_pbmp_t pbmp;
   3869 
   3870     if ((priority < 0) || (priority >= _TH3_MMU_NUM_INT_PRI)) {
   3871         return BCM_E_PARAM;
   3872     }
   3873 
   3874     BCM_PBMP_CLEAR(pbmp);
   3875 
   3876     if (port == -1) {
   3877         BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   3878     } else {
   3879         if (BCM_GPORT_IS_SET(port)) {
   3880             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   3881                 BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   3882                 BCM_GPORT_IS_SCHEDULER(port)) {
   3883                 return BCM_E_PARAM;
   3884             } else if (BCM_GPORT_IS_LOCAL(port)) {
   3885                 local_port = BCM_GPORT_LOCAL_GET(port);
   3886             } else if (BCM_GPORT_IS_MODPORT(port)) {
   3887                 BCM_IF_ERROR_RETURN
   3888                     (bcm_esw_port_local_get(unit, port, &local_port));
   3889             } else {
   3890                 return BCM_E_PARAM;
   3891             }
   3892         } else {
   3893             local_port = port;
   3894         }
   3895 
   3896         if (!SOC_PORT_VALID(unit, local_port)) {
   3897             return BCM_E_PORT;
   3898         }
   3899 
   3900         BCM_PBMP_PORT_ADD(pbmp, local_port);
   3901     }
   3902 
   3903     PBMP_ITER(pbmp, local_port) {
   3904         if (IS_LB_PORT(unit, local_port) || IS_CPU_PORT(unit, local_port)) {
   3905             continue;
   3906         }
   3907 
   3908         BCM_IF_ERROR_RETURN(_bcm_th3_cosq_mapping_get(unit, local_port,
   3909                  priority, BCM_COSQ_GPORT_UCAST_QUEUE_GROUP, NULL, cosq));
   3910         break;
   3911     }
   3912     return BCM_E_NONE;
   3913 }
   3914 
   3915 
   3916 /*
   3917  * This function is used to set shared pool
   3918  * for given Ingress [Port, Priority_group]
   3919  */
   3920 int
   3921 _bcm_th3_cosq_ingress_sp_set_by_pg(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp,
   3922                             int arg)
   3923 {
   3924     int local_port;
   3925     uint64 rval;
   3926     int profile_index;
   3927     static const soc_field_t prigroup_spid_field[] = {
   3928         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   3929         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   3930     };
   3931 
   3932     BCM_IF_ERROR_RETURN
   3933             (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   3934 
   3935     if (!SOC_PORT_VALID(unit, local_port)) {
   3936         return BCM_E_PORT;
   3937     }
   3938 
   3939     if ((pri_grp < 0) || (pri_grp >= SOC_MMU_CFG_PRI_GROUP_MAX)) {
   3940         return BCM_E_PARAM;
   3941     }
   3942 
   3943     COMPILER_64_ZERO(rval);
   3944     SOC_IF_ERROR_RETURN
   3945         (soc_reg_get(unit, MMU_THDI_ING_PORT_CONFIGr, local_port, -1, &rval));
   3946 
   3947     profile_index = soc_reg64_field32_get(unit, MMU_THDI_ING_PORT_CONFIGr, rval, PG_PROFILE_SELf);
   3948 
   3949     COMPILER_64_ZERO(rval);
   3950     SOC_IF_ERROR_RETURN
   3951         (soc_reg64_get(unit, MMU_THDI_PG_PROFILEr, REG_PORT_ANY, profile_index, &rval));
   3952     soc_reg64_field32_set(unit, MMU_THDI_PG_PROFILEr, &rval, prigroup_spid_field[pri_grp], arg);
   3953     SOC_IF_ERROR_RETURN
   3954         (soc_reg64_set(unit, MMU_THDI_PG_PROFILEr, REG_PORT_ANY, profile_index, rval));
   3955 
   3956 
   3957     return BCM_E_NONE;
   3958 }
   3959 
   3960 /*
   3961  * This function sets the shared limit in mmu info
   3962 */
   3963 int _bcm_th3_mmu_set_shared_size(int unit, int itm, int shd_size)
   3964 {
   3965     _BCM_TH3_MMU_INFO(unit)->shared_limit[itm] = shd_size;
   3966     return BCM_E_NONE;
   3967 }
   3968 
   3969 /*
   3970  * This function retrieves the shared limit in mmu info
   3971  */
   3972 int _bcm_th3_mmu_get_shared_size(int unit, int itm, int *shd_size)
   3973 {
   3974     *shd_size = _BCM_TH3_MMU_INFO(unit)->shared_limit[itm];
   3975     return BCM_E_NONE;
   3976 }
   3977 
   3978 
   3979 /*
   3980  * This function is used to set headroom pool
   3981  * for given Ingress [Port, Priority_group]
   3982  */
   3983 int
   3984 _bcm_th3_cosq_ingress_hdrm_pool_set_by_pg(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp,
   3985                             int arg)
   3986 {
   3987     int local_port;
   3988     uint64 rval;
   3989     int profile_index;
   3990     static const soc_field_t prigroup_hpid_field[] = {
   3991         PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf,
   3992         PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf
   3993     };
   3994 
   3995     BCM_IF_ERROR_RETURN
   3996             (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   3997 
   3998     if (!SOC_PORT_VALID(unit, local_port)) {
   3999         return BCM_E_PORT;
   4000     }
   4001 
   4002     if ((pri_grp < 0) || (pri_grp >= SOC_MMU_CFG_PRI_GROUP_MAX)) {
   4003         return BCM_E_PARAM;
   4004     }
   4005 
   4006     COMPILER_64_ZERO(rval);
   4007     SOC_IF_ERROR_RETURN
   4008         (soc_reg_get(unit, MMU_THDI_ING_PORT_CONFIGr, local_port, -1, &rval));
   4009 
   4010     profile_index = soc_reg64_field32_get(unit, MMU_THDI_ING_PORT_CONFIGr, rval, PG_PROFILE_SELf);
   4011 
   4012     COMPILER_64_ZERO(rval);
   4013     SOC_IF_ERROR_RETURN
   4014         (soc_reg64_get(unit, MMU_THDI_PG_PROFILEr, REG_PORT_ANY, profile_index, &rval));
   4015     soc_reg64_field32_set(unit, MMU_THDI_PG_PROFILEr, &rval, prigroup_hpid_field[pri_grp], arg);
   4016     SOC_IF_ERROR_RETURN
   4017         (soc_reg64_set(unit, MMU_THDI_PG_PROFILEr, REG_PORT_ANY, profile_index, rval));
   4018 
   4019 
   4020     return BCM_E_NONE;
   4021 }
   4022 
   4023 
   4024 /*
   4025  * This function is used to get shared pool
   4026  * for given Ingress [Port, Priority_group]
   4027  */
   4028 int
   4029 _bcm_th3_cosq_ingress_sp_get_by_pg(int unit, bcm_gport_t gport, bcm_cos_queue_t pri_grp,
   4030                             int *arg)
   4031 {
   4032     int local_port;
   4033     uint64 rval;
   4034     int profile_index;
   4035     static const soc_field_t prigroup_spid_field[] = {
   4036         PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf,
   4037         PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf
   4038     };
   4039 
   4040     BCM_IF_ERROR_RETURN
   4041             (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   4042 
   4043     if (!SOC_PORT_VALID(unit, local_port)) {
   4044         return BCM_E_PORT;
   4045     }
   4046 
   4047     if ((pri_grp < 0) || (pri_grp >= SOC_MMU_CFG_PRI_GROUP_MAX)) {
   4048         return BCM_E_PARAM;
   4049     }
   4050 
   4051     COMPILER_64_ZERO(rval);
   4052     SOC_IF_ERROR_RETURN
   4053         (soc_reg_get(unit, MMU_THDI_ING_PORT_CONFIGr, local_port, -1, &rval));
   4054 
   4055     profile_index = soc_reg64_field32_get(unit, MMU_THDI_ING_PORT_CONFIGr, rval, PG_PROFILE_SELf);
   4056 
   4057     COMPILER_64_ZERO(rval);
   4058     SOC_IF_ERROR_RETURN
   4059         (soc_reg64_get(unit, MMU_THDI_PG_PROFILEr, REG_PORT_ANY, profile_index, &rval));
   4060     *arg = soc_reg64_field32_get(unit, MMU_THDI_PG_PROFILEr, rval, prigroup_spid_field[pri_grp]);
   4061 
   4062 
   4063     return BCM_E_NONE;
   4064 }
   4065 
   4066 
   4067 /*
   4068  * This function is used to get headroom pool
   4069  * for given Ingress [Port, Priority_group]
   4070  */
   4071 int
   4072 _bcm_th3_cosq_ingress_hdrm_pool_get_by_pg(int unit, bcm_gport_t gport,
   4073                              bcm_cos_queue_t pri_grp, int *arg)
   4074 {
   4075     int local_port;
   4076     uint64 rval;
   4077     int profile_index;
   4078     static const soc_field_t prigroup_hpid_field[] = {
   4079         PG0_HPIDf, PG1_HPIDf, PG2_HPIDf, PG3_HPIDf,
   4080         PG4_HPIDf, PG5_HPIDf, PG6_HPIDf, PG7_HPIDf
   4081     };
   4082 
   4083     BCM_IF_ERROR_RETURN
   4084             (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   4085 
   4086     if (!SOC_PORT_VALID(unit, local_port)) {
   4087         return BCM_E_PORT;
   4088     }
   4089 
   4090     if ((pri_grp < 0) || (pri_grp >= SOC_MMU_CFG_PRI_GROUP_MAX)) {
   4091         return BCM_E_PARAM;
   4092     }
   4093 
   4094     COMPILER_64_ZERO(rval);
   4095     SOC_IF_ERROR_RETURN
   4096         (soc_reg_get(unit, MMU_THDI_ING_PORT_CONFIGr, local_port, -1, &rval));
   4097 
   4098     profile_index = soc_reg64_field32_get(unit, MMU_THDI_ING_PORT_CONFIGr, rval, PG_PROFILE_SELf);
   4099 
   4100     COMPILER_64_ZERO(rval);
   4101     SOC_IF_ERROR_RETURN
   4102         (soc_reg64_get(unit, MMU_THDI_PG_PROFILEr, REG_PORT_ANY, profile_index, &rval));
   4103     *arg = soc_reg64_field32_get(unit, MMU_THDI_PG_PROFILEr, rval, prigroup_hpid_field[pri_grp]);
   4104 
   4105 
   4106     return BCM_E_NONE;
   4107 }
   4108 
   4109 
   4110 int
   4111 _bcm_th3_cosq_egr_pool_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   4112                           bcm_cosq_buffer_id_t buffer,
   4113                           bcm_cosq_control_t type, int* arg)
   4114 {
   4115     bcm_port_t local_port;
   4116     int startq, pool;
   4117     int pipe;
   4118     uint32 entry[SOC_MAX_MEM_WORDS];
   4119     soc_mem_t mem;
   4120     soc_field_t fld_limit = INVALIDf;
   4121     int granularity = 1;
   4122 
   4123     if (!arg) {
   4124         return BCM_E_PARAM;
   4125     }
   4126 
   4127     BCM_IF_ERROR_RETURN
   4128         (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4129                                     _BCM_TH3_COSQ_INDEX_STYLE_EGR_POOL,
   4130                                     &local_port, &pool, NULL));
   4131 
   4132     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   4133 
   4134     if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool ||
   4135         type == bcmCosqControlMCEgressPool) {
   4136         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4137             if (type != bcmCosqControlEgressPool) {
   4138                 return BCM_E_PARAM;
   4139             }
   4140             /* regular unicast queue */
   4141             BCM_IF_ERROR_RETURN
   4142                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4143                                      _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4144                                      &local_port, &startq, NULL));
   4145         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4146             if (type != bcmCosqControlEgressPool) {
   4147                 return BCM_E_PARAM;
   4148             }
   4149             BCM_IF_ERROR_RETURN
   4150                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4151                                      _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4152                                      &local_port, &startq, NULL));
   4153         } else  { /* local port */
   4154             if (type == bcmCosqControlUCEgressPool) {
   4155                 BCM_IF_ERROR_RETURN
   4156                     (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4157                                          _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4158                                          &local_port, &startq, NULL));
   4159             } else if (type == bcmCosqControlMCEgressPool) {
   4160                 BCM_IF_ERROR_RETURN
   4161                     (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4162                                          _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4163                                          &local_port, &startq, NULL));
   4164             } else {
   4165                 if (IS_CPU_PORT(unit, local_port) || (cosq >= _bcm_th3_get_num_ucq(unit))) {
   4166                     BCM_IF_ERROR_RETURN
   4167                         (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4168                                                  _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4169                                                  &local_port, &startq, NULL));
   4170                 } else {
   4171                     BCM_IF_ERROR_RETURN
   4172                         (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4173                                                  _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4174                                                  &local_port, &startq, NULL));
   4175                 }
   4176             }
   4177         }
   4178         mem = MMU_THDO_QUEUE_CONFIGm;
   4179         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   4180         *arg = soc_mem_field32_get(unit, mem, entry, SPIDf);
   4181 
   4182         return BCM_E_NONE;
   4183     }
   4184 
   4185     /* per service pool settings */
   4186     if (type == bcmCosqControlEgressPoolSharedLimitBytes ||
   4187         type == bcmCosqControlEgressPoolResumeLimitBytes ||
   4188         type == bcmCosqControlEgressPoolYellowSharedLimitBytes ||
   4189         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
   4190         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
   4191         type == bcmCosqControlEgressPoolRedResumeLimitBytes ||
   4192         type == bcmCosqControlEgressPoolHighCongestionLimitBytes ||
   4193         type == bcmCosqControlEgressPoolLowCongestionLimitBytes) {
   4194         int itm;
   4195         uint64 rval;
   4196         soc_reg_t reg;
   4197         soc_reg_t wred_cng_lmt[4] = {
   4198             MMU_WRED_POOL_INST_CONG_LIMIT_0r,
   4199             MMU_WRED_POOL_INST_CONG_LIMIT_1r,
   4200             MMU_WRED_POOL_INST_CONG_LIMIT_2r,
   4201             MMU_WRED_POOL_INST_CONG_LIMIT_3r,
   4202         };
   4203 
   4204         switch (type) {
   4205             case bcmCosqControlEgressPoolSharedLimitBytes:
   4206                 reg = MMU_THDO_SHARED_DB_POOL_SHARED_LIMITr;
   4207                 fld_limit = SHARED_LIMITf;
   4208                 granularity = 1;
   4209                 break;
   4210             case bcmCosqControlEgressPoolResumeLimitBytes:
   4211                 reg = MMU_THDO_SHARED_DB_POOL_RESUME_LIMITr;
   4212                 fld_limit = RESUME_LIMITf;
   4213                 granularity = 8;
   4214                 break;
   4215             case bcmCosqControlEgressPoolYellowSharedLimitBytes:
   4216                 reg = MMU_THDO_SHARED_DB_POOL_YELLOW_SHARED_LIMITr;
   4217                 fld_limit = YELLOW_SHARED_LIMITf;
   4218                 granularity = 8;
   4219                 break;
   4220             case bcmCosqControlEgressPoolYellowResumeLimitBytes:
   4221                 reg = MMU_THDO_SHARED_DB_POOL_YELLOW_RESUME_LIMITr;
   4222                 fld_limit = YELLOW_RESUME_LIMITf;
   4223                 granularity = 8;
   4224                 break;
   4225             case bcmCosqControlEgressPoolRedSharedLimitBytes:
   4226                 reg = MMU_THDO_SHARED_DB_POOL_RED_SHARED_LIMITr;
   4227                 fld_limit = RED_SHARED_LIMITf;
   4228                 granularity = 8;
   4229                 break;
   4230             case bcmCosqControlEgressPoolRedResumeLimitBytes:
   4231                 reg = MMU_THDO_SHARED_DB_POOL_RED_RESUME_LIMITr;
   4232                 fld_limit = RED_RESUME_LIMITf;
   4233                 granularity = 8;
   4234                 break;
   4235             case bcmCosqControlEgressPoolHighCongestionLimitBytes:
   4236                 reg = wred_cng_lmt[pool];
   4237                 fld_limit = POOL_HI_CONG_LIMITf;
   4238                 pool = -1;
   4239                 granularity = 1;
   4240                 break;
   4241             case bcmCosqControlEgressPoolLowCongestionLimitBytes:
   4242                 reg = wred_cng_lmt[pool];
   4243                 fld_limit = POOL_LOW_CONG_LIMITf;
   4244                 pool = -1;
   4245                 granularity = 1;
   4246                 break;
   4247             /* coverity[dead_error_begin] */
   4248             default:
   4249                 return BCM_E_UNAVAIL;
   4250         }
   4251         /* These regs are chip unique, buffer = -1 writes on both itms
   4252            No need to do pipe-itm checking */
   4253         if (buffer == BCM_COSQ_BUFFER_ID_INVALID) {
   4254             itm = -1;
   4255         } else if (buffer <  NUM_ITM(unit)) {
   4256             itm = buffer;
   4257         } else {
   4258             return BCM_E_PARAM;
   4259         }
   4260 
   4261         SOC_IF_ERROR_RETURN(soc_tomahawk3_itm_reg_get
   4262             (unit, reg, itm, itm, pool, &rval));
   4263 
   4264         *arg = soc_reg64_field32_get(unit, reg, rval, fld_limit);
   4265         *arg = (*arg) * granularity * _TH3_MMU_BYTES_PER_CELL;
   4266 
   4267         return BCM_E_NONE;
   4268     }
   4269 
   4270     /* per port settings: */
   4271 
   4272     if (type == bcmCosqControlEgressPoolLimitEnable) {
   4273         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4274             BCM_IF_ERROR_RETURN
   4275                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4276                                              _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4277                                              &local_port, &startq, NULL));
   4278         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4279             BCM_IF_ERROR_RETURN
   4280                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4281                                              _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4282                                              &local_port, &startq, NULL));
   4283         } else {
   4284             if (IS_CPU_PORT(unit, local_port) || (cosq >= _bcm_th3_get_num_ucq(unit))) {
   4285                 BCM_IF_ERROR_RETURN
   4286                     (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4287                                              _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4288                                              &local_port, &startq, NULL));
   4289             } else {
   4290                 BCM_IF_ERROR_RETURN
   4291                     (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4292                                              _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4293                                              &local_port, &startq, NULL));
   4294             }
   4295         }
   4296         mem = MMU_THDO_QUEUE_CONFIGm;
   4297         fld_limit = LIMIT_ENABLEf;
   4298         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   4299         *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
   4300         return BCM_E_NONE;
   4301     }
   4302 
   4303     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4304         BCM_IF_ERROR_RETURN
   4305             (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4306                                          _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4307                                          &local_port, &startq, NULL));
   4308     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4309         BCM_IF_ERROR_RETURN
   4310             (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4311                                          _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4312                                          &local_port, &startq, NULL));
   4313     } else {
   4314         if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) {
   4315             /* Need to have the UC_MC_Combine config enabled */
   4316             return BCM_E_PARAM;
   4317         }
   4318         if (IS_CPU_PORT(unit, local_port) || (cosq >= _bcm_th3_get_num_ucq(unit))) {
   4319             BCM_IF_ERROR_RETURN
   4320                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4321                                          _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4322                                          &local_port, &startq, NULL));
   4323         } else {
   4324             BCM_IF_ERROR_RETURN
   4325                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4326                                          _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4327                                          &local_port, &startq, NULL));
   4328         }
   4329     }
   4330     mem = MMU_THDO_QUEUE_CONFIGm;
   4331 
   4332     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   4333 
   4334     switch (type) {
   4335         case bcmCosqControlEgressPoolLimitBytes:
   4336             fld_limit = SHARED_LIMITf;
   4337             granularity = 1;
   4338             break;
   4339         case bcmCosqControlEgressPoolYellowLimitBytes:
   4340             fld_limit = LIMIT_YELLOWf;
   4341             granularity = 8;
   4342             break;
   4343         case bcmCosqControlEgressPoolRedLimitBytes:
   4344             fld_limit = LIMIT_REDf;
   4345             granularity = 8;
   4346             break;
   4347         default:
   4348             return BCM_E_UNAVAIL;
   4349     }
   4350     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
   4351     *arg = (*arg) * granularity * _TH3_MMU_BYTES_PER_CELL;
   4352 
   4353 
   4354     return BCM_E_NONE;
   4355 
   4356 
   4357 }
   4358 
   4359 int
   4360 _bcm_th3_cosq_egr_pool_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   4361                           bcm_cosq_buffer_id_t buffer,
   4362                           bcm_cosq_control_t type, int arg)
   4363 {
   4364     bcm_port_t local_port;
   4365     int startq, pool;
   4366     int midx;
   4367     int pipe;
   4368     uint32 entry[SOC_MAX_MEM_WORDS];
   4369     soc_mem_t mem;
   4370     soc_mem_t mmu_thdo_per_queue_mem[] = {
   4371         MMU_THDO_QUEUE_CONFIGm,
   4372         MMU_THDO_Q_TO_QGRP_MAPD0m
   4373     };
   4374     int mmu_thdo_per_queue_mem_cnt = 2;
   4375     soc_field_t field_qspid[12] = {
   4376             QUEUE0_SPIDf, QUEUE1_SPIDf, QUEUE2_SPIDf,
   4377             QUEUE3_SPIDf, QUEUE4_SPIDf, QUEUE5_SPIDf,
   4378             QUEUE6_SPIDf, QUEUE7_SPIDf, QUEUE8_SPIDf,
   4379             QUEUE9_SPIDf, QUEUE10_SPIDf, QUEUE11_SPIDf
   4380     };
   4381     soc_field_t fld_limit = INVALIDf;
   4382     int idx;
   4383     int granularity = 1;
   4384     uint32 max_val;
   4385 
   4386     if (arg < 0) {
   4387         return BCM_E_PARAM;
   4388     }
   4389 
   4390     BCM_IF_ERROR_RETURN
   4391         (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4392                                     _BCM_TH3_COSQ_INDEX_STYLE_EGR_POOL,
   4393                                     &local_port, &pool, NULL));
   4394 
   4395     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   4396 
   4397     if (type == bcmCosqControlEgressPool || type == bcmCosqControlUCEgressPool ||
   4398         type == bcmCosqControlMCEgressPool) {
   4399         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4400             if (type != bcmCosqControlEgressPool) {
   4401                 return BCM_E_PARAM;
   4402             }
   4403             /* regular unicast queue */
   4404             BCM_IF_ERROR_RETURN
   4405                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4406                                      _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4407                                      &local_port, &startq, NULL));
   4408         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4409             if (type != bcmCosqControlEgressPool) {
   4410                 return BCM_E_PARAM;
   4411             }
   4412             BCM_IF_ERROR_RETURN
   4413                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4414                                      _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4415                                      &local_port, &startq, NULL));
   4416         } else  { /* local port */
   4417             if (type == bcmCosqControlUCEgressPool) {
   4418                 BCM_IF_ERROR_RETURN
   4419                     (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4420                                          _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4421                                          &local_port, &startq, NULL));
   4422             } else if (type == bcmCosqControlMCEgressPool) {
   4423                 BCM_IF_ERROR_RETURN
   4424                     (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4425                                          _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4426                                          &local_port, &startq, NULL));
   4427             } else {
   4428                 if (IS_CPU_PORT(unit, local_port) || (cosq >= _bcm_th3_get_num_ucq(unit))) {
   4429                     BCM_IF_ERROR_RETURN
   4430                         (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4431                                                  _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4432                                                  &local_port, &startq, NULL));
   4433                 } else {
   4434                     BCM_IF_ERROR_RETURN
   4435                         (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4436                                                  _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4437                                                  &local_port, &startq, NULL));
   4438                 }
   4439             }
   4440         }
   4441 
   4442         for (idx = 0; idx < mmu_thdo_per_queue_mem_cnt; idx++) {
   4443             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mmu_thdo_per_queue_mem[idx], MEM_BLOCK_ALL, startq, entry));
   4444             soc_mem_field32_set(unit, mmu_thdo_per_queue_mem[idx], &entry, SPIDf, arg);
   4445             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mmu_thdo_per_queue_mem[idx], MEM_BLOCK_ALL, startq, entry));
   4446         }
   4447 
   4448         mem = MMU_THDO_PORT_QUEUE_SERVICE_POOLm;
   4449         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port,
   4450                      MMU_THDO_PORT_QUEUE_SERVICE_POOLm, 0);
   4451         /* CMIC has 48 queues... so not applicalble for cmic port */
   4452         if (!IS_CPU_PORT(unit, local_port)) {
   4453             int cosq_idx;
   4454             if (cosq == -1) {
   4455                 cosq_idx = 0;
   4456             } else {
   4457                 cosq_idx = cosq;
   4458             }
   4459             BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx,
   4460                             entry));
   4461             soc_mem_field32_set(unit, mem,
   4462                     entry, field_qspid[cosq_idx],
   4463                     arg);
   4464             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx,
   4465                             entry));
   4466         }
   4467 
   4468         return BCM_E_NONE;
   4469     }
   4470 
   4471     /* per service pool settings */
   4472     if (type == bcmCosqControlEgressPoolSharedLimitBytes ||
   4473         type == bcmCosqControlEgressPoolResumeLimitBytes ||
   4474         type == bcmCosqControlEgressPoolYellowSharedLimitBytes ||
   4475         type == bcmCosqControlEgressPoolYellowResumeLimitBytes ||
   4476         type == bcmCosqControlEgressPoolRedSharedLimitBytes ||
   4477         type == bcmCosqControlEgressPoolRedResumeLimitBytes ||
   4478         type == bcmCosqControlEgressPoolHighCongestionLimitBytes ||
   4479         type == bcmCosqControlEgressPoolLowCongestionLimitBytes) {
   4480         int itm;
   4481         uint64 rval;
   4482         soc_reg_t reg;
   4483         soc_reg_t wred_cng_lmt[4] = {
   4484             MMU_WRED_POOL_INST_CONG_LIMIT_0r,
   4485             MMU_WRED_POOL_INST_CONG_LIMIT_1r,
   4486             MMU_WRED_POOL_INST_CONG_LIMIT_2r,
   4487             MMU_WRED_POOL_INST_CONG_LIMIT_3r,
   4488         };
   4489         arg = (arg + _TH3_MMU_BYTES_PER_CELL - 1) / _TH3_MMU_BYTES_PER_CELL;
   4490 
   4491         switch (type) {
   4492             case bcmCosqControlEgressPoolSharedLimitBytes:
   4493                 reg = MMU_THDO_SHARED_DB_POOL_SHARED_LIMITr;
   4494                 fld_limit = SHARED_LIMITf;
   4495                 granularity = 1;
   4496                 break;
   4497             case bcmCosqControlEgressPoolResumeLimitBytes:
   4498                 reg = MMU_THDO_SHARED_DB_POOL_RESUME_LIMITr;
   4499                 fld_limit = RESUME_LIMITf;
   4500                 granularity = 8;
   4501                 break;
   4502             case bcmCosqControlEgressPoolYellowSharedLimitBytes:
   4503                 reg = MMU_THDO_SHARED_DB_POOL_YELLOW_SHARED_LIMITr;
   4504                 fld_limit = YELLOW_SHARED_LIMITf;
   4505                 granularity = 8;
   4506                 break;
   4507             case bcmCosqControlEgressPoolYellowResumeLimitBytes:
   4508                 reg = MMU_THDO_SHARED_DB_POOL_YELLOW_RESUME_LIMITr;
   4509                 fld_limit = YELLOW_RESUME_LIMITf;
   4510                 granularity = 8;
   4511                 break;
   4512             case bcmCosqControlEgressPoolRedSharedLimitBytes:
   4513                 reg = MMU_THDO_SHARED_DB_POOL_RED_SHARED_LIMITr;
   4514                 fld_limit = RED_SHARED_LIMITf;
   4515                 granularity = 8;
   4516                 break;
   4517             case bcmCosqControlEgressPoolRedResumeLimitBytes:
   4518                 reg = MMU_THDO_SHARED_DB_POOL_RED_RESUME_LIMITr;
   4519                 fld_limit = RED_RESUME_LIMITf;
   4520                 granularity = 8;
   4521                 break;
   4522             case bcmCosqControlEgressPoolHighCongestionLimitBytes:
   4523                 reg = wred_cng_lmt[pool];
   4524                 fld_limit = POOL_HI_CONG_LIMITf;
   4525                 pool = -1;
   4526                 granularity = 1;
   4527                 break;
   4528             case bcmCosqControlEgressPoolLowCongestionLimitBytes:
   4529                 reg = wred_cng_lmt[pool];
   4530                 fld_limit = POOL_LOW_CONG_LIMITf;
   4531                 pool = -1;
   4532                 granularity = 1;
   4533                 break;
   4534             /* coverity[dead_error_begin] */
   4535             default:
   4536                 return BCM_E_UNAVAIL;
   4537         }
   4538         /* These regs are chip unique, buffer = -1 writes on both itms
   4539            No need to do pipe-itm checking */
   4540 
   4541         if (buffer == BCM_COSQ_BUFFER_ID_INVALID) {
   4542             itm = -1;
   4543         } else if (buffer <  NUM_ITM(unit)) {
   4544             itm = buffer;
   4545         } else {
   4546             return BCM_E_PARAM;
   4547         }
   4548 
   4549         SOC_IF_ERROR_RETURN(soc_tomahawk3_itm_reg_get
   4550             (unit, reg, itm, itm, pool, &rval));
   4551 
   4552         /* Check for min/max values */
   4553         max_val = (1 << soc_reg_field_length(unit, reg, fld_limit)) - 1;
   4554         if ((arg < 0) || ((arg/granularity) > max_val)) {
   4555             return BCM_E_PARAM;
   4556         } else {
   4557             soc_reg64_field32_set(unit, reg, &rval, fld_limit, (arg/granularity));
   4558         }
   4559 
   4560         SOC_IF_ERROR_RETURN(soc_tomahawk3_itm_reg_set
   4561             (unit, reg, itm, itm, pool, rval));
   4562 
   4563         return BCM_E_NONE;
   4564     }
   4565 
   4566     /* per port settings: Why is there under Pool */
   4567     if (type == bcmCosqControlEgressPoolLimitEnable) {
   4568         int limit;
   4569         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4570             BCM_IF_ERROR_RETURN
   4571                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4572                                              _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4573                                              &local_port, &startq, NULL));
   4574         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4575             BCM_IF_ERROR_RETURN
   4576                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4577                                              _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4578                                              &local_port, &startq, NULL));
   4579         } else {
   4580             if (IS_CPU_PORT(unit, local_port) || (cosq >= _bcm_th3_get_num_ucq(unit))) {
   4581                 BCM_IF_ERROR_RETURN
   4582                     (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4583                                              _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4584                                              &local_port, &startq, NULL));
   4585             } else {
   4586                 BCM_IF_ERROR_RETURN
   4587                     (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4588                                              _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4589                                              &local_port, &startq, NULL));
   4590             }
   4591         }
   4592         mem = MMU_THDO_QUEUE_CONFIGm;
   4593         fld_limit = LIMIT_ENABLEf;
   4594         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   4595         /* What if it is dynamic shared limit */
   4596         limit = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf);
   4597         if (limit == 0)
   4598             return BCM_E_PARAM;
   4599         soc_mem_field32_set(unit, mem, entry, fld_limit, arg);
   4600         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   4601         return BCM_E_NONE;
   4602     }
   4603     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   4604         BCM_IF_ERROR_RETURN
   4605             (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4606                                          _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4607                                          &local_port, &startq, NULL));
   4608     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4609         BCM_IF_ERROR_RETURN
   4610             (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4611                                          _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4612                                          &local_port, &startq, NULL));
   4613     } else {
   4614         if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0) == 0) {
   4615             /* Need to have the UC_MC_Combine config enabled */
   4616             return BCM_E_PARAM;
   4617         }
   4618         if (IS_CPU_PORT(unit, local_port) || (cosq >= _bcm_th3_get_num_ucq(unit))) {
   4619             BCM_IF_ERROR_RETURN
   4620                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4621                                          _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   4622                                          &local_port, &startq, NULL));
   4623         } else {
   4624             BCM_IF_ERROR_RETURN
   4625                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   4626                                          _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   4627                                          &local_port, &startq, NULL));
   4628         }
   4629     }
   4630 
   4631     mem = MMU_THDO_QUEUE_CONFIGm;
   4632     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   4633 
   4634     switch (type) {
   4635         case bcmCosqControlEgressPoolLimitBytes:
   4636             fld_limit = SHARED_LIMITf;
   4637             soc_mem_field32_set(unit, mem, entry, LIMIT_ENABLEf, 1);
   4638             granularity = 1;
   4639             break;
   4640         case bcmCosqControlEgressPoolYellowLimitBytes:
   4641             fld_limit = LIMIT_YELLOWf;
   4642             granularity = 8;
   4643             break;
   4644         case bcmCosqControlEgressPoolRedLimitBytes:
   4645             fld_limit = LIMIT_REDf;
   4646             granularity = 8;
   4647             break;
   4648         default:
   4649             return BCM_E_UNAVAIL;
   4650     }
   4651     /* Check for min/max values */
   4652     arg = (arg + _TH3_MMU_BYTES_PER_CELL - 1) / _TH3_MMU_BYTES_PER_CELL;
   4653     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   4654     if ((arg < 0) || ((arg/granularity) > max_val)) {
   4655         return BCM_E_PARAM;
   4656     } else {
   4657         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   4658     }
   4659     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   4660 
   4661     return BCM_E_NONE;
   4662 
   4663 
   4664 }
   4665 
   4666 /* Get pipe for a given port */
   4667 int
   4668 _bcm_th3_cosq_pipe_get(int unit, bcm_gport_t gport, int *pipe)
   4669 {
   4670     bcm_port_t local_port;
   4671 
   4672     if (pipe) {
   4673         BCM_IF_ERROR_RETURN
   4674             (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   4675         if (local_port < 0) {
   4676             return BCM_E_PORT;
   4677         }
   4678         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, pipe));
   4679     }
   4680     return BCM_E_NONE;
   4681 }
   4682 
   4683 int
   4684 _bcm_th3_cosq_ing_res_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   4685                           bcm_cosq_control_t type, int* arg)
   4686 {
   4687     bcm_port_t local_port;
   4688     int midx;
   4689     uint32 entry[SOC_MAX_MEM_WORDS];
   4690     soc_mem_t mem = INVALIDm;
   4691     soc_field_t fld_limit = INVALIDf;
   4692     int pipe, port_pg;
   4693     int pool, granularity = 1;
   4694     soc_field_t field_pgmin_limit[_TH3_MMU_NUM_PG] = {
   4695             PG0_MIN_LIMITf, PG1_MIN_LIMITf, PG2_MIN_LIMITf,
   4696             PG3_MIN_LIMITf, PG4_MIN_LIMITf, PG5_MIN_LIMITf,
   4697             PG6_MIN_LIMITf, PG7_MIN_LIMITf};
   4698     /* soc_field_t field_use_portsp[_TH3_MMU_NUM_PG] = {
   4699             PG0_USE_PORTSP_MINf, PG1_USE_PORTSP_MINf, PG2_USE_PORTSP_MINf,
   4700             PG3_USE_PORTSP_MINf, PG4_USE_PORTSP_MINf, PG5_USE_PORTSP_MINf,
   4701             PG6_USE_PORTSP_MINf, PG7_USE_PORTSP_MINf}; */
   4702     soc_field_t field_pghdrm_limit[_TH3_MMU_NUM_PG] = {
   4703             PG0_HDRM_LIMITf, PG1_HDRM_LIMITf, PG2_HDRM_LIMITf,
   4704             PG3_HDRM_LIMITf, PG4_HDRM_LIMITf, PG5_HDRM_LIMITf,
   4705             PG6_HDRM_LIMITf, PG7_HDRM_LIMITf};
   4706     soc_field_t field_pgshared_limit[_TH3_MMU_NUM_PG] = {
   4707             PG0_SHARED_LIMITf, PG1_SHARED_LIMITf, PG2_SHARED_LIMITf,
   4708             PG3_SHARED_LIMITf, PG4_SHARED_LIMITf, PG5_SHARED_LIMITf,
   4709             PG6_SHARED_LIMITf, PG7_SHARED_LIMITf};
   4710     soc_field_t field_pgreset_floor[_TH3_MMU_NUM_PG] = {
   4711             PG0_RESET_FLOORf, PG1_RESET_FLOORf, PG2_RESET_FLOORf,
   4712             PG3_RESET_FLOORf, PG4_RESET_FLOORf, PG5_RESET_FLOORf,
   4713             PG6_RESET_FLOORf, PG7_RESET_FLOORf};
   4714     soc_field_t field_sp_min[_TH3_MMU_NUM_POOL] = {
   4715             PORTSP0_MIN_LIMITf, PORTSP1_MIN_LIMITf,
   4716             PORTSP2_MIN_LIMITf, PORTSP3_MIN_LIMITf};
   4717     soc_field_t field_sp_shared[_TH3_MMU_NUM_POOL] = {
   4718             PORTSP0_SHARED_LIMITf, PORTSP1_SHARED_LIMITf,
   4719             PORTSP2_SHARED_LIMITf, PORTSP3_SHARED_LIMITf};
   4720     soc_field_t field_sp_resume[_TH3_MMU_NUM_POOL] = {
   4721             PORTSP0_RESUME_LIMITf, PORTSP1_RESUME_LIMITf,
   4722             PORTSP2_RESUME_LIMITf, PORTSP3_RESUME_LIMITf};
   4723     soc_field_t field_pgreset_offset[_TH3_MMU_NUM_PG] = {
   4724             PG0_RESET_OFFSETf, PG1_RESET_OFFSETf, PG2_RESET_OFFSETf,
   4725             PG3_RESET_OFFSETf, PG4_RESET_OFFSETf, PG5_RESET_OFFSETf,
   4726             PG6_RESET_OFFSETf, PG7_RESET_OFFSETf};
   4727 
   4728     if (!arg) {
   4729         return BCM_E_PARAM;
   4730     }
   4731 
   4732     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4733         BCM_GPORT_IS_SCHEDULER(gport) ||
   4734         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4735         return BCM_E_PARAM;
   4736     }
   4737 
   4738     BCM_IF_ERROR_RETURN
   4739         (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   4740     if (!SOC_PORT_VALID(unit, local_port)) {
   4741         return BCM_E_PORT;
   4742     }
   4743 
   4744     
   4745     if ((cosq < 0) || (cosq >= _TH3_MMU_NUM_PG)) {
   4746         return BCM_E_PARAM;
   4747     }
   4748     port_pg = cosq;
   4749 
   4750     BCM_IF_ERROR_RETURN
   4751         (_bcm_th3_cosq_pipe_get(unit, gport, &pipe));
   4752 
   4753     BCM_IF_ERROR_RETURN
   4754         (_bcm_th3_cosq_ingress_sp_get_by_pg(unit, gport, port_pg, &pool));
   4755 
   4756     sal_memset(&entry, 0, sizeof(entry));
   4757     if (type == bcmCosqControlIngressPortPGSharedLimitBytes) {
   4758         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDI_PORT_PG_SHARED_CONFIGm)[pipe];
   4759         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port,
   4760                                 MMU_THDI_PORT_PG_SHARED_CONFIGm, 0);
   4761     } else if (type == bcmCosqControlIngressPortPGMinLimitBytes) {
   4762         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDI_PORT_PG_MIN_CONFIGm)[pipe];
   4763         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port,
   4764                                 MMU_THDI_PORT_PG_MIN_CONFIGm, 0);
   4765     } else if (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) {
   4766         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDI_PORT_PG_HDRM_CONFIGm)[pipe];
   4767         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port,
   4768                                 MMU_THDI_PORT_PG_HDRM_CONFIGm, 0);
   4769     } else if ((type == bcmCosqControlIngressPortPGResetFloorBytes)||
   4770                (type == bcmCosqControlIngressPortPGResetOffsetBytes)) {
   4771         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDI_PORT_PG_RESUME_CONFIGm)[pipe];
   4772         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port,
   4773                                 MMU_THDI_PORT_PG_RESUME_CONFIGm, 0);
   4774     } else if ((type == bcmCosqControlIngressPortPoolMinLimitBytes) ||
   4775                (type == bcmCosqControlIngressPortPoolSharedLimitBytes) ||
   4776                (type == bcmCosqControlIngressPortPoolResumeLimitBytes)) {
   4777         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDI_PORTSP_CONFIGm)[pipe];
   4778         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port, MMU_THDI_PORTSP_CONFIGm, 0);
   4779     } else {
   4780         return BCM_E_UNAVAIL;
   4781     }
   4782 
   4783     if (midx < 0) {
   4784         return BCM_E_PARAM;
   4785     }
   4786 
   4787     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   4788 
   4789     switch (type) {
   4790         case bcmCosqControlIngressPortPGSharedLimitBytes:
   4791             fld_limit = field_pgshared_limit[port_pg];
   4792             granularity = 1;
   4793             break;
   4794         case bcmCosqControlIngressPortPGMinLimitBytes:
   4795             fld_limit = field_pgmin_limit[port_pg];
   4796             granularity = 1;
   4797             break;
   4798         case bcmCosqControlIngressPortPoolMinLimitBytes:
   4799             fld_limit = field_sp_min[pool];
   4800             granularity = 1;
   4801             break;
   4802         case bcmCosqControlIngressPortPoolSharedLimitBytes:
   4803             fld_limit = field_sp_shared[pool];
   4804             granularity = 1;
   4805             break;
   4806         case bcmCosqControlIngressPortPoolResumeLimitBytes:
   4807             fld_limit = field_sp_resume[pool];
   4808             granularity = 1;
   4809             break;
   4810         case bcmCosqControlIngressPortPGHeadroomLimitBytes:
   4811             fld_limit = field_pghdrm_limit[port_pg];
   4812             granularity = 1;
   4813             break;
   4814         case bcmCosqControlIngressPortPGResetFloorBytes:
   4815             fld_limit = field_pgreset_floor[port_pg];
   4816             granularity = 1;
   4817             break;
   4818         case bcmCosqControlIngressPortPGResetOffsetBytes:
   4819             fld_limit = field_pgreset_offset[port_pg];
   4820             granularity = 1;
   4821             break;
   4822         /*
   4823          * COVERITY
   4824          *
   4825          * This default is unreachable. It is kept intentionally
   4826          * as a defensive default for future development.
   4827          */
   4828         /* coverity[dead_error_begin] */
   4829         default:
   4830             return BCM_E_UNAVAIL;
   4831     }
   4832 
   4833     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
   4834     *arg = (*arg) * granularity * _TH3_MMU_BYTES_PER_CELL;
   4835 
   4836     return BCM_E_NONE;
   4837 }
   4838 
   4839 
   4840 int
   4841 _bcm_th3_cosq_ing_res_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   4842                           bcm_cosq_control_t type, int arg)
   4843 {
   4844     bcm_port_t local_port;
   4845     int midx;
   4846     uint32 max_val;
   4847     uint32 entry[SOC_MAX_MEM_WORDS];
   4848     soc_mem_t mem = INVALIDm;
   4849     soc_field_t fld_limit = INVALIDf;
   4850     int pipe, port_pg;
   4851     int pool, granularity = 1;
   4852     int shd_size[_TH3_ITMS_PER_DEV], cur_val;
   4853     soc_field_t field_pgmin_limit[_TH3_MMU_NUM_PG] = {
   4854             PG0_MIN_LIMITf, PG1_MIN_LIMITf, PG2_MIN_LIMITf,
   4855             PG3_MIN_LIMITf, PG4_MIN_LIMITf, PG5_MIN_LIMITf,
   4856             PG6_MIN_LIMITf, PG7_MIN_LIMITf};
   4857     /* soc_field_t field_use_portsp[_TH3_MMU_NUM_PG] = {
   4858             PG0_USE_PORTSP_MINf, PG1_USE_PORTSP_MINf, PG2_USE_PORTSP_MINf,
   4859             PG3_USE_PORTSP_MINf, PG4_USE_PORTSP_MINf, PG5_USE_PORTSP_MINf,
   4860             PG6_USE_PORTSP_MINf, PG7_USE_PORTSP_MINf}; */
   4861     soc_field_t field_pghdrm_limit[_TH3_MMU_NUM_PG] = {
   4862             PG0_HDRM_LIMITf, PG1_HDRM_LIMITf, PG2_HDRM_LIMITf,
   4863             PG3_HDRM_LIMITf, PG4_HDRM_LIMITf, PG5_HDRM_LIMITf,
   4864             PG6_HDRM_LIMITf, PG7_HDRM_LIMITf};
   4865     soc_field_t field_pgshared_limit[_TH3_MMU_NUM_PG] = {
   4866             PG0_SHARED_LIMITf, PG1_SHARED_LIMITf, PG2_SHARED_LIMITf,
   4867             PG3_SHARED_LIMITf, PG4_SHARED_LIMITf, PG5_SHARED_LIMITf,
   4868             PG6_SHARED_LIMITf, PG7_SHARED_LIMITf};
   4869     soc_field_t field_pgreset_floor[_TH3_MMU_NUM_PG] = {
   4870             PG0_RESET_FLOORf, PG1_RESET_FLOORf, PG2_RESET_FLOORf,
   4871             PG3_RESET_FLOORf, PG4_RESET_FLOORf, PG5_RESET_FLOORf,
   4872             PG6_RESET_FLOORf, PG7_RESET_FLOORf};
   4873     soc_field_t field_sp_min[_TH3_MMU_NUM_POOL] = {
   4874             PORTSP0_MIN_LIMITf, PORTSP1_MIN_LIMITf,
   4875             PORTSP2_MIN_LIMITf, PORTSP3_MIN_LIMITf};
   4876     soc_field_t field_sp_shared[_TH3_MMU_NUM_POOL] = {
   4877             PORTSP0_SHARED_LIMITf, PORTSP1_SHARED_LIMITf,
   4878             PORTSP2_SHARED_LIMITf, PORTSP3_SHARED_LIMITf};
   4879     soc_field_t field_sp_resume[_TH3_MMU_NUM_POOL] = {
   4880             PORTSP0_RESUME_LIMITf, PORTSP1_RESUME_LIMITf,
   4881             PORTSP2_RESUME_LIMITf, PORTSP3_RESUME_LIMITf};
   4882     soc_field_t field_pgreset_offset[_TH3_MMU_NUM_PG] = {
   4883             PG0_RESET_OFFSETf, PG1_RESET_OFFSETf, PG2_RESET_OFFSETf,
   4884             PG3_RESET_OFFSETf, PG4_RESET_OFFSETf, PG5_RESET_OFFSETf,
   4885             PG6_RESET_OFFSETf, PG7_RESET_OFFSETf};
   4886 
   4887 
   4888     if (arg < 0) {
   4889         return BCM_E_PARAM;
   4890     }
   4891 
   4892     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   4893         BCM_GPORT_IS_SCHEDULER(gport) ||
   4894         BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   4895         return BCM_E_PARAM;
   4896     }
   4897 
   4898     arg = (arg + _TH3_MMU_BYTES_PER_CELL - 1) / _TH3_MMU_BYTES_PER_CELL;
   4899     BCM_IF_ERROR_RETURN
   4900         (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   4901     if (!SOC_PORT_VALID(unit, local_port)) {
   4902         return BCM_E_PORT;
   4903     }
   4904 
   4905     
   4906     if ((cosq < 0) || (cosq >= _TH3_MMU_NUM_PG)) {
   4907         return BCM_E_PARAM;
   4908     }
   4909     port_pg = cosq;
   4910 
   4911     BCM_IF_ERROR_RETURN
   4912         (_bcm_th3_cosq_pipe_get(unit, gport, &pipe));
   4913 
   4914     BCM_IF_ERROR_RETURN
   4915         (_bcm_th3_cosq_ingress_sp_get_by_pg(unit, gport, port_pg, &pool));
   4916 
   4917     sal_memset(&entry, 0, sizeof(entry));
   4918     if (type == bcmCosqControlIngressPortPGSharedLimitBytes) {
   4919         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDI_PORT_PG_SHARED_CONFIGm)[pipe];
   4920         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port,
   4921                                 MMU_THDI_PORT_PG_SHARED_CONFIGm, 0);
   4922     } else if (type == bcmCosqControlIngressPortPGMinLimitBytes) {
   4923         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDI_PORT_PG_MIN_CONFIGm)[pipe];
   4924         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port,
   4925                                 MMU_THDI_PORT_PG_MIN_CONFIGm, 0);
   4926     } else if (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) {
   4927         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDI_PORT_PG_HDRM_CONFIGm)[pipe];
   4928         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port,
   4929                                 MMU_THDI_PORT_PG_HDRM_CONFIGm, 0);
   4930     } else if ((type == bcmCosqControlIngressPortPGResetFloorBytes) ||
   4931                (type == bcmCosqControlIngressPortPGResetOffsetBytes)) {
   4932         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDI_PORT_PG_RESUME_CONFIGm)[pipe];
   4933         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port,
   4934                                 MMU_THDI_PORT_PG_RESUME_CONFIGm, 0);
   4935     } else if ((type == bcmCosqControlIngressPortPoolMinLimitBytes) ||
   4936                (type == bcmCosqControlIngressPortPoolSharedLimitBytes) ||
   4937                (type == bcmCosqControlIngressPortPoolResumeLimitBytes)) {
   4938         mem = SOC_MEM_UNIQUE_ACC(unit, MMU_THDI_PORTSP_CONFIGm)[pipe];
   4939         midx = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port, MMU_THDI_PORTSP_CONFIGm, 0);
   4940     }
   4941     else {
   4942         return BCM_E_UNAVAIL;
   4943     }
   4944 
   4945     if (midx < 0) {
   4946         return BCM_E_PARAM;
   4947     }
   4948 
   4949     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   4950 
   4951     switch (type) {
   4952         case bcmCosqControlIngressPortPGSharedLimitBytes:
   4953             fld_limit = field_pgshared_limit[port_pg];
   4954             granularity = 1;
   4955             break;
   4956         case bcmCosqControlIngressPortPGMinLimitBytes:
   4957             fld_limit = field_pgmin_limit[port_pg];
   4958             granularity = 1;
   4959             break;
   4960         case bcmCosqControlIngressPortPoolMinLimitBytes:
   4961             fld_limit = field_sp_min[pool];
   4962             granularity = 1;
   4963             break;
   4964         case bcmCosqControlIngressPortPoolSharedLimitBytes:
   4965             fld_limit = field_sp_shared[pool];
   4966             granularity = 1;
   4967             break;
   4968         case bcmCosqControlIngressPortPoolResumeLimitBytes:
   4969             fld_limit = field_sp_resume[pool];
   4970             granularity = 1;
   4971             break;
   4972         case bcmCosqControlIngressPortPGHeadroomLimitBytes:
   4973             fld_limit = field_pghdrm_limit[port_pg];
   4974             granularity = 1;
   4975             break;
   4976         case bcmCosqControlIngressPortPGResetFloorBytes:
   4977             fld_limit = field_pgreset_floor[port_pg];
   4978             granularity = 1;
   4979             break;
   4980         case bcmCosqControlIngressPortPGResetOffsetBytes:
   4981             fld_limit = field_pgreset_offset[port_pg];
   4982             granularity = 1;
   4983             break;
   4984         /*
   4985          * COVERITY
   4986          *
   4987          * This default is unreachable. It is kept intentionally
   4988          * as a defensive default for future development.
   4989          */
   4990         /* coverity[dead_error_begin] */
   4991         default:
   4992             return BCM_E_UNAVAIL;
   4993     }
   4994 
   4995     /* Check for min/max values */
   4996     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   4997     if ((arg < 0) || ((arg/granularity) > max_val)) {
   4998         return BCM_E_PARAM;
   4999     }
   5000 
   5001     /* guarantee limits need adjust shared limits */
   5002     if ((type == bcmCosqControlIngressPortPGMinLimitBytes) ||
   5003         (type == bcmCosqControlIngressPortPGHeadroomLimitBytes)) {
   5004         int itm, itm_map;
   5005         int delta[_TH3_ITMS_PER_DEV] = {0}, update;
   5006 
   5007         cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit);
   5008         sal_memcpy(shd_size, _BCM_TH3_MMU_INFO(unit)->shared_limit,
   5009             sizeof(shd_size));
   5010 
   5011         /* adjustment delta */
   5012         itm_map = SOC_INFO(unit).ipipe_itm_map[pipe];
   5013         for (itm = 0; itm < _TH3_ITMS_PER_DEV; itm++) {
   5014             if (itm_map & (1 << itm)) {
   5015                 delta[itm] = ((arg / granularity) - cur_val) * granularity;
   5016             }
   5017         }
   5018 
   5019         /* shared limits to be decreased */
   5020         for (itm = 0, update = 0; itm < _TH3_ITMS_PER_DEV; itm ++) {
   5021             if ((itm_map & (1 << itm)) && (delta[itm] > 0)) {
   5022                 /* no space to decrease shared limit */
   5023                 if (delta[itm] > shd_size[itm]) {
   5024                     return BCM_E_RESOURCE;
   5025                 }
   5026                 shd_size[itm] -= delta[itm];
   5027                 update = 1;
   5028             }
   5029         }
   5030         if (update) {
   5031             /* Decrease shared limits */
   5032             BCM_IF_ERROR_RETURN
   5033                 (soc_th3_mmu_config_res_limits_update(unit, delta, pool, 1));
   5034         }
   5035 
   5036         /* set new guarantee */
   5037         /* the hw value may be changed by soc_th3_mmu_config_res_limits_update
   5038          * so read the register again in order to keep consistent  */
   5039         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   5040         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   5041         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   5042 
   5043         /* shared limits to be increased */
   5044         for (itm = 0, update = 0; itm < _TH3_ITMS_PER_DEV; itm ++) {
   5045             if ((itm_map & (1 << itm)) && (delta[itm] < 0)) {
   5046                 shd_size[itm] -= delta[itm];
   5047                 update = 1;
   5048             }
   5049         }
   5050         if (update) {
   5051             /* Increase shared limits */
   5052             BCM_IF_ERROR_RETURN
   5053                 (soc_th3_mmu_config_res_limits_update(unit, delta, pool, 0));
   5054         }
   5055         sal_memcpy(_BCM_TH3_MMU_INFO(unit)->shared_limit, shd_size,
   5056             sizeof(shd_size));
   5057 
   5058         /* In the case of PG Headroom limit, update headroom pool limit */
   5059         if (type == bcmCosqControlIngressPortPGHeadroomLimitBytes) {
   5060             uint32 rval = 0;
   5061             int cur_hdrm = 0;
   5062             for (itm = 0, update = 0; itm < _TH3_ITMS_PER_DEV; itm ++) {
   5063                 if (itm_map & (1 << itm)) {
   5064                     SOC_IF_ERROR_RETURN(
   5065                         soc_tomahawk3_itm_reg32_get(unit,
   5066                             MMU_THDI_HDRM_BUFFER_CELL_LIMIT_HPr, itm, itm, pool, &rval));
   5067                     cur_hdrm = soc_reg_field_get(unit, MMU_THDI_HDRM_BUFFER_CELL_LIMIT_HPr,
   5068                                              rval, LIMITf);
   5069                     cur_hdrm += delta[itm];
   5070                     if (cur_hdrm < 0) {
   5071                         return BCM_E_PARAM;
   5072                     }
   5073                     soc_reg_field_set(unit, MMU_THDI_HDRM_BUFFER_CELL_LIMIT_HPr,
   5074                                              &rval, LIMITf, cur_hdrm);
   5075                     SOC_IF_ERROR_RETURN(
   5076                         soc_tomahawk3_itm_reg32_set(unit,
   5077                             MMU_THDI_HDRM_BUFFER_CELL_LIMIT_HPr, itm, itm, pool, rval));
   5078                 }
   5079             }
   5080         }
   5081     } else {
   5082         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, midx, entry));
   5083         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   5084         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, entry));
   5085     }
   5086 
   5087     return BCM_E_NONE;
   5088 }
   5089 
   5090 int
   5091 _bcm_th3_cosq_egr_queue_set(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   5092                             bcm_cosq_control_t type, int arg)
   5093 {
   5094     bcm_port_t local_port;
   5095     /* int pipe;  */
   5096     int startq;
   5097     uint32 max_val;
   5098     uint32 entry[SOC_MAX_MEM_WORDS];
   5099     soc_mem_t mem = INVALIDm;
   5100     soc_field_t fld_limit = INVALIDf;
   5101     int granularity = 1;
   5102     int from_cos, to_cos, ci;
   5103     int shd_size[_TH3_ITMS_PER_DEV];
   5104     int cur_val;
   5105     int limit;
   5106     int disable_queuing = 0;
   5107 
   5108     if (arg < 0) {
   5109         return BCM_E_PARAM;
   5110     }
   5111 
   5112     arg = (arg + _TH3_MMU_BYTES_PER_CELL - 1) / _TH3_MMU_BYTES_PER_CELL;
   5113 
   5114     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   5115         (type == bcmCosqControlEgressUCQueueSharedLimitBytes) ||
   5116         (type == bcmCosqControlEgressUCQueueResumeOffsetBytes)) {
   5117         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5118             BCM_IF_ERROR_RETURN
   5119                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   5120                                              _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5121                                              &local_port, &startq, NULL));
   5122             /* SOC_IF_ERROR_RETURN
   5123                 (soc_port_pipe_get(unit, local_port, &pipe)); */
   5124         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5125             return BCM_E_PARAM;
   5126         }
   5127         else {
   5128             if (cosq == BCM_COS_INVALID) {
   5129                 from_cos = to_cos = 0;
   5130             } else {
   5131                 from_cos = to_cos = cosq;
   5132             }
   5133 
   5134             BCM_IF_ERROR_RETURN
   5135                 (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   5136             if (local_port < 0) {
   5137                 return BCM_E_PORT;
   5138             }
   5139             /* SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); */
   5140             for (ci = from_cos; ci <= to_cos; ci++) {
   5141                 BCM_IF_ERROR_RETURN
   5142                     (_bcm_th3_cosq_index_resolve
   5143                      (unit, local_port, ci, _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5144                       NULL, &startq, NULL));
   5145             }
   5146         }
   5147         if (type == bcmCosqControlEgressUCQueueResumeOffsetBytes) {
   5148             mem = MMU_THDO_QUEUE_RESUME_OFFSETm;
   5149         } else {
   5150             mem = MMU_THDO_QUEUE_CONFIGm;
   5151         }
   5152     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
   5153                (type == bcmCosqControlEgressMCQueueResumeOffsetBytes) ||
   5154                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
   5155         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5156             return BCM_E_PARAM;
   5157         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5158             BCM_IF_ERROR_RETURN
   5159                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   5160                                              _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5161                                              &local_port, &startq, NULL));
   5162             /* SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));*/
   5163         }
   5164         else {
   5165             if (cosq == BCM_COS_INVALID) {
   5166                 from_cos = to_cos = 0;
   5167             } else {
   5168                 from_cos = to_cos = cosq;
   5169             }
   5170 
   5171             BCM_IF_ERROR_RETURN
   5172                 (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   5173             if (local_port < 0) {
   5174                 return BCM_E_PORT;
   5175             }
   5176             /* SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe)); */
   5177             for (ci = from_cos; ci <= to_cos; ci++) {
   5178                 BCM_IF_ERROR_RETURN
   5179                     (_bcm_th3_cosq_index_resolve
   5180                      (unit, local_port, ci, _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5181                       NULL, &startq, NULL));
   5182             }
   5183         }
   5184         if (type == bcmCosqControlEgressMCQueueResumeOffsetBytes) {
   5185             mem = MMU_THDO_QUEUE_RESUME_OFFSETm;
   5186         } else {
   5187             mem = MMU_THDO_QUEUE_CONFIGm;
   5188         }
   5189     } else {
   5190         return BCM_E_PARAM;
   5191     }
   5192 
   5193     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5194 
   5195     switch (type) {
   5196         case bcmCosqControlEgressUCQueueSharedLimitBytes:
   5197         case bcmCosqControlEgressMCQueueSharedLimitBytes:
   5198             fld_limit = SHARED_LIMITf;
   5199 
   5200             /* Set MMU_THDO_QUEUE_CONFIG.DISABLE_QUEUING to 1 when both MIN
   5201              * and SHARED LIMIT are 0. Set it to 0 when either MIN or SHARED LIMIT
   5202              * is non-zero.
   5203              */
   5204             limit = soc_mem_field32_get(unit, mem, entry, MIN_LIMITf);
   5205             if (arg == 0 && limit == 0) {
   5206                 disable_queuing = 1;
   5207             } else if (arg != 0 || limit != 0) {
   5208                 disable_queuing = 0;
   5209             }
   5210             granularity = 1;
   5211             break;
   5212         case bcmCosqControlEgressUCQueueMinLimitBytes:
   5213         case bcmCosqControlEgressMCQueueMinLimitBytes:
   5214             fld_limit = MIN_LIMITf;
   5215 
   5216             /* Set MMU_THDO_QUEUE_CONFIG.DISABLE_QUEUING to 1 when both MIN
   5217              * and SHARED LIMIT are 0. Set it to 0 when either MIN or
   5218              * SHARED LIMIT is non-zero
   5219              */
   5220             limit = soc_mem_field32_get(unit, mem, entry, SHARED_LIMITf);
   5221             if (arg == 0 && limit == 0) {
   5222                 disable_queuing = 1;
   5223             } else if (arg != 0 || limit != 0) {
   5224                 disable_queuing = 0;
   5225             }
   5226 
   5227             granularity = 1;
   5228             break;
   5229         case bcmCosqControlEgressUCQueueResumeOffsetBytes:
   5230         case bcmCosqControlEgressMCQueueResumeOffsetBytes:
   5231             fld_limit = RESUME_OFFSETf;
   5232             granularity = 8;
   5233             break;
   5234         default:
   5235             return BCM_E_UNAVAIL;
   5236     }
   5237 
   5238     /* Check for min/max values */
   5239     max_val = (1 << soc_mem_field_length(unit, mem, fld_limit)) - 1;
   5240     if ((arg < 0) || ((arg/granularity) > max_val)) {
   5241         return BCM_E_PARAM;
   5242     }
   5243 
   5244     /* guarantee limits need adjust shared limits */
   5245     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   5246          (type == bcmCosqControlEgressMCQueueMinLimitBytes)) {
   5247         int itm, itm_map;
   5248         int delta[_TH3_ITMS_PER_DEV] = {0}, update;
   5249         int pool;
   5250         itm_map = SOC_INFO(unit).itm_map;
   5251         BCM_IF_ERROR_RETURN(_bcm_th3_cosq_egr_pool_get(unit, gport,
   5252             cosq, -1, bcmCosqControlEgressPool,&pool));
   5253 
   5254         cur_val = soc_mem_field32_get(unit, mem, entry, fld_limit);
   5255         sal_memcpy(shd_size, _BCM_TH3_MMU_INFO(unit)->shared_limit,
   5256             sizeof(shd_size));
   5257 
   5258         /* adjustment delta */
   5259         for (itm = 0; itm < NUM_ITM(unit); itm ++) {
   5260             if (itm_map & (1 << itm)) {
   5261                 delta[itm] = ((arg / granularity) - cur_val) * granularity;
   5262             }
   5263         }
   5264 
   5265         /* shared limits to be decreased */
   5266         for (itm = 0, update = 0; itm < NUM_ITM(unit); itm ++) {
   5267             if (itm_map & (1 << itm)) {
   5268                 if (delta[itm] > 0) {
   5269                     /* no space to decrease shared limit */
   5270                     if (delta[itm] > shd_size[itm]) {
   5271                         return BCM_E_RESOURCE;
   5272                     }
   5273                     shd_size[itm] -= delta[itm];
   5274                     update = 1;
   5275                 }
   5276             }
   5277         }
   5278         if (update) {
   5279             BCM_IF_ERROR_RETURN
   5280                 (soc_th3_mmu_config_res_limits_update(unit, delta, pool, 1));
   5281         }
   5282 
   5283         /* set new guarantee */
   5284         /* the hw value may be changed by soc_th3_mmu_config_res_limits_update
   5285          * so read the register again in order to keep consistent  */
   5286         BCM_IF_ERROR_RETURN
   5287             (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5288         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   5289         BCM_IF_ERROR_RETURN
   5290             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5291 
   5292         /* shared limits to be increased */
   5293         for (itm = 0, update = 0; itm < NUM_ITM(unit); itm ++) {
   5294             if (itm_map & (1 << itm)) {
   5295                 if (delta[itm] < 0) {
   5296                     shd_size[itm] -= delta[itm];
   5297                     update = 1;
   5298                 }
   5299             }
   5300         }
   5301         if (update) {
   5302             BCM_IF_ERROR_RETURN
   5303                 (soc_th3_mmu_config_res_limits_update(unit, delta, pool, 0));
   5304         }
   5305 
   5306         sal_memcpy(_BCM_TH3_MMU_INFO(unit)->shared_limit, shd_size,
   5307             sizeof(shd_size));
   5308     } else {
   5309         soc_mem_field32_set(unit, mem, entry, fld_limit, (arg/granularity));
   5310         BCM_IF_ERROR_RETURN
   5311             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5312     }
   5313 
   5314     /* limit enable */
   5315     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5316 
   5317     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   5318         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
   5319         soc_mem_field32_set(unit, mem, entry, DISABLE_QUEUINGf, disable_queuing);
   5320     }
   5321 
   5322     if ((type == bcmCosqControlEgressUCQueueSharedLimitBytes) ||
   5323         (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
   5324         soc_mem_field32_set(unit, mem, entry, LIMIT_ENABLEf, 1);
   5325         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5326     }
   5327 
   5328     return BCM_E_NONE;
   5329 }
   5330 
   5331 
   5332 
   5333 int
   5334 _bcm_th3_cosq_egr_queue_get(int unit, bcm_gport_t gport, bcm_cos_queue_t cosq,
   5335                             bcm_cosq_control_t type, int* arg)
   5336 {
   5337     bcm_port_t local_port;
   5338     int pipe, startq;
   5339     uint32 entry[SOC_MAX_MEM_WORDS];
   5340     soc_mem_t mem = INVALIDm;
   5341     soc_field_t fld_limit = INVALIDf;
   5342     int granularity = 1;
   5343     int from_cos, to_cos, ci;
   5344 
   5345     if (!arg) {
   5346         return BCM_E_PARAM;
   5347     }
   5348 
   5349 
   5350     if ((type == bcmCosqControlEgressUCQueueMinLimitBytes) ||
   5351         (type == bcmCosqControlEgressUCQueueResumeOffsetBytes) ||
   5352         (type == bcmCosqControlEgressUCQueueSharedLimitBytes)) {
   5353         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5354             BCM_IF_ERROR_RETURN
   5355                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   5356                                              _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5357                                              &local_port, &startq, NULL));
   5358             SOC_IF_ERROR_RETURN
   5359                 (soc_port_pipe_get(unit, local_port, &pipe));
   5360         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5361             return BCM_E_PARAM;
   5362         }
   5363         else {
   5364             if (cosq == BCM_COS_INVALID) {
   5365                 from_cos = to_cos = 0;
   5366             } else {
   5367                 from_cos = to_cos = cosq;
   5368             }
   5369 
   5370             BCM_IF_ERROR_RETURN
   5371                 (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   5372             if (local_port < 0) {
   5373                 return BCM_E_PORT;
   5374             }
   5375             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5376             for (ci = from_cos; ci <= to_cos; ci++) {
   5377                 BCM_IF_ERROR_RETURN
   5378                     (_bcm_th3_cosq_index_resolve
   5379                      (unit, local_port, ci, _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5380                       NULL, &startq, NULL));
   5381             }
   5382         }
   5383         if (type == bcmCosqControlEgressUCQueueResumeOffsetBytes) {
   5384             mem = MMU_THDO_QUEUE_RESUME_OFFSETm;
   5385         } else {
   5386             mem = MMU_THDO_QUEUE_CONFIGm;
   5387         }
   5388     } else if ((type == bcmCosqControlEgressMCQueueMinLimitBytes) ||
   5389                (type == bcmCosqControlEgressMCQueueResumeOffsetBytes) ||
   5390                (type == bcmCosqControlEgressMCQueueSharedLimitBytes)) {
   5391         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5392             return BCM_E_PARAM;
   5393         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5394             BCM_IF_ERROR_RETURN
   5395                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   5396                                              _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5397                                              &local_port, &startq, NULL));
   5398             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5399         }
   5400         else {
   5401             if (cosq == BCM_COS_INVALID) {
   5402                 from_cos = to_cos = 0;
   5403             } else {
   5404                 from_cos = to_cos = cosq;
   5405             }
   5406 
   5407             BCM_IF_ERROR_RETURN
   5408                 (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   5409             if (local_port < 0) {
   5410                 return BCM_E_PORT;
   5411             }
   5412             SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5413             for (ci = from_cos; ci <= to_cos; ci++) {
   5414                 BCM_IF_ERROR_RETURN
   5415                     (_bcm_th3_cosq_index_resolve
   5416                      (unit, local_port, ci, _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5417                       NULL, &startq, NULL));
   5418             }
   5419         }
   5420         if (type == bcmCosqControlEgressMCQueueResumeOffsetBytes) {
   5421             mem = MMU_THDO_QUEUE_RESUME_OFFSETm;
   5422         } else {
   5423             mem = MMU_THDO_QUEUE_CONFIGm;
   5424         }
   5425     } else {
   5426         return BCM_E_PARAM;
   5427     }
   5428 
   5429     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5430 
   5431     switch (type) {
   5432         case bcmCosqControlEgressUCQueueSharedLimitBytes:
   5433         case bcmCosqControlEgressMCQueueSharedLimitBytes:
   5434             fld_limit = SHARED_LIMITf;
   5435             granularity = 1;
   5436             break;
   5437         case bcmCosqControlEgressUCQueueMinLimitBytes:
   5438         case bcmCosqControlEgressMCQueueMinLimitBytes:
   5439             fld_limit = MIN_LIMITf;
   5440             granularity = 1;
   5441             break;
   5442         case bcmCosqControlEgressUCQueueResumeOffsetBytes:
   5443         case bcmCosqControlEgressMCQueueResumeOffsetBytes:
   5444             fld_limit = RESUME_OFFSETf;
   5445             granularity = 8;
   5446             break;
   5447         default:
   5448             return BCM_E_UNAVAIL;
   5449     }
   5450 
   5451     BCM_IF_ERROR_RETURN
   5452         (soc_mem_read(unit, mem, MEM_BLOCK_ALL, startq, entry));
   5453     *arg = soc_mem_field32_get(unit, mem, entry, fld_limit);
   5454     *arg = (*arg) * granularity * _TH3_MMU_BYTES_PER_CELL;
   5455 
   5456     return BCM_E_NONE;
   5457 }
   5458 
   5459 /*
   5460  * This function is used to get enables
   5461  * for Qgroup Min and Shared Limits for a given Egress Unicast Queue
   5462  */
   5463 int
   5464 _bcm_th3_cosq_qgroup_limit_enables_get(int unit, bcm_gport_t gport,
   5465                                bcm_cos_t cosq, bcm_cosq_control_t type,
   5466                                int* arg)
   5467 {
   5468     bcm_port_t local_port;
   5469     int startq=0, pipe=0;
   5470     uint32 entry[SOC_MAX_MEM_WORDS];
   5471     soc_mem_t mem = INVALIDm;
   5472     soc_field_t field = INVALIDf;
   5473 
   5474     if (!arg) {
   5475         return BCM_E_PARAM;
   5476     }
   5477 
   5478     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5479         if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
   5480             BCM_IF_ERROR_RETURN
   5481                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   5482                                         _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5483                                         &local_port, &startq, NULL));
   5484         } else {
   5485             return BCM_E_PARAM;
   5486         }
   5487     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5488         if (type == bcmCosqControlEgressMCQueueGroupMinEnable) {
   5489             BCM_IF_ERROR_RETURN
   5490                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   5491                                         _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5492                                         &local_port, &startq, NULL));
   5493         } else {
   5494             return BCM_E_PARAM;
   5495         }
   5496     } else {
   5497         if (cosq < 0) {
   5498             return BCM_E_PARAM;
   5499         }
   5500         BCM_IF_ERROR_RETURN
   5501             (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   5502         if (local_port < 0) {
   5503             return BCM_E_PORT;
   5504         }
   5505         if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
   5506             BCM_IF_ERROR_RETURN
   5507                 (_bcm_th3_cosq_index_resolve
   5508                  (unit, local_port, cosq, _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5509                   NULL, &startq, NULL));
   5510         } else {
   5511             BCM_IF_ERROR_RETURN
   5512                 (_bcm_th3_cosq_index_resolve
   5513                  (unit, local_port, cosq, _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5514                   NULL, &startq, NULL));
   5515         }
   5516     }
   5517 
   5518     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5519     mem = MMU_THDO_QUEUE_CONFIGm;
   5520     if ((type == bcmCosqControlEgressUCQueueGroupMinEnable) ||
   5521         (type == bcmCosqControlEgressMCQueueGroupMinEnable)) {
   5522         field = USE_QGROUP_MINf;
   5523     } else {
   5524         return BCM_E_PARAM;
   5525     }
   5526 
   5527     BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   5528                     startq, entry));
   5529     *arg = soc_mem_field32_get(unit, mem, entry, field);
   5530 
   5531     return BCM_E_NONE;
   5532 }
   5533 
   5534 /*
   5535  * This function is used to set enables
   5536  * for Qgroup Min and Shared Limits for a given Egress Unicast Queue
   5537  */
   5538 int
   5539 _bcm_th3_cosq_qgroup_limit_enables_set(int unit, bcm_gport_t gport,
   5540                                bcm_cos_t cosq, bcm_cosq_control_t type,
   5541                                int arg)
   5542 {
   5543     bcm_port_t local_port;
   5544     int startq=0, count=1, lc=0, to_cos=0;
   5545     uint32 entry[SOC_MAX_MEM_WORDS], entry2[SOC_MAX_MEM_WORDS];
   5546     soc_mem_t mem = INVALIDm;
   5547     soc_mem_t mmu_thdo_per_queue_mem = MMU_THDO_Q_TO_QGRP_MAPD0m;
   5548     int enable;
   5549     int valid;
   5550     soc_field_t field = INVALIDf;
   5551     soc_field_t field2 = INVALIDf;
   5552 
   5553     if (arg < 0) {
   5554         return BCM_E_PARAM;
   5555     }
   5556     arg = arg ? 1 : 0;
   5557 
   5558     if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   5559         if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
   5560             BCM_IF_ERROR_RETURN
   5561                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   5562                                         _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5563                                         &local_port, &startq, NULL));
   5564         } else {
   5565             return BCM_E_PARAM;
   5566         }
   5567     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5568         if (type == bcmCosqControlEgressMCQueueGroupMinEnable) {
   5569             BCM_IF_ERROR_RETURN
   5570                 (_bcm_th3_cosq_index_resolve(unit, gport, cosq,
   5571                                         _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5572                                         &local_port, &startq, NULL));
   5573         } else {
   5574             return BCM_E_PARAM;
   5575         }
   5576     } else {
   5577         if (cosq < -1) {
   5578             return BCM_E_PARAM;
   5579         }
   5580         BCM_IF_ERROR_RETURN
   5581             (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   5582         if (local_port < 0) {
   5583             return BCM_E_PORT;
   5584         }
   5585         if (type == bcmCosqControlEgressUCQueueGroupMinEnable) {
   5586             BCM_IF_ERROR_RETURN
   5587                 (_bcm_th3_cosq_index_resolve
   5588                  (unit, local_port, cosq, _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE,
   5589                   NULL, &startq, &count));
   5590         } else {
   5591             BCM_IF_ERROR_RETURN
   5592                 (_bcm_th3_cosq_index_resolve
   5593                  (unit, local_port, cosq, _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE,
   5594                   NULL, &startq, &count));
   5595         }
   5596     }
   5597 
   5598     mem = MMU_THDO_QUEUE_CONFIGm;
   5599     if ((type == bcmCosqControlEgressUCQueueGroupMinEnable) ||
   5600         (type == bcmCosqControlEgressMCQueueGroupMinEnable)) {
   5601         field = USE_QGROUP_MINf;
   5602         field2 = QGROUP_VALIDf;
   5603     } else {
   5604         return BCM_E_PARAM;
   5605     }
   5606 
   5607     to_cos = startq + count;
   5608     for (lc = startq; lc < to_cos; lc++) {
   5609         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   5610                     lc, entry));
   5611         enable = soc_mem_field32_get(unit, mem, entry, field);
   5612         if (enable != arg) {
   5613             soc_mem_field32_set(unit, mem, entry, field, arg);
   5614             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   5615                         lc, entry));
   5616         }
   5617         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mmu_thdo_per_queue_mem,
   5618                     MEM_BLOCK_ALL, lc, entry2));
   5619         valid = soc_mem_field32_get(unit, mmu_thdo_per_queue_mem, entry2, field2);
   5620         if (valid != arg) {
   5621             soc_mem_field32_set(unit, mmu_thdo_per_queue_mem, entry2, field2, arg);
   5622             BCM_IF_ERROR_RETURN(soc_mem_write(unit, mmu_thdo_per_queue_mem,
   5623                         MEM_BLOCK_ALL, lc, entry2));
   5624         }
   5625     }
   5626 
   5627     /*If qgroup min limit enable is being set,
   5628      buffer shared limits will not be recalculated. It is the responsibility
   5629      of the user to set the QueueMinLimitBytes to 0
   5630      */
   5631 
   5632     return BCM_E_NONE;
   5633 }
   5634 
   5635 /*
   5636  * This function is used to get limits
   5637  * for Qgroup Min and Shared Limits for a given Egress Unicast Queue
   5638  */
   5639 int
   5640 _bcm_th3_cosq_qgroup_limit_get(int unit, bcm_gport_t gport, bcm_cos_t cosq,
   5641                                bcm_cosq_control_t type, int* arg)
   5642 {
   5643     bcm_port_t local_port;
   5644     int pipe;
   5645     uint32 entry[SOC_MAX_MEM_WORDS];
   5646     soc_mem_t mem = INVALIDm;
   5647     soc_field_t field = INVALIDf;
   5648     int granularity;
   5649 
   5650     if (cosq < 0) {
   5651         return BCM_E_PARAM;
   5652     }
   5653 
   5654     if (BCM_GPORT_IS_SET(gport)) {
   5655         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   5656             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5657             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) &&
   5658                 (type != bcmCosqControlEgressUCQueueGroupMinLimitBytes)) {
   5659                 return BCM_E_PARAM;
   5660             }
   5661             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) &&
   5662                 (type != bcmCosqControlEgressMCQueueGroupMinLimitBytes)) {
   5663                 return BCM_E_PARAM;
   5664             }
   5665         } else { /* GPORT is local or modport type */
   5666             if ((type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) &&
   5667                 (cosq >= _bcm_th3_get_num_ucq(unit) )) {
   5668                 return BCM_E_PARAM;
   5669             }
   5670             if ((type == bcmCosqControlEgressMCQueueGroupMinLimitBytes) &&
   5671                 (cosq < _bcm_th3_get_num_ucq(unit) )) {
   5672                 return BCM_E_PARAM;
   5673             }
   5674         }
   5675     } else { /* local port case */
   5676             if ((type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) &&
   5677                 (cosq >= _bcm_th3_get_num_ucq(unit) )) {
   5678                 return BCM_E_PARAM;
   5679             }
   5680             if ((type == bcmCosqControlEgressMCQueueGroupMinLimitBytes) &&
   5681                 (cosq < _bcm_th3_get_num_ucq(unit) )) {
   5682                 return BCM_E_PARAM;
   5683             }
   5684     }
   5685 
   5686     BCM_IF_ERROR_RETURN
   5687         (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   5688     if (local_port < 0) {
   5689         return BCM_E_PORT;
   5690     }
   5691 
   5692     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5693 
   5694     if ((type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) ||
   5695         (type == bcmCosqControlEgressMCQueueGroupMinLimitBytes)) {
   5696         if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) {
   5697             mem = MMU_THDO_CONFIG_UC_QGROUP0m;
   5698         }
   5699         else {
   5700             mem = MMU_THDO_CONFIG_MC_QGROUPm;
   5701         }
   5702         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   5703                 SOC_TH3_MMU_CHIP_PORT(unit, local_port), entry));
   5704         field = MIN_LIMITf;
   5705         granularity =1;
   5706     } else {
   5707         return BCM_E_PARAM;
   5708     }
   5709 
   5710     *arg = soc_mem_field32_get(unit, mem, entry, field);
   5711     *arg = (*arg) * granularity * _TH3_MMU_BYTES_PER_CELL;
   5712 
   5713     return BCM_E_NONE;
   5714 }
   5715 
   5716 /*
   5717  * This function is used to set limits
   5718  * for Qgroup Min and Shared Limits for a given Egress Unicast Queue
   5719  */
   5720 int
   5721 _bcm_th3_cosq_qgroup_limit_set(int unit, bcm_gport_t gport, bcm_cos_t cosq,
   5722                                bcm_cosq_control_t type, int arg)
   5723 {
   5724     bcm_port_t local_port;
   5725     int pipe;
   5726     uint32 entry[SOC_MAX_MEM_WORDS];
   5727     soc_mem_t mem = INVALIDm;
   5728     soc_field_t field = INVALIDf;
   5729     int granularity;
   5730     int shd_size[_TH3_ITMS_PER_DEV], cur_val;
   5731     int rv, itm;
   5732     int delta[_TH3_ITMS_PER_DEV] = {0};
   5733     int max_val;
   5734 
   5735     if (cosq < 0) {
   5736         return BCM_E_PARAM;
   5737     }
   5738 
   5739     if (BCM_GPORT_IS_SET(gport)) {
   5740         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   5741             BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   5742             if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) &&
   5743                 (type != bcmCosqControlEgressUCQueueGroupMinLimitBytes)) {
   5744                 return BCM_E_PARAM;
   5745             }
   5746             if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) &&
   5747                 (type != bcmCosqControlEgressMCQueueGroupMinLimitBytes)) {
   5748                 return BCM_E_PARAM;
   5749             }
   5750         } else { /* GPORT is local or modport type */
   5751             if ((type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) &&
   5752                 (cosq >= _bcm_th3_get_num_ucq(unit) )) {
   5753                 return BCM_E_PARAM;
   5754             }
   5755             if ((type == bcmCosqControlEgressMCQueueGroupMinLimitBytes) &&
   5756                 (cosq < _bcm_th3_get_num_ucq(unit) )) {
   5757                 return BCM_E_PARAM;
   5758             }
   5759         }
   5760     } else { /* local port case */
   5761             if ((type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) &&
   5762                 (cosq >= _bcm_th3_get_num_ucq(unit) )) {
   5763                 return BCM_E_PARAM;
   5764             }
   5765             if ((type == bcmCosqControlEgressMCQueueGroupMinLimitBytes) &&
   5766                 (cosq < _bcm_th3_get_num_ucq(unit) )) {
   5767                 return BCM_E_PARAM;
   5768             }
   5769     }
   5770 
   5771     BCM_IF_ERROR_RETURN
   5772         (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   5773     if (local_port < 0) {
   5774         return BCM_E_PORT;
   5775     }
   5776 
   5777     if ((type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) ||
   5778         (type == bcmCosqControlEgressMCQueueGroupMinLimitBytes)) {
   5779         arg = (arg + _TH3_MMU_BYTES_PER_CELL - 1) / _TH3_MMU_BYTES_PER_CELL;
   5780     }
   5781 
   5782     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   5783 
   5784     if ((type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) ||
   5785         (type == bcmCosqControlEgressMCQueueGroupMinLimitBytes)) {
   5786         int pool;
   5787         if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) {
   5788             mem = MMU_THDO_CONFIG_UC_QGROUP0m;
   5789         }
   5790         else {
   5791             mem = MMU_THDO_CONFIG_MC_QGROUPm;
   5792         }
   5793         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   5794                 SOC_TH3_MMU_CHIP_PORT(unit, local_port), entry));
   5795         field = MIN_LIMITf;
   5796         granularity =1;
   5797         /* Recalculate Shared Values if Min Changed */
   5798         BCM_IF_ERROR_RETURN(_bcm_th3_cosq_egr_pool_get(unit, gport,
   5799             cosq, -1, bcmCosqControlEgressPool,&pool));
   5800         sal_memcpy(shd_size, _BCM_TH3_MMU_INFO(unit)->shared_limit,
   5801              sizeof(shd_size));
   5802 
   5803         cur_val = soc_mem_field32_get(unit, mem, entry, field);
   5804         /* adjustment delta */
   5805         for (itm = 0; itm < NUM_ITM(unit); itm ++) {
   5806             delta[itm] = ((arg / granularity) - cur_val) * granularity;
   5807         }
   5808         /* shared limits to be increased/decreased */
   5809         for (itm = 0; itm < NUM_ITM(unit); itm ++) {
   5810             if (delta[itm] > 0) {
   5811                 /* no space to decrease shared limit */
   5812                 if (delta[itm] > shd_size[itm]) {
   5813                     return BCM_E_RESOURCE;
   5814                 }
   5815                 shd_size[itm] -= delta[itm];
   5816             }
   5817             if (delta[itm] < 0) {
   5818                 shd_size[itm] -= delta[itm];
   5819             }
   5820         }
   5821 
   5822         rv = soc_th3_mmu_config_res_limits_update(unit, delta, pool, 1);
   5823 
   5824         if (rv < 0) {
   5825             return rv;
   5826         }
   5827 
   5828         sal_memcpy(_BCM_TH3_MMU_INFO(unit)->shared_limit,shd_size,
   5829              sizeof(shd_size));
   5830     } else {
   5831         return BCM_E_PARAM;
   5832     }
   5833 
   5834     /* Check for min/max values */
   5835     max_val = (1 << soc_mem_field_length(unit, mem, field)) - 1;
   5836     if ((arg < 0) || ((arg/granularity) > max_val)) {
   5837         return BCM_E_PARAM;
   5838     } else {
   5839         soc_mem_field32_set(unit, mem, entry, field, (arg/granularity));
   5840     }
   5841     if (type == bcmCosqControlEgressUCQueueGroupMinLimitBytes) {
   5842         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   5843                    SOC_TH3_MMU_CHIP_PORT(unit, local_port), entry));
   5844     } else {
   5845         BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   5846                     SOC_TH3_MMU_CHIP_PORT(unit, local_port), entry));
   5847     }
   5848     return BCM_E_NONE;
   5849 }
   5850 
   5851 /*
   5852  * Function:
   5853  *     bcm_th3_cosq_gport_traverse
   5854  * Purpose:
   5855  *     Walks through the valid COSQ GPORTs and calls
   5856  *     the user supplied callback function for each entry.
   5857  * Parameters:
   5858  *     unit       - (IN) unit number
   5859  *     trav_fn    - (IN) Callback function.
   5860  *     user_data  - (IN) User data to be passed to callback function
   5861  * Returns:
   5862  *     BCM_E_NONE - Success.
   5863  *     BCM_E_XXX
   5864  */
   5865 int
   5866 bcm_th3_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb,
   5867                            void *user_data)
   5868 {
   5869     _bcm_th3_cosq_port_info_t *port_info = NULL;
   5870     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
   5871     bcm_module_t my_modid, modid_out;
   5872     bcm_port_t port, port_out, local_port;
   5873     bcm_gport_t gport;
   5874     int id, rv = SOC_E_NONE;
   5875 
   5876     if (_bcm_th3_cosq_port_info[unit] == NULL) {
   5877         return BCM_E_INIT;
   5878     }
   5879     if (_bcm_th3_cosq_cpu_port_info[unit] == NULL) {
   5880         return BCM_E_INIT;
   5881     }
   5882 
   5883     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   5884     PBMP_ALL_ITER(unit, port) {
   5885         BCM_IF_ERROR_RETURN
   5886             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   5887                                      my_modid, port, &modid_out, &port_out));
   5888         BCM_GPORT_MODPORT_SET(gport, modid_out, port_out);
   5889 
   5890         BCM_IF_ERROR_RETURN
   5891             (_bcm_th3_cosq_localport_resolve(unit, port, &local_port));
   5892 
   5893         if (IS_CPU_PORT(unit, local_port)) {
   5894             cpu_port_info = &_bcm_th3_cosq_cpu_port_info[unit][local_port];
   5895         } else {
   5896             port_info = &_bcm_th3_cosq_port_info[unit][local_port];
   5897         }
   5898         if (!IS_CPU_PORT(unit, local_port)) {
   5899             for (id = 0; id < _bcm_th3_get_num_ucq(unit); id++) {
   5900                 if (port_info->ucast[id].numq == 0) {
   5901                     continue;
   5902                 }
   5903                 rv = cb(unit, gport, port_info->ucast[id].numq,
   5904                         BCM_COSQ_GPORT_UCAST_QUEUE_GROUP,
   5905                         port_info->ucast[id].gport, user_data);
   5906 #ifdef BCM_CB_ABORT_ON_ERR
   5907                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   5908                     return rv;
   5909                 }
   5910 #else
   5911                 /*
   5912                  * If CB_ABORT_ON_ERR is not defined don't return error
   5913                  * and continue.
   5914                  */
   5915                 rv = BCM_E_NONE;
   5916 #endif
   5917             }
   5918         }
   5919         if (IS_CPU_PORT(unit, local_port)) {
   5920             for (id = 0; id < _BCM_TH3_NUM_CPU_MCAST_QUEUE; id++) {
   5921                 if (cpu_port_info->mcast[id].numq == 0) {
   5922                     continue;
   5923                 }
   5924                 rv = cb(unit, gport, cpu_port_info->mcast[id].numq,
   5925                         BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   5926                         cpu_port_info->mcast[id].gport, user_data);
   5927 #ifdef BCM_CB_ABORT_ON_ERR
   5928                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   5929                     return rv;
   5930                 }
   5931 #else
   5932                 /*
   5933                  * If CB_ABORT_ON_ERR is not defined don't return error
   5934                  * and continue.
   5935                  */
   5936                 rv = BCM_E_NONE;
   5937 #endif
   5938             }
   5939         } else {
   5940             for (id = 0; id < _bcm_th3_get_num_mcq(unit); id++) {
   5941                 if (port_info->mcast[id].numq == 0) {
   5942                     continue;
   5943                 }
   5944                 rv = cb(unit, gport, port_info->mcast[id].numq,
   5945                         BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   5946                         port_info->mcast[id].gport, user_data);
   5947 #ifdef BCM_CB_ABORT_ON_ERR
   5948                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   5949                     return rv;
   5950                 }
   5951 #else
   5952                 /*
   5953                  * If CB_ABORT_ON_ERR is not defined don't return error
   5954                  * and continue.
   5955                  */
   5956                 rv = BCM_E_NONE;
   5957 #endif
   5958             }
   5959         }
   5960         for (id = 0; id < _BCM_TH3_NUM_SCHEDULER_PER_PORT; id++) {
   5961             if (IS_CPU_PORT(unit, local_port)) {
   5962                 if (cpu_port_info->sched[id].numq == 0) {
   5963                     continue;
   5964                 }
   5965                 rv = cb(unit, gport, cpu_port_info->sched[id].numq,
   5966                         BCM_COSQ_GPORT_SCHEDULER,
   5967                         cpu_port_info->sched[id].gport, user_data);
   5968             } else {
   5969                 if (port_info->sched[id].numq == 0 ||
   5970                     port_info->sched[id].in_use == 0) {
   5971                     continue;
   5972                 }
   5973                 rv = cb(unit, gport, port_info->sched[id].numq,
   5974                         BCM_COSQ_GPORT_SCHEDULER,
   5975                         port_info->sched[id].gport, user_data);
   5976             }
   5977 #ifdef BCM_CB_ABORT_ON_ERR
   5978             if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   5979                 return rv;
   5980             }
   5981 #else
   5982             /*
   5983              * If CB_ABORT_ON_ERR is not defined don't return error
   5984              * and continue.
   5985              */
   5986             rv = BCM_E_NONE;
   5987 #endif
   5988         }
   5989     }
   5990     return rv;
   5991 }
   5992 
   5993 /*
   5994  * Function:
   5995  *     bcm_th3_cosq_gport_attach_get
   5996  * Purpose:
   5997  *     Get attached status of a scheduler port
   5998  * Parameters:
   5999  *     unit       - (IN) unit number
   6000  *     sched_port - (IN) scheduler GPORT identifier
   6001  *     input_port - (OUT) GPORT to attach to
   6002  *     cosq       - (OUT) COS queue to attached to
   6003  * Returns:
   6004  *     BCM_E_XXX
   6005  * Notes:
   6006  */
   6007 int
   6008 bcm_th3_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport,
   6009                              bcm_gport_t *input_gport, bcm_cos_queue_t *cosq)
   6010 {
   6011     _bcm_th3_cosq_node_t *node = NULL;
   6012     int cpu_mc_base = 0;
   6013     bcm_port_t local_port = -1;
   6014     soc_info_t *si = &SOC_INFO(unit);
   6015 
   6016     if (!(BCM_GPORT_IS_SET(sched_gport) ||
   6017           BCM_GPORT_IS_SCHEDULER(sched_gport) ||
   6018           BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport) ||
   6019           BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport))) {
   6020         return BCM_E_PARAM;
   6021     }
   6022 
   6023     BCM_IF_ERROR_RETURN
   6024         (_bcm_th3_cosq_node_get(unit, sched_gport, NULL, &local_port, NULL,
   6025                                &node));
   6026     if (node == NULL) {
   6027         return BCM_E_PARAM;
   6028     }
   6029 
   6030     if (local_port < 0) {
   6031         return BCM_E_PARAM;
   6032     }
   6033 
   6034     if (BCM_GPORT_IS_SCHEDULER(sched_gport)) {
   6035         if (IS_CPU_PORT(unit, local_port)) {
   6036             *cosq = (node->hw_index - cpu_mc_base) % _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   6037         } else {
   6038             *cosq = node->cos % _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   6039         }
   6040     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(sched_gport)) {
   6041         *cosq = node->cos % _BCM_TH3_MAX_QUEUE_PER_PORT;
   6042     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(sched_gport)) {
   6043         if (IS_CPU_PORT(unit, local_port)) {
   6044             cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   6045             *cosq = (node->hw_index - cpu_mc_base) % _BCM_TH3_NUM_CPU_MCAST_QUEUE;
   6046         } else {
   6047             *cosq = node->cos % _BCM_TH3_MAX_QUEUE_PER_PORT;
   6048         }
   6049     } else {
   6050         return BCM_E_PARAM;
   6051     }
   6052     *input_gport = node->parent_gport;
   6053 
   6054     return BCM_E_NONE;
   6055 }
   6056 
   6057 
   6058 /*
   6059  * Function:
   6060  *      _bcm_th3_cosq_gport_cpu_tree_create
   6061  * Purpose:
   6062  *      During cosq init create the default cosq gport tree for CPU.
   6063  *      Schedualar (L0) nodes are created and attach to physical ports.
   6064  *      UC and MC queues are added and attached to each L0 nodes.
   6065  * Parameters:
   6066  *      unit - (IN) unit number.
   6067  *      port - (IN) port number
   6068  * Returns:
   6069  *     BCM_E_XXX
   6070  */
   6071 int
   6072 _bcm_th3_cosq_gport_cpu_tree_create(int unit, bcm_port_t port)
   6073 {
   6074     bcm_gport_t cpu_mc_gport[_BCM_TH3_NUM_CPU_MCAST_QUEUE];
   6075     int id, pci_cmc = SOC_PCI_CMC(unit);
   6076     int ch_l0_map;
   6077     bcm_gport_t sched_gport[_BCM_TH3_NUM_SCHEDULER_PER_PORT];
   6078     int numq;
   6079     int num_queues_uc0 = soc_property_get(unit, "num_queues_uc0", 0);
   6080     int num_queues_uc1 = soc_property_get(unit, "num_queues_uc1", 0);
   6081 
   6082     if (!IS_CPU_PORT(unit, port)) {
   6083         return BCM_E_PARAM;
   6084     }
   6085     /* CMIC requires all 48 queues to be set and for the respective CMC */
   6086     if ((NUM_CPU_ARM_COSQ(unit, pci_cmc) + num_queues_uc0 + num_queues_uc1) !=
   6087          SOC_TH3_NUM_CPU_QUEUES) {
   6088         return BCM_E_PARAM;
   6089     }
   6090 
   6091 
   6092     numq = 48;
   6093     /* Adding L0 (schedular) nodes and attaching them to cpu port */
   6094     for (id = 0; id < _BCM_TH3_NUM_SCHEDULER_PER_PORT; id++) {
   6095         BCM_IF_ERROR_RETURN
   6096             (bcm_th3_cosq_gport_add(unit, port, numq, BCM_COSQ_GPORT_SCHEDULER,
   6097                                    &sched_gport[id]));
   6098         BCM_IF_ERROR_RETURN
   6099             (bcm_th3_cosq_gport_attach(unit, sched_gport[id], port, id));
   6100         LOG_INFO(BSL_LS_BCM_COSQ,
   6101             (BSL_META_U(unit,
   6102             "sched_gport[%d]=0x%x\n"),
   6103             id, sched_gport[id]));
   6104     }
   6105     /* Add MC queues and attach them to Schedular nodes.
   6106      * L0.0 node - PCI host
   6107      * L0.7 node - uc0
   6108      * L0.8 node - uc1
   6109      */
   6110 
   6111     /* CMICX supports only 2 CMCs.
   6112      * CMC0 connected to PCI.
   6113      * CMC1 is connected to other arm cores.
   6114      */
   6115 
   6116     for (id = 0; id < _BCM_TH3_NUM_CPU_MCAST_QUEUE; id++) {
   6117         ch_l0_map = (id < NUM_CPU_ARM_COSQ(unit, pci_cmc)) ? pci_cmc :
   6118                     (id < (NUM_CPU_ARM_COSQ(unit, pci_cmc) +
   6119                         (num_queues_uc0))) ? 7 : 8;
   6120         BCM_IF_ERROR_RETURN
   6121             (bcm_th3_cosq_gport_add(unit, 0, 1,
   6122                                    BCM_COSQ_GPORT_MCAST_QUEUE_GROUP,
   6123                                    &cpu_mc_gport[id]));
   6124         BCM_IF_ERROR_RETURN
   6125             (bcm_th3_cosq_gport_attach(unit, cpu_mc_gport[id],
   6126                                       sched_gport[ch_l0_map], id));
   6127     }
   6128 
   6129 
   6130     return SOC_E_NONE;
   6131 }
   6132 
   6133 
   6134 /*
   6135  * Function:
   6136  *      _bcm_th3_cosq_gport_tree_create
   6137  * Purpose:
   6138  *      During cosq init create the default cosq gport tree.
   6139  *      Schedualar (L0) nodes are created and attach to physical ports.
   6140  *      UC and MC queues are added and attached to each L0 nodes.
   6141  * Parameters:
   6142  *      unit - (IN) unit number.
   6143  *      port - (IN) port number
   6144  * Returns:
   6145  *     BCM_E_XXX
   6146  */
   6147 int
   6148 _bcm_th3_cosq_gport_tree_create(int unit, bcm_port_t port)
   6149 {
   6150     int id;
   6151 
   6152     if (IS_CPU_PORT(unit, port)) {
   6153         _bcm_th3_cosq_gport_cpu_tree_create(unit, port);
   6154     } else {
   6155         /* Adding L0 (schedular) nodes and attaching them to front panel and cpu port */
   6156         for (id = 0; id < _BCM_TH3_NUM_SCHEDULER_PER_PORT; id++) {
   6157             BCM_IF_ERROR_RETURN
   6158                 (_bcm_th3_cosq_gport_add_attach(unit, port, id, BCM_COSQ_GPORT_SCHEDULER));
   6159         }
   6160 
   6161         /* Adding UC/MC queues and attaching them to Schedular nodes */
   6162         for (id = 0; id < _BCM_TH3_MAX_NUM_QUEUE_PER_PORT; id++) {
   6163             BCM_IF_ERROR_RETURN
   6164                 (_bcm_th3_cosq_gport_add_attach(unit, port, id, 0));
   6165         }
   6166     }
   6167 
   6168     return SOC_E_NONE;
   6169 }
   6170 
   6171 /*
   6172  * Function:
   6173  *     bcm_th3_cosq_sched_weight_max_get
   6174  * Purpose:
   6175  *     Retrieve maximum weights for given COS policy
   6176  * Parameters:
   6177  *     unit    - (IN) unit number
   6178  *     mode    - (IN) Scheduling mode (BCM_COSQ_xxx)
   6179  *     weight_max - (OUT) Maximum weight for COS queue.
   6180  * Returns:
   6181  *     BCM_E_XXX
   6182  */
   6183 int
   6184 bcm_th3_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   6185 {
   6186     switch (mode) {
   6187     case BCM_COSQ_STRICT:
   6188         *weight_max = BCM_COSQ_WEIGHT_STRICT;
   6189         break;
   6190     case BCM_COSQ_ROUND_ROBIN:
   6191     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   6192     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   6193          /* In TH the maximum weight will be 127 */
   6194         *weight_max =
   6195             (1 << soc_mem_field_length(unit, MMU_QSCH_L0_WEIGHT_MEMm,
   6196                                        WEIGHTf)) - 1;
   6197         break;
   6198     default:
   6199         return BCM_E_PARAM;
   6200     }
   6201 
   6202     return BCM_E_NONE;
   6203 }
   6204 
   6205 
   6206 /*
   6207  * Function:
   6208  *     bcm_th3_cosq_gport_get
   6209  * Purpose:
   6210  *     Get a cosq gport structure
   6211  * Parameters:
   6212  *     unit  - (IN) unit number
   6213  *     gport - (IN) GPORT identifier
   6214  *     port  - (OUT) port number
   6215  *     numq  - (OUT) number of COS queues
   6216  *     flags - (OUT) flags (BCM_COSQ_GPORT_XXX)
   6217  * Returns:
   6218  *     BCM_E_XXX
   6219  */
   6220 int
   6221 bcm_th3_cosq_gport_get(int unit, bcm_gport_t gport, bcm_gport_t *port,
   6222                       int *numq, uint32 *flags)
   6223 {
   6224     _bcm_th3_cosq_node_t *node;
   6225     bcm_port_t local_port;
   6226     bcm_module_t modid;
   6227     _bcm_gport_dest_t dest;
   6228 
   6229     if (port == NULL || numq == NULL || flags == NULL) {
   6230         return BCM_E_PARAM;
   6231     }
   6232 
   6233     if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   6234          BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6235          BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   6236          BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport)) {
   6237         BCM_IF_ERROR_RETURN
   6238             (_bcm_th3_cosq_node_get(unit, gport, NULL, &local_port,
   6239                                    NULL, &node));
   6240 
   6241         *numq = node->numq;
   6242 
   6243         if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6244             *flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP;
   6245         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6246             *flags = BCM_COSQ_GPORT_MCAST_QUEUE_GROUP;
   6247         } else if (BCM_GPORT_IS_SCHEDULER(gport)) {
   6248             *flags = BCM_COSQ_GPORT_SCHEDULER;
   6249         } else {
   6250             *flags = 0;
   6251         }
   6252     } else {
   6253         BCM_IF_ERROR_RETURN
   6254             (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   6255         *flags = 0;
   6256         *numq = _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   6257     }
   6258 
   6259     if (SOC_USE_GPORT(unit)) {
   6260         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid));
   6261         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
   6262         dest.modid = modid;
   6263         dest.port = local_port;
   6264         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, port));
   6265     } else {
   6266         *port = local_port;
   6267     }
   6268 
   6269     LOG_INFO(BSL_LS_BCM_COSQ,
   6270         (BSL_META_U(unit,
   6271         "port=0x%x numq=%d flags=0x%x\n"),
   6272         *port, *numq, *flags));
   6273 
   6274     return BCM_E_NONE;
   6275 }
   6276 
   6277 /*
   6278  * Function:
   6279  *     bcm_tomahawk3_cosq_schedq_mapping_set
   6280  * Purpose:
   6281  *     Get a cosq gport structure
   6282  * Parameters:
   6283  *     unit             - (IN) unit number
   6284  *     profile_index    - (IN) Profile index
   6285  *     size             - (OUT) Array size
   6286  *     cosq_mapping_arr - (OUT) Cosq mapping
   6287  * Returns:
   6288  *     BCM_E_XXX
   6289  */
   6290 int
   6291 bcm_tomahawk3_cosq_schedq_mapping_set(int unit, int profile_index,
   6292     int size, bcm_cosq_mapping_t *cosq_mapping_arr)
   6293 {
   6294     _soc_mmu_cfg_scheduler_profile_t *sched_profile;
   6295     int cosq_idx, cos;
   6296     int L0[_BCM_TH3_COS_MAX];
   6297     int schedq[_BCM_TH3_COS_MAX];
   6298     int mmuq[_BCM_TH3_COS_MAX];
   6299     int cos_list[_BCM_TH3_COS_MAX];
   6300     int strict_priority[_BCM_TH3_COS_MAX];
   6301     int fc_is_uc_only[_BCM_TH3_COS_MAX];
   6302     bcm_port_t port;
   6303     int rv = BCM_E_NONE;
   6304 
   6305     if (profile_index < 0 || profile_index >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   6306         return BCM_E_PARAM;
   6307     }
   6308     if (cosq_mapping_arr == NULL) {
   6309         return BCM_E_PARAM;
   6310     }
   6311     if (size < 0 || size > _BCM_TH3_COS_MAX) {
   6312         return BCM_E_PARAM;
   6313     }
   6314 
   6315     sched_profile = soc_mmu_cfg_scheduler_profile_alloc(unit);
   6316 
   6317     for (cosq_idx = 0; cosq_idx < _BCM_TH3_COS_MAX; cosq_idx++) {
   6318         sched_profile[profile_index].num_unicast_queue[cosq_idx] = 0;
   6319         sched_profile[profile_index].num_multicast_queue[cosq_idx] = 0;
   6320         sched_profile[profile_index].strict_priority[cosq_idx] = 0;
   6321         sched_profile[profile_index].flow_control_only_unicast[cosq_idx] = 0;
   6322     }
   6323 
   6324     for (cosq_idx = 0; cosq_idx < size; cosq_idx++) {
   6325         cos = cosq_mapping_arr[cosq_idx].cosq;
   6326         sched_profile[profile_index].num_unicast_queue[cos] = cosq_mapping_arr[cosq_idx].num_ucq;
   6327         sched_profile[profile_index].num_multicast_queue[cos] = cosq_mapping_arr[cosq_idx].num_mcq;
   6328         sched_profile[profile_index].strict_priority[cos] = cosq_mapping_arr[cosq_idx].strict_priority;
   6329         sched_profile[profile_index].flow_control_only_unicast[cos] = cosq_mapping_arr[cosq_idx].fc_is_uc_only;
   6330         sched_profile[profile_index].valid = 1;
   6331     }
   6332     rv = _soc_mmu_tomahawk3_scheduler_profile_config_check(unit,
   6333                         profile_index, sched_profile);
   6334     if (rv != BCM_E_NONE) {
   6335         goto exit;
   6336     }
   6337 
   6338     rv = _soc_scheduler_profile_mapping_setup(unit,
   6339                         sched_profile, profile_index, L0, schedq, mmuq, cos_list,
   6340                         strict_priority, fc_is_uc_only);
   6341     if (rv != BCM_E_NONE) {
   6342         goto exit;
   6343     }
   6344 
   6345     /*initilization of L0.i->schedq.i->mmuq.i*/
   6346     LOG_INFO(BSL_LS_BCM_COSQ,
   6347         (BSL_META_U(unit, "Profile %d cos %d L0 %d schedq %d mmuq %d cos_list %d\n"),
   6348          profile_index, cosq_idx, L0[cosq_idx], schedq[cosq_idx], mmuq[cosq_idx], cos_list[cosq_idx]));
   6349     rv = soc_tomahawk3_sched_update_init(unit, profile_index, L0, schedq, mmuq, cos_list, strict_priority, fc_is_uc_only);
   6350     if (rv != BCM_E_NONE) {
   6351         goto exit;
   6352     }
   6353 
   6354     _BCM_TH3_MMU_INFO(unit)->gport_tree_created = FALSE;
   6355     PBMP_ALL_ITER(unit, port) {
   6356         if (IS_LB_PORT(unit, port)) {
   6357             continue;
   6358         }
   6359         rv = _bcm_th3_cosq_gport_tree_create(unit, port);
   6360         if (rv != BCM_E_NONE) {
   6361             goto exit;
   6362         }
   6363     }
   6364     _BCM_TH3_MMU_INFO(unit)->gport_tree_created = TRUE;
   6365 
   6366 exit:
   6367     soc_mmu_cfg_scheduler_profile_free(unit, sched_profile);
   6368 
   6369     return rv;
   6370 }
   6371 
   6372 
   6373 /*
   6374  * Function:
   6375  *     bcm_tomahawk3_cosq_schedq_mapping_get
   6376  * Purpose:
   6377  *     Get a cosq gport structure
   6378  * Parameters:
   6379  *     unit             - (IN) unit number
   6380  *     profile_index    - (IN) Profile index
   6381  *     size             - (OUT) Array size
   6382  *     cosq_mapping_arr - (OUT) Cosq mapping
   6383  * Returns:
   6384  *     BCM_E_XXX
   6385  */
   6386 int
   6387 bcm_tomahawk3_cosq_schedq_mapping_get(int unit, int profile_index,
   6388     int array_max, bcm_cosq_mapping_t *cosq_mapping_arr, int *size)
   6389 {
   6390     int cosq_idx, qidx;
   6391 
   6392     if (profile_index < 0 || profile_index >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
   6393         return BCM_E_PARAM;
   6394     }
   6395     if (array_max < 0 || array_max > _BCM_TH3_COS_MAX) {
   6396         return BCM_E_PARAM;
   6397     }
   6398     if (cosq_mapping_arr == NULL) {
   6399         return BCM_E_PARAM;
   6400     }
   6401     for (cosq_idx = 0; cosq_idx < array_max; cosq_idx++) {
   6402         cosq_mapping_arr[cosq_idx].cosq = cosq_idx;
   6403         cosq_mapping_arr[cosq_idx].num_ucq = -1;
   6404         cosq_mapping_arr[cosq_idx].num_mcq = -1;
   6405         cosq_mapping_arr[cosq_idx].strict_priority = 0;
   6406         cosq_mapping_arr[cosq_idx].fc_is_uc_only = 0;
   6407     }
   6408 
   6409     cosq_idx = 0;
   6410     for (qidx = 0; qidx < _BCM_TH3_MAX_NUM_QUEUE_PER_PORT; qidx++) {
   6411         if (cosq_idx >= array_max) {
   6412             break;
   6413         }
   6414         if (th3_sched_profile_info[unit][profile_index][qidx].cos == -1) {
   6415             continue;
   6416         }
   6417         cosq_mapping_arr[cosq_idx].cosq = th3_sched_profile_info[unit][profile_index][qidx].cos;
   6418         if (th3_sched_profile_info[unit][profile_index][qidx].mmuq[0] != -1) {
   6419             cosq_mapping_arr[cosq_idx].num_ucq = 0;
   6420             cosq_mapping_arr[cosq_idx].num_mcq = 0;
   6421             if (th3_sched_profile_info[unit][profile_index][qidx].mmuq[0] <
   6422                 _bcm_th3_get_num_ucq(unit)) {
   6423                 cosq_mapping_arr[cosq_idx].num_ucq++;
   6424             } else {
   6425                 cosq_mapping_arr[cosq_idx].num_mcq++;
   6426             }
   6427         }
   6428         if (th3_sched_profile_info[unit][profile_index][qidx].mmuq[1] != -1) {
   6429             if (th3_sched_profile_info[unit][profile_index][qidx].mmuq[1] <
   6430                 _bcm_th3_get_num_ucq(unit)) {
   6431                 cosq_mapping_arr[cosq_idx].num_ucq++;
   6432             } else {
   6433                 cosq_mapping_arr[cosq_idx].num_mcq++;
   6434             }
   6435         }
   6436         cosq_mapping_arr[cosq_idx].strict_priority =
   6437             th3_sched_profile_info[unit][profile_index][qidx].strict_priority;
   6438         cosq_mapping_arr[cosq_idx].fc_is_uc_only =
   6439             th3_sched_profile_info[unit][profile_index][qidx].fc_is_uc_only;
   6440         cosq_idx++;
   6441     }
   6442 
   6443     *size = cosq_idx;
   6444 
   6445     return BCM_E_NONE;
   6446 }
   6447 
   6448 /* Registers accessed for IDB APIs */
   6449 static const soc_mem_t
   6450     obm_pri_map_mem[_TH3_PBLKS_PER_PIPE][_TH3_PORTS_PER_PBLK] = {
   6451      {IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m,
   6452       IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m,
   6453       IDB_OBM0_PRI_MAP_PORT4m, IDB_OBM0_PRI_MAP_PORT5m,
   6454       IDB_OBM0_PRI_MAP_PORT6m, IDB_OBM0_PRI_MAP_PORT7m},
   6455      {IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m,
   6456       IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m,
   6457       IDB_OBM1_PRI_MAP_PORT4m, IDB_OBM1_PRI_MAP_PORT5m,
   6458       IDB_OBM1_PRI_MAP_PORT6m, IDB_OBM1_PRI_MAP_PORT7m},
   6459      {IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m,
   6460       IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m,
   6461       IDB_OBM2_PRI_MAP_PORT4m, IDB_OBM2_PRI_MAP_PORT5m,
   6462       IDB_OBM2_PRI_MAP_PORT6m, IDB_OBM2_PRI_MAP_PORT7m},
   6463      {IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m,
   6464       IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m,
   6465       IDB_OBM3_PRI_MAP_PORT4m, IDB_OBM3_PRI_MAP_PORT5m,
   6466       IDB_OBM3_PRI_MAP_PORT6m, IDB_OBM3_PRI_MAP_PORT7m},
   6467     };
   6468 static const soc_mem_t
   6469     obm_dscp_map_mem[_TH3_PBLKS_PER_PIPE][_TH3_PORTS_PER_PBLK] = {
   6470      {IDB_OBM0_DSCP_MAP_PORT0m, IDB_OBM0_DSCP_MAP_PORT1m,
   6471       IDB_OBM0_DSCP_MAP_PORT2m, IDB_OBM0_DSCP_MAP_PORT3m,
   6472       IDB_OBM0_DSCP_MAP_PORT4m, IDB_OBM0_DSCP_MAP_PORT5m,
   6473       IDB_OBM0_DSCP_MAP_PORT6m, IDB_OBM0_DSCP_MAP_PORT7m},
   6474      {IDB_OBM1_DSCP_MAP_PORT0m, IDB_OBM1_DSCP_MAP_PORT1m,
   6475       IDB_OBM1_DSCP_MAP_PORT2m, IDB_OBM1_DSCP_MAP_PORT3m,
   6476       IDB_OBM1_DSCP_MAP_PORT4m, IDB_OBM1_DSCP_MAP_PORT5m,
   6477       IDB_OBM1_DSCP_MAP_PORT6m, IDB_OBM1_DSCP_MAP_PORT7m},
   6478      {IDB_OBM2_DSCP_MAP_PORT0m, IDB_OBM2_DSCP_MAP_PORT1m,
   6479       IDB_OBM2_DSCP_MAP_PORT2m, IDB_OBM2_DSCP_MAP_PORT3m,
   6480       IDB_OBM2_DSCP_MAP_PORT4m, IDB_OBM2_DSCP_MAP_PORT5m,
   6481       IDB_OBM2_DSCP_MAP_PORT6m, IDB_OBM2_DSCP_MAP_PORT7m},
   6482      {IDB_OBM3_DSCP_MAP_PORT0m, IDB_OBM3_DSCP_MAP_PORT1m,
   6483       IDB_OBM3_DSCP_MAP_PORT2m, IDB_OBM3_DSCP_MAP_PORT3m,
   6484       IDB_OBM3_DSCP_MAP_PORT4m, IDB_OBM3_DSCP_MAP_PORT5m,
   6485       IDB_OBM3_DSCP_MAP_PORT6m, IDB_OBM3_DSCP_MAP_PORT7m},
   6486     };
   6487 static const soc_field_t obm_ob_pri_fields[8] = {
   6488     OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf,
   6489     OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf,
   6490     OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf
   6491 };
   6492 
   6493 static const soc_reg_t obm_port_config_regs[_TH3_PBLKS_PER_PIPE] = {
   6494     IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr,
   6495     IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr
   6496 };
   6497 
   6498 /* New APIs for IDB */
   6499 STATIC int
   6500 _bcm_th3_enable_dscp_ob_pri_mapping (int unit, soc_reg_t reg, int index, int
   6501         inst) {
   6502 
   6503     uint32 rval = 0;
   6504     BCM_IF_ERROR_RETURN
   6505         (soc_reg32_get(unit, reg, inst, index, &rval));
   6506     soc_reg_field_set(unit, reg, &rval, TRUST_DSCPf, 1);
   6507     BCM_IF_ERROR_RETURN(
   6508         soc_reg32_set(unit, reg, inst, index, rval));
   6509 
   6510 
   6511     return BCM_E_NONE;
   6512 }
   6513 
   6514 /*
   6515  * Function:
   6516  *     bcm_tomahawk3_obm_port_pri_traffic_class_mapping_set
   6517  * Purpose:
   6518  *     Determine which COS queue a given priority currently maps to.
   6519  * Parameters:
   6520  *     unit     - (IN) unit number
   6521  *     port     - (IN) port number
   6522  *     priority_type - (IN) Lookup priority type
   6523  *     obm_tc     - (IN) OBM traffic class to be mapped
   6524  * Returns:
   6525  *     BCM_E_XXX
   6526  */
   6527 int
   6528 bcm_tomahawk3_obm_port_pri_traffic_class_mapping_set(int unit, bcm_port_t port,
   6529         bcm_obm_lookup_priority_type_t piority_type, int priority,
   6530                         bcm_obm_traffic_class_t obm_tc)
   6531 {
   6532     int phy_port, pm_num, pipe, subp;
   6533     soc_mem_t mem = INVALIDm;
   6534     soc_reg_t reg = INVALIDr;
   6535     soc_field_t field = INVALIDf, reg_field = INVALIDf;
   6536     soc_info_t *si = &SOC_INFO(unit);
   6537     int index, field_val, reg_field_val = 0;
   6538     uint32 rval;
   6539     uint32 entry[SOC_MAX_MEM_WORDS];
   6540 
   6541     if (!SOC_PORT_VALID(unit, port)) {
   6542         return BCM_E_PORT;
   6543     }
   6544     if (priority < 0 || priority >= 8) {
   6545         return BCM_E_PARAM;
   6546     }
   6547 
   6548     switch(obm_tc) {
   6549         case bcmObmClassLossyLow:
   6550             field_val = 0;
   6551             break;
   6552         case bcmObmClassLossyHigh:
   6553             field_val = 1;
   6554             break;
   6555         case bcmObmClassLossless0:
   6556             field_val = 2;
   6557             break;
   6558         case bcmObmClassLossless1:
   6559             field_val = 3;
   6560             break;
   6561         default:
   6562             return BCM_E_PARAM;
   6563     }
   6564 
   6565     phy_port = si->port_l2p_mapping[port];
   6566     pipe = si->port_pipe[port];
   6567     pm_num = soc_tomahawk3_get_pipe_pm_from_phy_port(phy_port);
   6568     subp = soc_tomahawk3_get_subp_from_phy_port(phy_port);
   6569 
   6570     switch(piority_type) {
   6571         case bcmObmPriorityTypeVLAN:
   6572             mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, obm_pri_map_mem[pm_num][subp],
   6573                     pipe);
   6574             field = obm_ob_pri_fields[priority];
   6575             index = 0;
   6576             break;
   6577         case bcmObmPriorityTypeDSCP:
   6578             mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, obm_dscp_map_mem[pm_num][subp],
   6579                     pipe);
   6580             field = obm_ob_pri_fields[priority];
   6581             index = 0;
   6582             BCM_IF_ERROR_RETURN(
   6583                 _bcm_th3_enable_dscp_ob_pri_mapping(unit,
   6584                     obm_port_config_regs[pm_num], subp, pipe));
   6585             break;
   6586         case bcmObmPriorityTypeUntagged:
   6587             reg = obm_port_config_regs[pm_num];
   6588             reg_field = PORT_PRIf;
   6589             index = subp;
   6590             reg_field_val = priority;
   6591             mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, obm_pri_map_mem[pm_num][subp],
   6592                     pipe);
   6593             field = obm_ob_pri_fields[priority];
   6594             break;
   6595         default:
   6596             return BCM_E_PARAM;
   6597     }
   6598 
   6599     if (mem!= INVALIDm && field != INVALIDf) {
   6600         BCM_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   6601                     index, &entry));
   6602         soc_mem_field32_set(unit, mem, &entry, field , field_val);
   6603         BCM_IF_ERROR_RETURN
   6604             (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry));
   6605     }
   6606     if (reg != INVALIDr && reg_field != INVALIDf) {
   6607         rval = 0;
   6608         BCM_IF_ERROR_RETURN
   6609             (soc_reg32_get(unit, reg, pipe, index, &rval));
   6610         soc_reg_field_set(unit, reg, &rval, reg_field, reg_field_val);
   6611         BCM_IF_ERROR_RETURN(
   6612             soc_reg32_set(unit, reg, pipe, index, rval));
   6613     }
   6614     return BCM_E_NONE;
   6615 }
   6616 
   6617 /*
   6618  * Function:
   6619  *     bcm_tomahawk3_obm_port_pri_traffic_class_mapping_get
   6620  * Purpose:
   6621  *     Determine which COS queue a given priority currently maps to.
   6622  * Parameters:
   6623  *     unit     - (IN) unit number
   6624  *     port     - (IN) port number
   6625  *     priority_type - (IN) Lookup priority type
   6626  *     obm_tc     - (OUT) OBM traffic class to be mapped
   6627  * Returns:
   6628  *     BCM_E_XXX
   6629  */
   6630 int
   6631 bcm_tomahawk3_obm_port_pri_traffic_class_mapping_get(int unit, bcm_port_t port,
   6632         bcm_obm_lookup_priority_type_t piority_type, int priority,
   6633                         bcm_obm_traffic_class_t *obm_tc)
   6634 {
   6635     int phy_port, pm_num, pipe, subp;
   6636     soc_mem_t mem = INVALIDm;
   6637     soc_reg_t reg = INVALIDr;
   6638     soc_field_t field = INVALIDf;
   6639     soc_info_t *si = &SOC_INFO(unit);
   6640     int index, field_val;
   6641     uint32 rval;
   6642     uint32 entry[SOC_MAX_MEM_WORDS];
   6643     int untag_pri;
   6644 
   6645     if (!SOC_PORT_VALID(unit, port)) {
   6646         return BCM_E_PORT;
   6647     }
   6648     if (priority < 0 || priority >= 8) {
   6649         return BCM_E_PARAM;
   6650     }
   6651 
   6652     phy_port = si->port_l2p_mapping[port];
   6653     pipe = si->port_pipe[port];
   6654     pm_num = soc_tomahawk3_get_pipe_pm_from_phy_port(phy_port);
   6655     subp = soc_tomahawk3_get_subp_from_phy_port(phy_port);
   6656 
   6657     switch(piority_type) {
   6658         case bcmObmPriorityTypeVLAN:
   6659             mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, obm_pri_map_mem[pm_num][subp],
   6660                     pipe);
   6661             field = obm_ob_pri_fields[priority];
   6662             index = 0;
   6663             BCM_IF_ERROR_RETURN(
   6664                 soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry));
   6665             field_val = soc_mem_field32_get(unit, mem, entry, field);
   6666             break;
   6667         case bcmObmPriorityTypeDSCP:
   6668             mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, obm_dscp_map_mem[pm_num][subp],
   6669                     pipe);
   6670             field = obm_ob_pri_fields[priority];
   6671             index = 0;
   6672             BCM_IF_ERROR_RETURN(
   6673                 soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry));
   6674             field_val = soc_mem_field32_get(unit, mem, entry, field);
   6675             break;
   6676         case bcmObmPriorityTypeUntagged:
   6677             reg = obm_port_config_regs[pm_num];
   6678             field = PORT_PRIf;
   6679             index = subp;
   6680             BCM_IF_ERROR_RETURN(
   6681                 soc_reg32_get(unit, reg, index, 0, &rval));
   6682             untag_pri = soc_reg_field_get(unit, reg, rval, field);
   6683             field = obm_ob_pri_fields[untag_pri];
   6684             index = 0;
   6685             mem = SOC_MEM_UNIQUE_ACC_PIPE(unit, obm_pri_map_mem[pm_num][subp],
   6686                     pipe);
   6687             BCM_IF_ERROR_RETURN(
   6688                 soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry));
   6689             field_val = soc_mem_field32_get(unit, mem, entry, field);
   6690             break;
   6691         default:
   6692             return BCM_E_PARAM;
   6693     }
   6694     switch(field_val) {
   6695         case 0:
   6696             *obm_tc = bcmObmClassLossyLow;
   6697             break;
   6698         case 1:
   6699             *obm_tc = bcmObmClassLossyHigh;
   6700             break;
   6701         case 2:
   6702             *obm_tc = bcmObmClassLossless0;
   6703             break;
   6704         case 3:
   6705             *obm_tc = bcmObmClassLossless1;
   6706             break;
   6707         default:
   6708             return BCM_E_INTERNAL;
   6709     }
   6710 
   6711 
   6712     return BCM_E_NONE;
   6713 }
   6714 
   6715 static const soc_reg_t obm_max_use_config_regs[4] = {
   6716     IDB_OBM0_MAX_USAGE_SELECTr, IDB_OBM1_MAX_USAGE_SELECTr,
   6717     IDB_OBM2_MAX_USAGE_SELECTr, IDB_OBM3_MAX_USAGE_SELECTr
   6718 };
   6719 
   6720 int
   6721 bcm_tomahawk3_obm_port_max_usage_mode_get (int unit, bcm_port_t port,
   6722         bcm_obm_max_watermark_mode_t *obm_wm_mode) {
   6723     int pipe, pm_num, phy_port;
   6724     uint32 rval;
   6725     soc_field_t field = PRIORITY_SELECTf;
   6726     soc_info_t *si = &SOC_INFO(unit);
   6727 
   6728     if (!SOC_PORT_VALID(unit, port)) {
   6729         return BCM_E_PORT;
   6730     }
   6731 
   6732     phy_port = si->port_l2p_mapping[port];
   6733     pipe = si->port_pipe[port];
   6734     pm_num = soc_tomahawk3_get_pipe_pm_from_phy_port(phy_port);
   6735 
   6736     BCM_IF_ERROR_RETURN(
   6737                 soc_reg32_get(unit, obm_max_use_config_regs[pm_num], pipe, 0,
   6738                     &rval));
   6739     *obm_wm_mode = soc_reg_field_get(unit, obm_max_use_config_regs[pm_num], rval,
   6740             field);
   6741 
   6742     return BCM_E_NONE;
   6743 }
   6744 
   6745 int
   6746 bcm_tomahawk3_obm_port_max_usage_mode_set (int unit, bcm_port_t port,
   6747         bcm_obm_max_watermark_mode_t obm_wm_mode) {
   6748     int pipe, pm_num, phy_port;
   6749     int field_val;
   6750     uint32 rval;
   6751     soc_field_t field = PRIORITY_SELECTf;
   6752     soc_info_t *si = &SOC_INFO(unit);
   6753 
   6754     if (!SOC_PORT_VALID(unit, port)) {
   6755         return BCM_E_PORT;
   6756     }
   6757 
   6758     phy_port = si->port_l2p_mapping[port];
   6759     pipe = si->port_pipe[port];
   6760     pm_num = soc_tomahawk3_get_pipe_pm_from_phy_port(phy_port);
   6761 
   6762     switch(obm_wm_mode) {
   6763         case bcmObmMaxUsageModeAllTraffic:
   6764             field_val = 0;
   6765             break;
   6766         case bcmObmMaxUsageModeLossy:
   6767             field_val = 1;
   6768             break;
   6769         case bcmObmMaxUsageModeLossless0:
   6770             field_val = 2;
   6771             break;
   6772         case bcmObmMaxUsageModeLossless1:
   6773             field_val = 3;
   6774             break;
   6775         default:
   6776             return BCM_E_PARAM;
   6777 
   6778     }
   6779 
   6780     BCM_IF_ERROR_RETURN(
   6781         soc_reg32_get(unit, obm_max_use_config_regs[pm_num], pipe, 0, &rval));
   6782     soc_reg_field_set(unit, obm_max_use_config_regs[pm_num], &rval, field,
   6783             field_val);
   6784     BCM_IF_ERROR_RETURN(
   6785         soc_reg32_set(unit, obm_max_use_config_regs[pm_num], pipe, 0, rval));
   6786 
   6787     return BCM_E_NONE;
   6788 }
   6789 
   6790 static const soc_reg_t obm_priority_profile_regs[4] = {
   6791     IDB_OBM0_FLOW_CONTROL_CONFIGr, IDB_OBM1_FLOW_CONTROL_CONFIGr,
   6792     IDB_OBM2_FLOW_CONTROL_CONFIGr, IDB_OBM3_FLOW_CONTROL_CONFIGr
   6793 };
   6794 
   6795 int
   6796 bcm_tomahawk3_obm_traffic_class_pfc_priority_mapping_set (int unit, bcm_port_t port,
   6797         bcm_obm_traffic_class_t obm_tc, int max_pri_count,
   6798         int* priority_list) {
   6799 
   6800     int pipe, pm_num, phy_port, subp;
   6801     uint64 rval;
   6802     soc_field_t field;
   6803     soc_info_t *si = &SOC_INFO(unit);
   6804     int array_idx, pri_val;
   6805     int field_val = 0;
   6806 
   6807     if (!SOC_PORT_VALID(unit, port)) {
   6808         return BCM_E_PORT;
   6809     }
   6810     if (max_pri_count <= 0 || max_pri_count > 8) {
   6811         return BCM_E_PARAM;
   6812     }
   6813     switch (obm_tc) {
   6814         case bcmObmClassLossless0:
   6815             field = LOSSLESS0_PRIORITY_PROFILEf;
   6816             break;
   6817         case bcmObmClassLossless1:
   6818             field = LOSSLESS1_PRIORITY_PROFILEf;
   6819             break;
   6820         default:
   6821             return BCM_E_PARAM;
   6822     }
   6823 
   6824     for (array_idx = 0; array_idx < max_pri_count; array_idx ++) {
   6825         pri_val = priority_list[array_idx];
   6826         if (pri_val < 0 || pri_val >= 8) {
   6827             return BCM_E_PARAM;
   6828         }
   6829         field_val |= (1 << pri_val);
   6830     }
   6831 
   6832     phy_port = si->port_l2p_mapping[port];
   6833     pipe = si->port_pipe[port];
   6834     pm_num = soc_tomahawk3_get_pipe_pm_from_phy_port(phy_port);
   6835     subp = soc_tomahawk3_get_subp_from_phy_port(phy_port);
   6836 
   6837     BCM_IF_ERROR_RETURN(
   6838         soc_reg64_get(unit, obm_priority_profile_regs[pm_num], pipe, subp, &rval));
   6839     soc_reg64_field32_set(unit, obm_priority_profile_regs[pm_num], &rval, field,
   6840             field_val);
   6841     BCM_IF_ERROR_RETURN(
   6842         soc_reg64_set(unit, obm_priority_profile_regs[pm_num], pipe, subp, rval));
   6843 
   6844     return BCM_E_NONE;
   6845 }
   6846 
   6847 int
   6848 bcm_tomahawk3_obm_traffic_class_pfc_priority_mapping_get (int unit, bcm_port_t port,
   6849         bcm_obm_traffic_class_t obm_tc, int max_pri_count,
   6850         int* priority_list, int* pri_count) {
   6851 
   6852     int pipe, pm_num, phy_port, subp;
   6853     uint64 rval;
   6854     soc_field_t field;
   6855     soc_info_t *si = &SOC_INFO(unit);
   6856     int field_val, pri_val, array_idx = 0;
   6857 
   6858     if (!SOC_PORT_VALID(unit, port)) {
   6859         return BCM_E_PORT;
   6860     }
   6861     if (max_pri_count <= 0 || max_pri_count > 8) {
   6862         return BCM_E_PARAM;
   6863     }
   6864     switch (obm_tc) {
   6865         case bcmObmClassLossless0:
   6866             field = LOSSLESS0_PRIORITY_PROFILEf;
   6867             break;
   6868         case bcmObmClassLossless1:
   6869             field = LOSSLESS1_PRIORITY_PROFILEf;
   6870             break;
   6871         default:
   6872             return BCM_E_PARAM;
   6873     }
   6874 
   6875     phy_port = si->port_l2p_mapping[port];
   6876     pipe = si->port_pipe[port];
   6877     pm_num = soc_tomahawk3_get_pipe_pm_from_phy_port(phy_port);
   6878     subp = soc_tomahawk3_get_subp_from_phy_port(phy_port);
   6879 
   6880     BCM_IF_ERROR_RETURN(
   6881                 soc_reg_get(unit, obm_priority_profile_regs[pm_num], pipe,
   6882                     subp, &rval));
   6883     field_val = soc_reg64_field32_get(unit, obm_priority_profile_regs[pm_num], rval,
   6884             field);
   6885     for (pri_val = 0; pri_val < 8 ; pri_val++) {
   6886         if ((field_val == 0) || (array_idx == max_pri_count)) {
   6887             break;
   6888         }
   6889         if ((field_val >> pri_val) & 1) {
   6890             priority_list[array_idx++] = pri_val;
   6891         }
   6892     }
   6893     *pri_count = array_idx;
   6894     return BCM_E_NONE;
   6895 }
   6896 
   6897 /*
   6898  * Function:
   6899  *     _bcm_th3_cosq_bucket_set
   6900  * Purpose:
   6901  *     Get COS queue bandwidth control bucket setting
   6902  * Parameters:
   6903  *     unit          - (IN) unit number
   6904  *     gport         - (IN) port number or GPORT identifier
   6905  *     cosq          - (IN) COS queue number
   6906  *     min_quantum   - (OUT) kbps or packet/second
   6907  *     max_quantum   - (OUT) kbps or packet/second
   6908  *     burst_quantum - (OUT) kbps or packet/second
   6909  *     flags         - (IN)
   6910  * Returns:
   6911  *     BCM_E_XXX
   6912  * Notes:
   6913  *     If port is any form of local port, cosq is the hardware queue index.
   6914  */
   6915 STATIC int
   6916 _bcm_th3_cosq_bucket_set(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
   6917                         uint32 min_quantum, uint32 max_quantum,
   6918                         uint32 kbits_burst_min, uint32 kbits_burst_max,
   6919                         uint32 flags)
   6920 {
   6921     _bcm_th3_cosq_node_t *node = NULL;
   6922     bcm_port_t local_port;
   6923     uint32 rval, meter_flags;
   6924     uint32 bucketsize_max, bucketsize_min;
   6925     uint32 granularity_max, granularity_min;
   6926     uint32 refresh_rate_max, refresh_rate_min;
   6927     int refresh_bitsize = 0, bucket_bitsize = 0;
   6928     int pipe, local_mmu_port, index;
   6929     soc_mem_t config_mem = INVALIDm;
   6930     uint32 entry[SOC_MAX_MEM_WORDS];
   6931     soc_info_t *si = &SOC_INFO(unit);
   6932     int cpu_mc_base = 0;
   6933 
   6934     if (cosq < 0) {
   6935         if (cosq == -1) {
   6936             /* caller needs to resolve the wild card value (-1) */
   6937             return BCM_E_INTERNAL;
   6938         } else { /* reject all other negative value */
   6939             return BCM_E_PARAM;
   6940         }
   6941     }
   6942 
   6943     BCM_IF_ERROR_RETURN
   6944         (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   6945 
   6946     BCM_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   6947 
   6948     local_mmu_port = SOC_TH3_MMU_LOCAL_PORT(unit, local_port);
   6949 
   6950     if (BCM_GPORT_IS_SET(gport) &&
   6951         ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   6952           BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   6953           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   6954           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport))) {
   6955 
   6956         BCM_IF_ERROR_RETURN
   6957             (_bcm_th3_cosq_node_get(unit, gport, NULL,
   6958                                    NULL, NULL, &node));
   6959     }
   6960 
   6961     if (node) {
   6962         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   6963             if (node->level == SOC_TH3_NODE_LVL_L0) {
   6964                 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L0_Am)[pipe];
   6965                 cosq = node->hw_index % _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   6966                 index = ((local_mmu_port & (SOC_TH3_MMU_PORT_STRIDE - 1)) *
   6967                          _BCM_TH3_NUM_SCHEDULER_PER_PORT) + cosq;
   6968             } else {
   6969                 return BCM_E_PARAM;
   6970             }
   6971         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   6972             /* L1 level metering is supported only for CPU.
   6973                CPU has only multicast queues.
   6974                So cannot be Unicast type */
   6975                 return BCM_E_PARAM;
   6976         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   6977             /* L1 level metering is supported only for CPU */
   6978             if (!IS_CPU_PORT(unit, local_port)) {
   6979                 return BCM_E_PORT;
   6980             }
   6981             config_mem = MMU_MTRO_CPU_L1_Am;
   6982             cosq = node->hw_index % si->port_num_cosq[local_port];
   6983 
   6984             /*Adjust mc cosq for cpu port*/
   6985             cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   6986             cosq = (node->hw_index - cpu_mc_base) %
   6987                    _BCM_TH3_NUM_CPU_MCAST_QUEUE;
   6988             index = cosq;
   6989         } else {
   6990             return BCM_E_PARAM;
   6991         }
   6992     } else {
   6993         if ((cosq < 0) || (cosq >= _TH3_PORT_NUM_COS(unit, local_port))) {
   6994             return BCM_E_PARAM;
   6995         }
   6996         if (!IS_CPU_PORT(unit, local_port)) {
   6997             index = ((local_mmu_port & (SOC_TH3_MMU_PORT_STRIDE - 1)) *
   6998                      _BCM_TH3_NUM_SCHEDULER_PER_PORT) + cosq;
   6999             config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L0_Am)[pipe];
   7000         } else {
   7001             /* For CPU port, refer L1 memory directly */
   7002             config_mem = MMU_MTRO_CPU_L1_Am;
   7003             
   7004             index = cosq;
   7005         }
   7006     }
   7007 
   7008     /*
   7009      * COVERITY
   7010      *
   7011      * This checker will not be True.
   7012      * It is kept intentionally as a defensive case for future development.
   7013      */
   7014     /* coverity[dead_error_line] */
   7015     if (config_mem == INVALIDm) {
   7016         return BCM_E_PARAM;
   7017     }
   7018 
   7019     meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ?
   7020                             _BCM_TH3_METER_FLAG_PACKET_MODE : 0;
   7021 
   7022     BCM_IF_ERROR_RETURN(READ_MMU_MTRO_CONFIGr(unit, &rval));
   7023     if (soc_reg_field_get(unit, MMU_MTRO_CONFIGr, rval, ITU_MODE_SELf)) {
   7024         meter_flags |= _BCM_TH3_METER_FLAG_NON_LINEAR;
   7025     }
   7026 
   7027 
   7028     refresh_bitsize = soc_mem_field_length(unit, config_mem, MAX_REFRESHf);
   7029     bucket_bitsize = soc_mem_field_length(unit, config_mem, MAX_THD_SELf);
   7030     BCM_IF_ERROR_RETURN
   7031         (_bcm_th3_rate_to_bucket_encoding(unit, max_quantum, kbits_burst_max,
   7032                                            meter_flags, refresh_bitsize,
   7033                                            bucket_bitsize, &refresh_rate_max,
   7034                                            &bucketsize_max, &granularity_max));
   7035 
   7036     refresh_bitsize = soc_mem_field_length(unit, config_mem, MIN_REFRESHf);
   7037     bucket_bitsize = soc_mem_field_length(unit, config_mem, MIN_THD_SELf);
   7038     BCM_IF_ERROR_RETURN
   7039         (_bcm_th3_rate_to_bucket_encoding(unit, min_quantum, kbits_burst_min,
   7040                                            meter_flags, refresh_bitsize,
   7041                                            bucket_bitsize, &refresh_rate_min,
   7042                                            &bucketsize_min, &granularity_min));
   7043 
   7044     sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS);
   7045     soc_mem_field32_set(unit, config_mem, &entry, MAX_METER_GRANf, granularity_max);
   7046     soc_mem_field32_set(unit, config_mem, &entry, MAX_REFRESHf, refresh_rate_max);
   7047     soc_mem_field32_set(unit, config_mem, &entry, MAX_THD_SELf, bucketsize_max);
   7048     soc_mem_field32_set(unit, config_mem, &entry, MIN_METER_GRANf, granularity_min);
   7049     soc_mem_field32_set(unit, config_mem, &entry, MIN_REFRESHf, refresh_rate_min);
   7050     soc_mem_field32_set(unit, config_mem, &entry, MIN_THD_SELf, bucketsize_min);
   7051     soc_mem_field32_set(unit, config_mem, &entry, PACKET_SHAPINGf, (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0);
   7052     BCM_IF_ERROR_RETURN
   7053         (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, index, &entry));
   7054 
   7055     return BCM_E_NONE;
   7056 }
   7057 
   7058 
   7059 /*
   7060  * Function:
   7061  *     _bcm_th3_cosq_bucket_get
   7062  * Purpose:
   7063  *     Get COS queue bandwidth control bucket setting
   7064  * Parameters:
   7065  *     unit          - (IN) unit number
   7066  *     gport         - (IN) port number or GPORT identifier
   7067  *     cosq          - (IN) COS queue number
   7068  *     min_quantum   - (OUT) kbps or packet/second
   7069  *     max_quantum   - (OUT) kbps or packet/second
   7070  *     burst_quantum - (OUT) kbps or packet/second
   7071  *     flags         - (IN)
   7072  * Returns:
   7073  *     BCM_E_XXX
   7074  * Notes:
   7075  *     If port is any form of local port, cosq is the hardware queue index.
   7076  */
   7077 STATIC int
   7078 _bcm_th3_cosq_bucket_get(int unit, bcm_port_t gport, bcm_cos_queue_t cosq,
   7079                         uint32 *min_quantum, uint32 *max_quantum,
   7080                         uint32 *kbits_burst_min, uint32 *kbits_burst_max,
   7081                         uint32 *flags)
   7082 {
   7083     _bcm_th3_cosq_node_t *node = NULL;
   7084     bcm_port_t local_port;
   7085     uint32 rval;
   7086     int local_mmu_port, index;
   7087     soc_mem_t config_mem = INVALIDm;
   7088     uint32 entry[SOC_MAX_MEM_WORDS];
   7089     soc_info_t *si = &SOC_INFO(unit);
   7090     int cpu_mc_base = 0;
   7091     int pipe;
   7092     uint32 refresh_rate, bucketsize, granularity, meter_flags;
   7093 
   7094     meter_flags = 0;
   7095 
   7096     LOG_INFO(BSL_LS_BCM_COSQ,
   7097              (BSL_META_U(unit,
   7098                          "gport: %d cosq: %d\n"),
   7099               gport, cosq));
   7100     if (cosq < 0) {
   7101         if (cosq == -1) {
   7102             /* caller needs to resolve the wild card value (-1) */
   7103             return BCM_E_INTERNAL;
   7104         } else { /* reject all other negative value */
   7105             return BCM_E_PARAM;
   7106         }
   7107     }
   7108 
   7109     BCM_IF_ERROR_RETURN
   7110         (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   7111     pipe = si->port_pipe[local_port];
   7112 
   7113     local_mmu_port = SOC_TH3_MMU_LOCAL_PORT(unit, local_port);
   7114 
   7115     if (BCM_GPORT_IS_SET(gport) &&
   7116         ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   7117           BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   7118           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport) ||
   7119           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(gport))) {
   7120 
   7121         BCM_IF_ERROR_RETURN
   7122             (_bcm_th3_cosq_node_get(unit, gport, NULL,
   7123                                    NULL, NULL, &node));
   7124     }
   7125 
   7126     if (node) {
   7127         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   7128             if (node->level == SOC_TH3_NODE_LVL_L0) {
   7129                 config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L0_Am)[pipe];
   7130                 cosq = node->hw_index % _BCM_TH3_NUM_SCHEDULER_PER_PORT;
   7131                 index = ((local_mmu_port & (SOC_TH3_MMU_PORT_STRIDE - 1)) *
   7132                          _BCM_TH3_NUM_SCHEDULER_PER_PORT) + cosq;
   7133             } else {
   7134                 return BCM_E_PARAM;
   7135             }
   7136         } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
   7137             /* L1 level metering is supported only for CPU
   7138                so cannot be Unicast type */
   7139                 return BCM_E_PARAM;
   7140         } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7141             /* L1 level metering is supported only for CPU */
   7142             if (!IS_CPU_PORT(unit, local_port)) {
   7143                 return BCM_E_PORT;
   7144             }
   7145             config_mem = MMU_MTRO_CPU_L1_Am;
   7146             cosq = node->hw_index % si->port_num_cosq[local_port];
   7147 
   7148             /*Adjust mc cosq for cpu port*/
   7149             cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   7150             cosq = (node->hw_index - cpu_mc_base) %
   7151                    _BCM_TH3_NUM_CPU_MCAST_QUEUE;
   7152             index = cosq;
   7153         } else {
   7154             return BCM_E_PARAM;
   7155         }
   7156     } else {
   7157         if ((cosq < 0) || (cosq >= _TH3_PORT_NUM_COS(unit, local_port))) {
   7158             return BCM_E_PARAM;
   7159         }
   7160         if (!IS_CPU_PORT(unit, local_port)) {
   7161             index = ((local_mmu_port & (SOC_TH3_MMU_PORT_STRIDE - 1)) *
   7162                      _BCM_TH3_NUM_SCHEDULER_PER_PORT) + cosq;
   7163             config_mem = SOC_MEM_UNIQUE_ACC(unit, MMU_MTRO_L0_Am)[pipe];
   7164         } else {
   7165             /* For CPU port, refer L1 memory directly */
   7166             config_mem = MMU_MTRO_CPU_L1_Am;
   7167             index = cosq;
   7168         }
   7169     }
   7170 
   7171     /*
   7172      * COVERITY
   7173      *
   7174      * This checker will not be True.
   7175      * It is kept intentionally as a defensive case for future development.
   7176      */
   7177     /* coverity[dead_error_line] */
   7178     if (config_mem == INVALIDm) {
   7179         return BCM_E_PARAM;
   7180     }
   7181 
   7182     /* index = SOC_TH3_MMU_PIPED_MEM_INDEX(unit, local_port, config_mem, index); */
   7183 
   7184     if (min_quantum == NULL || max_quantum == NULL ||
   7185         kbits_burst_max == NULL || kbits_burst_min == NULL) {
   7186         return BCM_E_PARAM;
   7187     }
   7188 
   7189     BCM_IF_ERROR_RETURN
   7190         (soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, index, &entry));
   7191 
   7192     *flags = 0;
   7193     BCM_IF_ERROR_RETURN(READ_MMU_MTRO_CONFIGr(unit, &rval));
   7194     if (soc_reg_field_get(unit, MMU_MTRO_CONFIGr, rval, ITU_MODE_SELf)) {
   7195         meter_flags |= _BCM_TH3_METER_FLAG_NON_LINEAR;
   7196     }
   7197 
   7198     if (soc_mem_field32_get(unit, config_mem, &entry, PACKET_SHAPINGf)) {
   7199         meter_flags |= _BCM_TH3_METER_FLAG_PACKET_MODE;
   7200         *flags |= BCM_COSQ_BW_PACKET_MODE;
   7201     }
   7202 
   7203     granularity = soc_mem_field32_get(unit, config_mem, &entry, MAX_METER_GRANf);
   7204     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MAX_REFRESHf);
   7205     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MAX_THD_SELf);
   7206     BCM_IF_ERROR_RETURN
   7207         (_bcm_th3_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   7208                                            granularity, meter_flags,
   7209                                            max_quantum, kbits_burst_max));
   7210 
   7211     granularity = soc_mem_field32_get(unit, config_mem, &entry, MIN_METER_GRANf);
   7212     refresh_rate = soc_mem_field32_get(unit, config_mem, &entry, MIN_REFRESHf);
   7213     bucketsize = soc_mem_field32_get(unit, config_mem, &entry, MIN_THD_SELf);
   7214     BCM_IF_ERROR_RETURN
   7215         (_bcm_th3_bucket_encoding_to_rate(unit, refresh_rate, bucketsize,
   7216                                            granularity, meter_flags,
   7217                                            min_quantum, kbits_burst_min));
   7218     return BCM_E_NONE;
   7219 }
   7220 
   7221 /*
   7222  * Function:
   7223  *     bcm_th3_cosq_port_bandwidth_set
   7224  * Purpose:
   7225  *     Configure COS queue bandwidth control
   7226  * Parameters:
   7227  *     unit          - (IN) unit number
   7228  *     port          - (IN) port number or GPORT identifier
   7229  *     cosq          - (IN) COS queue number
   7230  *     min_quantum   - (IN)
   7231  *     max_quantum   - (IN)
   7232  *     burst_quantum - (IN)
   7233  *     flags         - (IN)
   7234  * Returns:
   7235  *     BCM_E_XXX
   7236  * Notes:
   7237  *     If port is any form of local port, cosq is the hardware queue index.
   7238  */
   7239 int
   7240 bcm_th3_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   7241                                bcm_cos_queue_t cosq,
   7242                                uint32 min_quantum, uint32 max_quantum,
   7243                                uint32 burst_quantum, uint32 flags)
   7244 {
   7245         return bcm_th3_cosq_gport_bandwidth_set(unit, port, cosq,
   7246                                                min_quantum, max_quantum,
   7247                                                flags);
   7248 }
   7249 
   7250 
   7251 /*
   7252  * Function:
   7253  *     bcm_th3_cosq_port_bandwidth_get
   7254  * Purpose:
   7255  *     Get COS queue bandwidth control configuration
   7256  * Parameters:
   7257  *     unit          - (IN) unit number
   7258  *     port          - (IN) port number or GPORT identifier
   7259  *     cosq          - (IN) COS queue number
   7260  *     min_quantum   - (OUT)
   7261  *     max_quantum   - (OUT)
   7262  *     burst_quantum - (OUT)
   7263  *     flags         - (OUT)
   7264  * Returns:
   7265  *     BCM_E_XXX
   7266  * Notes:
   7267  *     If port is any form of local port, cosq is the hardware queue index.
   7268  */
   7269 
   7270 int
   7271 bcm_th3_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   7272                                bcm_cos_queue_t cosq,
   7273                                uint32 *min_quantum, uint32 *max_quantum,
   7274                                uint32 *burst_quantum, uint32 *flags)
   7275 {
   7276     return bcm_th3_cosq_gport_bandwidth_get(unit, port, cosq,
   7277                                                min_quantum, max_quantum,
   7278                                                flags);
   7279 }
   7280 
   7281 /*
   7282  * Function:
   7283  *     bcm_th3_cosq_gport_bandwidth_burst_get
   7284  * Purpose:
   7285  *     Get COS queue bandwidth burst setting
   7286  * Parameters:
   7287  *     unit        - (IN) unit number
   7288  *     gport       - (IN) GPORT identifier
   7289  *     cosq        - (IN) COS queue to get, -1 for Queue 0
   7290  *     kbits_burst - (OUT) maximum burst, kbits
   7291  * Returns:
   7292  *     BCM_E_XXX
   7293  */
   7294 int
   7295 bcm_th3_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport,
   7296                                       bcm_cos_queue_t cosq,
   7297                                       uint32 *kbits_burst_min,
   7298                                       uint32 *kbits_burst_max)
   7299 {
   7300     uint32 kbits_sec_min, kbits_sec_max, flags;
   7301 
   7302     if (cosq < -1) {
   7303         return BCM_E_PARAM;
   7304     }
   7305 
   7306     BCM_IF_ERROR_RETURN
   7307         (_bcm_th3_cosq_bucket_get(unit, gport, cosq == -1 ? 0 : cosq,
   7308                                  &kbits_sec_min, &kbits_sec_max, kbits_burst_min,
   7309                                  kbits_burst_max, &flags));
   7310 
   7311     return BCM_E_NONE;
   7312 }
   7313 
   7314 /*
   7315  * Function:
   7316  *     bcm_th3_cosq_gport_bandwidth_burst_set
   7317  * Purpose:
   7318  *     Configure COS queue bandwidth burst setting
   7319  * Parameters:
   7320  *      unit        - (IN) unit number
   7321  *      gport       - (IN) GPORT identifier
   7322  *      cosq        - (IN) COS queue to configure, -1 for all COS queues
   7323  *      kbits_burst - (IN) maximum burst, kbits
   7324  * Returns:
   7325  *      BCM_E_XXX
   7326  */
   7327 
   7328 int
   7329 bcm_th3_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport,
   7330                                       bcm_cos_queue_t cosq,
   7331                                       uint32 kbits_burst_min,
   7332                                       uint32 kbits_burst_max)
   7333 {
   7334     int i, start_cos=0, end_cos=0;
   7335     uint32 kbits_sec_min, kbits_sec_max, kbits_sec_burst, flags;
   7336     bcm_port_t local_port;
   7337 
   7338     BCM_IF_ERROR_RETURN
   7339         (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   7340 
   7341     start_cos = end_cos = cosq;
   7342 
   7343     if (cosq == BCM_COS_INVALID) {
   7344         start_cos = 0;
   7345         end_cos = (IS_CPU_PORT(unit, local_port)) ?
   7346                    NUM_CPU_COSQ(unit) - 1 : _TH3_PORT_NUM_COS(unit, local_port)
   7347                    - 1;
   7348     }
   7349 
   7350     if (BCM_GPORT_IS_SET(gport)) {
   7351         if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   7352              BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   7353              BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   7354             start_cos = end_cos = 0;
   7355         }
   7356     }
   7357 
   7358     for (i = start_cos; i <= end_cos; i++) {
   7359         BCM_IF_ERROR_RETURN
   7360             (_bcm_th3_cosq_bucket_get(unit, gport, i, &kbits_sec_min,
   7361                                      &kbits_sec_max, &kbits_sec_burst,
   7362                                      &kbits_sec_burst, &flags));
   7363         BCM_IF_ERROR_RETURN
   7364             (_bcm_th3_cosq_bucket_set(unit, gport, i, kbits_sec_min,
   7365                                      kbits_sec_max, kbits_burst_min,
   7366                                      kbits_burst_max, flags));
   7367     }
   7368     return BCM_E_NONE;
   7369 }
   7370 
   7371 int
   7372 bcm_th3_cosq_port_pps_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   7373                          int pps)
   7374 {
   7375     uint32 min, max, burst, burst_min, flags;
   7376     bcm_port_t  local_port =  port;
   7377 
   7378     if (!IS_CPU_PORT(unit, port)) {
   7379         return BCM_E_PORT;
   7380     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   7381         return BCM_E_PARAM;
   7382     }
   7383 
   7384     if (BCM_GPORT_IS_SET(port) &&
   7385         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   7386           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   7387           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   7388           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   7389         return BCM_E_UNAVAIL;
   7390     }
   7391 
   7392     BCM_IF_ERROR_RETURN
   7393         (_bcm_th3_cosq_bucket_get(unit, port, cosq, &min, &max, &burst_min,
   7394                                     &burst, &flags));
   7395     min = pps;
   7396     burst_min = (min > 0) ?
   7397           _bcm_th3_default_burst_size(unit, local_port, min) : 0;
   7398     burst = burst_min;
   7399 
   7400     return _bcm_th3_cosq_bucket_set(unit, port, cosq, min, pps, burst_min,
   7401                                    burst, flags | BCM_COSQ_BW_PACKET_MODE);
   7402 }
   7403 
   7404 int
   7405 bcm_th3_cosq_port_pps_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   7406                          int *pps)
   7407 {
   7408     uint32 min, max, burst, flags;
   7409 
   7410     if (!IS_CPU_PORT(unit, port)) {
   7411         return BCM_E_PORT;
   7412     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   7413         return BCM_E_PARAM;
   7414     }
   7415 
   7416     if (BCM_GPORT_IS_SET(port) &&
   7417         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   7418           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   7419           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   7420           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   7421         return BCM_E_UNAVAIL;
   7422     }
   7423 
   7424     BCM_IF_ERROR_RETURN
   7425         (_bcm_th3_cosq_bucket_get(unit, port, cosq, &min, &max, &burst, &burst,
   7426                                  &flags));
   7427     *pps = max;
   7428 
   7429     return BCM_E_NONE;
   7430 }
   7431 
   7432 int
   7433 bcm_th3_cosq_port_burst_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   7434                            int burst)
   7435 {
   7436     uint32 min, max, cur_burst, flags;
   7437 
   7438     if (!IS_CPU_PORT(unit, port)) {
   7439         return BCM_E_PORT;
   7440     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   7441         return BCM_E_PARAM;
   7442     }
   7443 
   7444     if (BCM_GPORT_IS_SET(port) &&
   7445         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   7446           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   7447           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   7448           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   7449         return BCM_E_UNAVAIL;
   7450     }
   7451 
   7452     BCM_IF_ERROR_RETURN
   7453         (_bcm_th3_cosq_bucket_get(unit, port, cosq, &min, &max, &cur_burst,
   7454                                  &cur_burst, &flags));
   7455 
   7456     /* Replace the current BURST setting, keep PPS the same */
   7457 
   7458     return _bcm_th3_cosq_bucket_set(unit, port, cosq, min, max, burst, burst,
   7459                                    flags | BCM_COSQ_BW_PACKET_MODE);
   7460     return BCM_E_NONE;
   7461 }
   7462 
   7463 int
   7464 bcm_th3_cosq_port_burst_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   7465                            int *burst)
   7466 {
   7467     uint32 min, max, cur_burst, cur_burst_min, flags;
   7468 
   7469     if (!IS_CPU_PORT(unit, port)) {
   7470         return BCM_E_PORT;
   7471     } else if (cosq < 0 || cosq >= NUM_CPU_COSQ(unit)) {
   7472         return BCM_E_PARAM;
   7473     }
   7474 
   7475     if (BCM_GPORT_IS_SET(port) &&
   7476         ((BCM_GPORT_IS_SCHEDULER(port)) ||
   7477           BCM_GPORT_IS_UCAST_QUEUE_GROUP(port) ||
   7478           BCM_GPORT_IS_MCAST_QUEUE_GROUP(port) ||
   7479           BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(port))) {
   7480         return BCM_E_PARAM;
   7481     }
   7482 
   7483     BCM_IF_ERROR_RETURN
   7484         (_bcm_th3_cosq_bucket_get(unit, port, cosq, &min, &max,
   7485                                  &cur_burst_min, &cur_burst, &flags));
   7486     *burst = cur_burst;
   7487     return BCM_E_NONE;
   7488 }
   7489 
   7490 STATIC int
   7491 _bcm_th3_cosq_time_domain_set(int unit, int time_value, int *time_id)
   7492 {
   7493     int id;
   7494     uint32 time_domain_val;
   7495     soc_reg_t time_domain_reg = MMU_WRED_TIME_DOMAINr;
   7496 
   7497     if (time_value < 0 || time_value > 63) {
   7498         return SOC_E_PARAM;
   7499     }
   7500 
   7501     for (id = 0; id < _BCM_TH3_NUM_TIME_DOMAIN; id++) {
   7502         BCM_IF_ERROR_RETURN(
   7503             soc_reg32_get(unit, time_domain_reg, REG_PORT_ANY, id, &time_domain_val));
   7504         if (!th3_time_domain_info[unit][id].ref_count) {
   7505             soc_reg_field_set(unit, time_domain_reg, &time_domain_val,
   7506                               TIME_DOMAIN_FIELDf, time_value);
   7507             th3_time_domain_info[unit][id].ref_count++;
   7508             break;
   7509         }
   7510     }
   7511 
   7512     if (id == _BCM_TH3_NUM_TIME_DOMAIN) {/* No field in TIME_DOMAINr is free,return ERR*/
   7513         return BCM_E_RESOURCE;
   7514     }
   7515 
   7516     if (time_id) {
   7517         *time_id = id;
   7518     }
   7519     BCM_IF_ERROR_RETURN(
   7520         soc_reg32_set(unit, time_domain_reg, REG_PORT_ANY, id, time_domain_val));
   7521     return BCM_E_NONE;
   7522 }
   7523 
   7524 STATIC int
   7525 _bcm_th3_cosq_time_domain_get(int unit, int time_id, int *time_value)
   7526 {
   7527     uint32 time_domain_val;
   7528     soc_reg_t time_domain_reg = MMU_WRED_TIME_DOMAINr;
   7529 
   7530     if (time_id < 0 || time_id > _BCM_TH3_NUM_TIME_DOMAIN - 1) {
   7531         return SOC_E_PARAM;
   7532     }
   7533 
   7534     if (time_value == NULL) {
   7535         return SOC_E_PARAM;
   7536     }
   7537 
   7538     BCM_IF_ERROR_RETURN(
   7539         soc_reg32_get(unit, time_domain_reg, REG_PORT_ANY, time_id, &time_domain_val));
   7540     *time_value = soc_reg_field_get(unit, time_domain_reg,
   7541                                    time_domain_val, TIME_DOMAIN_FIELDf);
   7542     return SOC_E_NONE;
   7543 }
   7544 
   7545 
   7546 /*
   7547  * Function:
   7548  *     _bcm_th3_cosq_wred_set
   7549  * Purpose:
   7550  *     Configure unicast queue WRED setting
   7551  * Parameters:
   7552  *     unit                - (IN) unit number
   7553  *     port                - (IN) port number or GPORT identifier
   7554  *     cosq                - (IN) COS queue number
   7555  *     flags               - (IN) BCM_COSQ_DISCARD_XXX
   7556  *     min_thresh          - (IN) Min Threshold
   7557  *     max_thresh          - (IN) Max Threshold
   7558  *     drop_probablity     - (IN) Probabilistic drop rate
   7559  *     gain                - (IN)
   7560  *     ignore_enable_flags - (IN)
   7561  *     lflags              - (IN) Config Flags
   7562  *     refresh_time        - (IN) actual refresh time
   7563  * Returns:
   7564  *     BCM_E_XXX
   7565  * Notes:
   7566  *     If port is any form of local port, cosq is the hardware queue index.
   7567  */
   7568 STATIC int
   7569 _bcm_th3_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   7570                       bcm_cosq_buffer_id_t buffer,
   7571                       uint32 flags, uint32 min_thresh, uint32 max_thresh,
   7572                       int drop_probability, int gain, int ignore_enable_flags,
   7573                       uint32 lflags, int refresh_time, uint32 resolution_id)
   7574 {
   7575     /* Local Variables */
   7576     soc_mem_t wred_config_mem = INVALIDm;
   7577     soc_reg_t wred_config_reg = INVALIDr;
   7578     bcm_port_t local_port = -1;
   7579     bcm_port_t port_num;
   7580     int index, i, start_index, end_index, count = 0;
   7581     int end_offset, need_profile = 0, pipe, itm, itm_map, accessed = 0;
   7582     uint32 profile_index, old_profile_index;
   7583     uint32 wred_flags = 0;
   7584     void *entries[_BCM_TH3_NUM_WRED_PROFILES];
   7585     soc_mem_t mems[_BCM_TH3_NUM_WRED_PROFILES];
   7586     static soc_mem_t wred_mems[_BCM_TH3_NUM_WRED_PROFILES] = {
   7587         MMU_WRED_DROP_CURVE_PROFILE_0_0m, MMU_WRED_DROP_CURVE_PROFILE_1_0m,
   7588         MMU_WRED_DROP_CURVE_PROFILE_2_0m, MMU_WRED_DROP_CURVE_PROFILE_3_0m,
   7589         MMU_WRED_DROP_CURVE_PROFILE_4_0m, MMU_WRED_DROP_CURVE_PROFILE_5_0m,
   7590         MMU_WRED_DROP_CURVE_PROFILE_6_0m, MMU_WRED_DROP_CURVE_PROFILE_7_0m,
   7591         MMU_WRED_DROP_CURVE_PROFILE_8_0m
   7592     };
   7593     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   7594     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   7595     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   7596     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   7597     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   7598     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   7599     mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green;
   7600     mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow;
   7601     mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red;
   7602     /* mmu_wred_config_entry_t entry; */
   7603     uint32 entry = 0;
   7604     int rate = 0;
   7605     int from_pipe, to_pipe;
   7606     int time_id,time,old_time,current_time_sel;
   7607     int rv = SOC_E_NONE, exists = 0;
   7608     int device_setting, portsp_setting, queue_setting;
   7609 
   7610     device_setting = 0;
   7611     portsp_setting = 0;
   7612     queue_setting = 0;
   7613 
   7614     LOG_INFO(BSL_LS_BCM_COSQ,
   7615         (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: port: %d cosq: %d min_thres: %d max_thresh: %d flags: %x\n"),
   7616             port, cosq, min_thresh, max_thresh, flags));
   7617     if ((buffer != BCM_COSQ_BUFFER_ID_INVALID) &&
   7618         ((buffer < 0) || (buffer >= _TH3_ITMS_PER_DEV))) {
   7619         return BCM_E_PARAM;
   7620     }
   7621 
   7622     wred_flags = flags | lflags;
   7623     end_offset = 0;
   7624 
   7625     /* Check Flags for WRED res level - Device-SP/Port-SP/Queues */
   7626     if ((wred_flags & BCM_COSQ_DISCARD_DEVICE) && (port == BCM_GPORT_INVALID)) {
   7627         /* (Port == -1) For all Global SPs */
   7628         wred_config_reg = MMU_WRED_POOL_CONFIGr;
   7629         wred_config_mem = MMU_WRED_QUEUE_CONFIGm;
   7630         index = 0;
   7631         count = _TH3_MMU_NUM_POOL;
   7632         /*For all pipe*/
   7633         from_pipe = 0;
   7634         to_pipe = NUM_PIPE(unit) - 1;
   7635         device_setting = 1;
   7636     } else {
   7637         BCM_IF_ERROR_RETURN
   7638             (_bcm_th3_cosq_localport_resolve(unit, port, &local_port));
   7639         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   7640         from_pipe = to_pipe = pipe;
   7641 
   7642         if (wred_flags & BCM_COSQ_DISCARD_DEVICE) {
   7643             wred_config_reg = MMU_WRED_POOL_CONFIGr;
   7644             device_setting = 1;
   7645             BCM_IF_ERROR_RETURN
   7646                 (_bcm_th3_cosq_index_resolve(unit, port, cosq,
   7647                                             _BCM_TH3_COSQ_INDEX_STYLE_WRED_DEVICE,
   7648                                             NULL, &index, &count));
   7649             /* (cosq == -1) For all Global SPs */
   7650             LOG_INFO(BSL_LS_BCM_COSQ,
   7651                 (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: Device settings port: %d cosq: %d index: %d count: %d\n"),
   7652                     port, cosq, index, count));
   7653         } else if (wred_flags & BCM_COSQ_DISCARD_PORT) {
   7654             /* Port SP - Given or all SPs of the port */
   7655             wred_config_mem = MMU_WRED_PORTSP_CONFIGm;
   7656             portsp_setting = 1;
   7657             BCM_IF_ERROR_RETURN
   7658                 (_bcm_th3_cosq_index_resolve(unit, port, cosq,
   7659                                             _BCM_TH3_COSQ_INDEX_STYLE_WRED_PORT,
   7660                                             NULL, &index, &count));
   7661             /* (cosq == -1) For all SPs of the given port */
   7662             LOG_INFO(BSL_LS_BCM_COSQ,
   7663                 (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: Port settings port: %d cosq: %d index: %d count: %d\n"),
   7664                     port, cosq, index, count));
   7665         } else {
   7666             /* Per Queue WRED settings */
   7667             wred_config_mem = MMU_WRED_QUEUE_CONFIGm;
   7668             queue_setting = 1;
   7669             BCM_IF_ERROR_RETURN
   7670                 (_bcm_th3_cosq_index_resolve(unit, port, cosq,
   7671                                             _BCM_TH3_COSQ_INDEX_STYLE_WRED_QUEUE,
   7672                                             NULL, &index, &count));
   7673             /* (cosq == -1) For all Queues of the given port */
   7674             LOG_INFO(BSL_LS_BCM_COSQ,
   7675                 (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: Queue settings port: %d cosq: %d index: %d count: %d\n"),
   7676                     port, cosq, index, count));
   7677         }
   7678     }
   7679 
   7680 
   7681     end_offset = (count > 0) ? (count - 1) : 0;
   7682 
   7683     if (index < 0) {
   7684         return BCM_E_PARAM;
   7685     }
   7686     if (refresh_time < 1) {
   7687         return BCM_E_PARAM;
   7688     }
   7689     start_index = index;
   7690     end_index = start_index + end_offset;
   7691 
   7692     rate = _bcm_th3_percent_to_drop_prob(drop_probability);
   7693 
   7694     LOG_INFO(BSL_LS_BCM_COSQ,
   7695         (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: Queue settings port: %d cosq: %d rate: %d start_index: %d end_index:%d\n"),
   7696             port, cosq, rate, start_index, end_index));
   7697 
   7698     for (pipe = from_pipe; pipe <= to_pipe; pipe++ ) {
   7699         /* Config MMU_WRED_CONFIGm for the respective resource */
   7700 
   7701         for (i=0; i < _BCM_TH3_NUM_WRED_PROFILES; i++) {
   7702             mems[i] = INVALIDm;
   7703         }
   7704 
   7705         if (wred_flags & (BCM_COSQ_DISCARD_COLOR_ALL |
   7706                           BCM_COSQ_DISCARD_TCP |
   7707                           BCM_COSQ_DISCARD_NONTCP |
   7708                           BCM_COSQ_DISCARD_ECT_MARKED |
   7709                           BCM_COSQ_DISCARD_RESPONSIVE_DROP |
   7710                           BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) {
   7711             need_profile = 1;
   7712             LOG_INFO(BSL_LS_BCM_COSQ,
   7713                 (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: Queue settings port: %d cosq: %d need_profile: %d\n"),
   7714                     port, cosq, need_profile));
   7715 
   7716             if (!(flags & (BCM_COSQ_DISCARD_COLOR_GREEN |
   7717                            BCM_COSQ_DISCARD_COLOR_YELLOW |
   7718                            BCM_COSQ_DISCARD_COLOR_RED))) {
   7719                 flags |= BCM_COSQ_DISCARD_COLOR_ALL;
   7720             }
   7721 
   7722             if (!(wred_flags & (BCM_COSQ_DISCARD_NONTCP |
   7723                                 BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP |
   7724                                 BCM_COSQ_DISCARD_ECT_MARKED)) ||
   7725                  ((wred_flags & BCM_COSQ_DISCARD_TCP) ||
   7726                  (wred_flags & BCM_COSQ_DISCARD_RESPONSIVE_DROP))) {
   7727                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   7728                     mems[0] = wred_mems[0];
   7729                 }
   7730                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   7731                     mems[1] = wred_mems[1];
   7732                 }
   7733                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   7734                     mems[2] = wred_mems[2];
   7735                 }
   7736             }
   7737             if ((wred_flags & BCM_COSQ_DISCARD_NONTCP) ||
   7738                 (wred_flags & BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)){
   7739                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   7740                     mems[3] = wred_mems[3];
   7741                 }
   7742                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   7743                     mems[4] = wred_mems[4];
   7744                 }
   7745                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   7746                     mems[5] = wred_mems[5];
   7747                 }
   7748             }
   7749             if (wred_flags & BCM_COSQ_DISCARD_ECT_MARKED) {
   7750                 if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   7751                     mems[6] = wred_mems[6];
   7752                 }
   7753                 if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   7754                     mems[7] = wred_mems[7];
   7755                 }
   7756                 if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   7757                     mems[8] = wred_mems[8];
   7758                 }
   7759             }
   7760         }
   7761 
   7762         entries[0] = &entry_tcp_green;
   7763         entries[1] = &entry_tcp_yellow;
   7764         entries[2] = &entry_tcp_red;
   7765         entries[3] = &entry_nontcp_green;
   7766         entries[4] = &entry_nontcp_yellow;
   7767         entries[5] = &entry_nontcp_red;
   7768         entries[6] = &entry_ecn_green;
   7769         entries[7] = &entry_ecn_yellow;
   7770         entries[8] = &entry_ecn_red;
   7771 
   7772         if (buffer == BCM_COSQ_BUFFER_ID_INVALID) {
   7773             itm_map = 3;
   7774         } else {
   7775             itm_map = (1 << buffer);
   7776         }
   7777 
   7778         for (itm = 0; itm < NUM_ITM(unit); itm ++) {
   7779             if (!(itm_map & (1 << itm))) {
   7780                 continue;
   7781             }
   7782 
   7783             accessed = 1;
   7784             for (index = start_index; index <= end_index; index++) {
   7785                 old_profile_index = TH3_WRED_PROFILE_INDEX_INVALID;
   7786                 if (portsp_setting || queue_setting) {
   7787                     BCM_IF_ERROR_RETURN
   7788                      (soc_tomahawk3_itm_mem_read(unit, wred_config_mem, itm, pipe,
   7789                                                 MEM_BLOCK_ALL, index, &entry));
   7790                 }  else { /* device_setting */
   7791                     BCM_IF_ERROR_RETURN
   7792                      (soc_tomahawk3_itm_reg32_get(unit, wred_config_reg, -1, -1,
   7793                                                 index, &entry));
   7794                 }
   7795                 if (need_profile) {
   7796                     if (portsp_setting || queue_setting) {
   7797                         old_profile_index = soc_mem_field32_get(unit, wred_config_mem,
   7798                                                             &entry, PROFILE_INDEXf);
   7799                     } else { /* device_setting */
   7800                         old_profile_index = soc_reg_field_get(unit, wred_config_reg,
   7801                                                             entry, PROFILE_INDEXf);
   7802                     }
   7803                     LOG_INFO(BSL_LS_BCM_COSQ,
   7804                         (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: Queue settings port: %d cosq: %d old_profile_index: %d\n"),
   7805                             port, cosq, old_profile_index));
   7806 
   7807                     BCM_IF_ERROR_RETURN
   7808                         (soc_profile_mem_get(unit, _bcm_th3_wred_profile[unit],
   7809                                              old_profile_index, 1, entries));
   7810                     LOG_INFO(BSL_LS_BCM_COSQ,
   7811                         (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: Queue settings port: %d cosq: %d 1\n"),
   7812                             port, cosq));
   7813 
   7814                     for (i = 0; i < _BCM_TH3_NUM_WRED_PROFILES; i++) {
   7815                         if (mems[i] == INVALIDm) {
   7816                             continue;
   7817                         }
   7818                         soc_mem_field32_set(unit, wred_mems[i], entries[i],
   7819                                             MIN_THDf, min_thresh);
   7820                         soc_mem_field32_set(unit, wred_mems[i], entries[i],
   7821                                             MAX_THDf, max_thresh);
   7822                         soc_mem_field32_set(unit, wred_mems[i], entries[i],
   7823                                             MAX_DROP_RATEf, rate);
   7824                     }
   7825                     BCM_IF_ERROR_RETURN
   7826                         (soc_profile_mem_add(unit, _bcm_th3_wred_profile[unit],
   7827                                              entries, 1, &profile_index));
   7828 
   7829                     LOG_INFO(BSL_LS_BCM_COSQ,
   7830                         (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: Queue settings port: %d cosq: %d profile_index: %d\n"),
   7831                             port, cosq, profile_index));
   7832                     if (portsp_setting || queue_setting) {
   7833                         soc_mem_field32_set(unit, wred_config_mem, &entry, PROFILE_INDEXf, profile_index);
   7834                     } else { /* device_setting */
   7835                         soc_reg_field_set(unit, wred_config_reg, &entry, PROFILE_INDEXf, profile_index);
   7836                     }
   7837                 }
   7838 
   7839                 if (queue_setting) {
   7840                     /* Determine SPID */
   7841                     int spid;
   7842                     if (cosq == -1) {
   7843                         BCM_IF_ERROR_RETURN
   7844                             (_bcm_th3_cosq_index_resolve(unit, port, index - start_index,
   7845                                                 _BCM_TH3_COSQ_INDEX_STYLE_EGR_POOL,
   7846                                                 NULL, &spid, &count));
   7847                     } else {
   7848                         BCM_IF_ERROR_RETURN
   7849                             (_bcm_th3_cosq_index_resolve(unit, port, cosq,
   7850                                                 _BCM_TH3_COSQ_INDEX_STYLE_EGR_POOL,
   7851                                                 NULL, &spid, &count));
   7852                     }
   7853                     LOG_INFO(BSL_LS_BCM_COSQ,
   7854                         (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: Queue settings port: %d cosq: %d spid: %d\n"),
   7855                             port, cosq, spid));
   7856                     soc_mem_field32_set(unit, wred_config_mem, &entry, SPIDf, spid);
   7857                 }
   7858 
   7859 
   7860                 if (portsp_setting || queue_setting) {
   7861                     soc_mem_field32_set(unit, wred_config_mem, &entry, WEIGHTf, gain);
   7862                 } else { /* device_setting */
   7863                     soc_reg_field_set(unit, wred_config_reg, &entry, WEIGHTf, gain);
   7864                 }
   7865 
   7866                 /* Some APIs only modify profiles */
   7867                 if (!ignore_enable_flags) {
   7868                     if (portsp_setting || queue_setting) {
   7869                         soc_mem_field32_set(unit, wred_config_mem, &entry, CAP_AVERAGEf,
   7870                                         flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   7871                         soc_mem_field32_set(unit, wred_config_mem, &entry, WRED_ENf,
   7872                                     flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   7873                     } else { /* device_setting */
   7874                         soc_reg_field_set(unit, wred_config_reg, &entry, CAP_AVERAGEf,
   7875                                         flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   7876                         soc_reg_field_set(unit, wred_config_reg, &entry, WRED_ENf,
   7877                                     flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   7878                     }
   7879                     if (queue_setting) {
   7880                         soc_mem_field32_set(unit, wred_config_mem, &entry, ECN_MARKING_ENf,
   7881                                         flags & BCM_COSQ_DISCARD_MARK_CONGESTION ?  1 : 0);
   7882                     }
   7883                 }
   7884 
   7885                 if (portsp_setting || queue_setting) {
   7886                     current_time_sel = soc_mem_field32_get(unit, wred_config_mem,
   7887                                                        &entry, TIME_DOMAIN_SELf);
   7888                 } else { /* device_setting */
   7889                     current_time_sel = soc_reg_field_get(unit, wred_config_reg,
   7890                                                        entry, TIME_DOMAIN_SELf);
   7891                 }
   7892                 time = refresh_time - 1;
   7893                 exists = 0;
   7894                 /* If the time value exist, update reference count only */
   7895                 for (time_id = 0; time_id < _BCM_TH3_NUM_TIME_DOMAIN; time_id++) {
   7896                     BCM_IF_ERROR_RETURN
   7897                         (_bcm_th3_cosq_time_domain_get(unit, time_id, &old_time));
   7898                     if (time == old_time) {
   7899                         /* Only set exist flag if this entry reference count already update,
   7900                                       otherwise update reference count */
   7901                         if(time_id != current_time_sel){
   7902                             if (portsp_setting || queue_setting) {
   7903                                 soc_mem_field32_set(unit, wred_config_mem, &entry,
   7904                                                 TIME_DOMAIN_SELf, time_id);
   7905                             } else { /* device_setting */
   7906                                 soc_reg_field_set(unit, wred_config_reg, &entry,
   7907                                                 TIME_DOMAIN_SELf, time_id);
   7908                             }
   7909                             th3_time_domain_info[unit][time_id].ref_count++;
   7910                             th3_time_domain_info[unit][current_time_sel].ref_count--;
   7911                         }
   7912                         exists = 1;
   7913                         break;
   7914                     }
   7915                 }
   7916 
   7917                 if(!exists){
   7918                     rv = _bcm_th3_cosq_time_domain_set(unit, time, &time_id);
   7919                     if(rv == SOC_E_NONE){
   7920                         if (portsp_setting || queue_setting) {
   7921                             soc_mem_field32_set(unit, wred_config_mem, &entry,
   7922                                             TIME_DOMAIN_SELf, time_id);
   7923                         } else { /* device_setting */
   7924                             soc_reg_field_set(unit, wred_config_reg, &entry,
   7925                                             TIME_DOMAIN_SELf, time_id);
   7926                         }
   7927                         th3_time_domain_info[unit][current_time_sel].ref_count--;
   7928                     } else {
   7929                         return rv;
   7930                     }
   7931                 }
   7932 
   7933                 if (flags & BCM_COSQ_DISCARD_MARK_CONGESTION) {
   7934                     if (queue_setting) {
   7935                         soc_mem_field32_set(unit, wred_config_mem, &entry,
   7936                             WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf,
   7937                             resolution_id);
   7938                     }
   7939                 } else {
   7940                     if (queue_setting) {
   7941                         soc_mem_field32_set(unit, wred_config_mem, &entry,
   7942                             WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf,
   7943                             resolution_id);
   7944                     }
   7945                 }
   7946 
   7947                 if (portsp_setting || queue_setting) {
   7948                     BCM_IF_ERROR_RETURN
   7949                         (soc_tomahawk3_itm_mem_write(unit, wred_config_mem, itm, pipe,
   7950                                                 MEM_BLOCK_ALL, index, &entry));
   7951                 } else { /* device_setting */
   7952                     BCM_IF_ERROR_RETURN
   7953                         (soc_tomahawk3_itm_reg32_set(unit, wred_config_reg, itm, -1,
   7954                                                 index, entry));
   7955                 }
   7956 
   7957                 if (old_profile_index != TH3_WRED_PROFILE_INDEX_INVALID) {
   7958                     SOC_IF_ERROR_RETURN
   7959                         (soc_profile_mem_delete(unit, _bcm_th3_wred_profile[unit],
   7960                                                 old_profile_index));
   7961                 }
   7962 
   7963             }
   7964         }
   7965     }
   7966 
   7967     /* pipe (port) and itm (buffer) are not related */
   7968     if (!accessed) {
   7969         return BCM_E_PARAM;
   7970     }
   7971 
   7972     if (device_setting) {
   7973         flags &= ~(BCM_COSQ_DISCARD_DEVICE);
   7974         PBMP_PORT_ITER(unit, port_num) {
   7975             LOG_INFO(BSL_LS_BCM_COSQ,
   7976                 (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: device_setting calling wred_queue with port: %d cosq: -1\n"),
   7977                             port_num));
   7978             BCM_IF_ERROR_RETURN
   7979                 (_bcm_th3_cosq_wred_set(unit, port_num, -1, buffer,
   7980                                    flags, min_thresh, max_thresh,
   7981                                    drop_probability, gain,
   7982                                    FALSE, flags, refresh_time,
   7983                                    resolution_id));
   7984         }
   7985     }
   7986     if (portsp_setting) {
   7987         LOG_INFO(BSL_LS_BCM_COSQ,
   7988             (BSL_META_U(unit, "_bcm_th3_cosq_wred_set: portsp_setting calling wred_queue with port: %d cosq: -1\n"),
   7989                         port));
   7990         flags &= ~(BCM_COSQ_DISCARD_PORT);
   7991         BCM_IF_ERROR_RETURN
   7992             (_bcm_th3_cosq_wred_set(unit, port, -1, buffer,
   7993                                flags, min_thresh, max_thresh,
   7994                                drop_probability, gain,
   7995                                FALSE, flags, refresh_time,
   7996                                resolution_id));
   7997     }
   7998 
   7999     return rv;
   8000 }
   8001 
   8002 /*
   8003  * Function:
   8004  *     _bcm_th3_cosq_wred_get
   8005  * Purpose:
   8006  *     Configure unicast queue WRED setting
   8007  * Parameters:
   8008  *     unit                - (IN) unit number
   8009  *     port                - (IN) port number or GPORT identifier
   8010  *     cosq                - (IN) COS queue number
   8011  *     flags               - (IN/OUT) BCM_COSQ_DISCARD_XXX
   8012  *     min_thresh          - (OUT) Min Threshold
   8013  *     max_thresh          - (OUT) Max Threshold
   8014  *     drop_probablity     - (OUT) Probabilistic drop rate
   8015  *     gain                - (OUT)
   8016  *     lflags              - (IN) Config flags
   8017  *     refresh_time        - (OUT) Time Domain
   8018  * Returns:
   8019  *     BCM_E_XXX
   8020  * Notes:
   8021  *     If port is any form of local port, cosq is the hardware queue index.
   8022  */
   8023 STATIC int
   8024 _bcm_th3_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8025                       bcm_cosq_buffer_id_t buffer,
   8026                       uint32 *flags, uint32 *min_thresh, uint32 *max_thresh,
   8027                       int *drop_probability, int *gain, uint32 lflags,
   8028                       int *refresh_time, uint32 *resolution_id)
   8029 {
   8030     soc_mem_t wred_config_mem = INVALIDm, mem = INVALIDm;
   8031     soc_reg_t wred_config_reg = INVALIDr;
   8032     bcm_port_t local_port = -1;
   8033     mmu_wred_drop_curve_profile_0_entry_t entry_tcp_green;
   8034     mmu_wred_drop_curve_profile_1_entry_t entry_tcp_yellow;
   8035     mmu_wred_drop_curve_profile_2_entry_t entry_tcp_red;
   8036     mmu_wred_drop_curve_profile_3_entry_t entry_nontcp_green;
   8037     mmu_wred_drop_curve_profile_4_entry_t entry_nontcp_yellow;
   8038     mmu_wred_drop_curve_profile_5_entry_t entry_nontcp_red;
   8039     mmu_wred_drop_curve_profile_6_entry_t entry_ecn_green;
   8040     mmu_wred_drop_curve_profile_7_entry_t entry_ecn_yellow;
   8041     mmu_wred_drop_curve_profile_8_entry_t entry_ecn_red;
   8042     void *entries[_BCM_TH3_NUM_WRED_PROFILES];
   8043     void *entry_p;
   8044     int index, profile_index;
   8045     uint32 entry = 0;
   8046     uint32 wred_flags = 0;
   8047     int rate = 0, pipe = -1, itm;
   8048     int time_id, time;
   8049     int portsp_setting = 0;
   8050     int queue_setting = 0;
   8051 
   8052     if ((buffer != BCM_COSQ_BUFFER_ID_INVALID) &&
   8053         ((buffer < 0) || (buffer >= NUM_ITM(unit)))) {
   8054         return BCM_E_PARAM;
   8055     }
   8056 
   8057     if (flags) {
   8058         wred_flags = *flags | lflags;
   8059     } else {
   8060         wred_flags = lflags;
   8061     }
   8062 
   8063     if ((wred_flags & BCM_COSQ_DISCARD_DEVICE) && (port == BCM_GPORT_INVALID)) {
   8064         /* (Port == -1) For all Global SPs */
   8065         index = 0;
   8066         pipe = 0;
   8067         wred_config_reg = MMU_WRED_POOL_CONFIGr;
   8068     } else {
   8069         BCM_IF_ERROR_RETURN
   8070             (_bcm_th3_cosq_localport_resolve(unit, port, &local_port));
   8071         SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
   8072 
   8073         /* Check Flags for WRED res level - Device-SP/Port-SP/Queues */
   8074         if(wred_flags & BCM_COSQ_DISCARD_DEVICE) {
   8075             wred_config_reg = MMU_WRED_POOL_CONFIGr;
   8076             BCM_IF_ERROR_RETURN
   8077                 (_bcm_th3_cosq_index_resolve(unit, port, cosq,
   8078                                             _BCM_TH3_COSQ_INDEX_STYLE_WRED_DEVICE,
   8079                                             NULL, &index, NULL));
   8080         } else if (wred_flags & BCM_COSQ_DISCARD_PORT) {
   8081             /* Port SP - Given or all SPs of the port */
   8082             wred_config_mem = MMU_WRED_PORTSP_CONFIGm;
   8083             portsp_setting = 1;
   8084             BCM_IF_ERROR_RETURN
   8085                 (_bcm_th3_cosq_index_resolve(unit, port, cosq,
   8086                                             _BCM_TH3_COSQ_INDEX_STYLE_WRED_PORT,
   8087                                             NULL, &index, NULL));
   8088         } else {
   8089             /* Per Queue WRED settings */
   8090             wred_config_mem = MMU_WRED_QUEUE_CONFIGm;
   8091             queue_setting = 1;
   8092             BCM_IF_ERROR_RETURN
   8093                 (_bcm_th3_cosq_index_resolve(unit, port, cosq,
   8094                                             _BCM_TH3_COSQ_INDEX_STYLE_WRED_QUEUE,
   8095                                             NULL, &index, NULL));
   8096         }
   8097     }
   8098 
   8099     if ((index < 0) || (pipe == -1)) {
   8100         return BCM_E_PARAM;
   8101     }
   8102 
   8103     if (buffer == BCM_COSQ_BUFFER_ID_INVALID) {
   8104         itm = -1;
   8105     } else if (port == BCM_GPORT_INVALID) {
   8106         itm = buffer;
   8107         pipe = -1;
   8108     } else {
   8109         itm = buffer;
   8110     }
   8111 
   8112     if (portsp_setting || queue_setting) {
   8113         BCM_IF_ERROR_RETURN
   8114             (soc_tomahawk3_itm_mem_read(unit, wred_config_mem, itm, pipe,
   8115                                    MEM_BLOCK_ALL, index, &entry));
   8116         profile_index = soc_mem_field32_get(unit, wred_config_mem,
   8117                                         &entry, PROFILE_INDEXf);
   8118     } else { /* device_setting */
   8119         BCM_IF_ERROR_RETURN
   8120             (soc_tomahawk3_itm_reg32_get(unit, wred_config_reg, itm, -1,
   8121                                                 index, &entry));
   8122         profile_index = soc_reg_field_get(unit, wred_config_reg,
   8123                                         entry, PROFILE_INDEXf);
   8124     }
   8125 
   8126 
   8127     if (!(wred_flags & (BCM_COSQ_DISCARD_NONTCP |
   8128                         BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP |
   8129                         BCM_COSQ_DISCARD_ECT_MARKED))) {
   8130         /* By default we will assume
   8131            BCM_COSQ_DISCARD_TCP */
   8132         if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   8133             mem = MMU_WRED_DROP_CURVE_PROFILE_1_0m;
   8134             entry_p = &entry_tcp_yellow;
   8135         } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) {
   8136             mem = MMU_WRED_DROP_CURVE_PROFILE_2_0m;
   8137             entry_p = &entry_tcp_red;
   8138         } else {
   8139             /* By default we will assume
   8140                BCM_COSQ_DISCARD_COLOR_GREEN */
   8141             mem = MMU_WRED_DROP_CURVE_PROFILE_0_0m;
   8142             entry_p = &entry_tcp_green;
   8143         }
   8144     } else if ((wred_flags & BCM_COSQ_DISCARD_NONTCP) ||
   8145                (wred_flags & BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) {
   8146         if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   8147             mem = MMU_WRED_DROP_CURVE_PROFILE_4_0m;
   8148             entry_p = &entry_nontcp_yellow;
   8149         } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) {
   8150             mem = MMU_WRED_DROP_CURVE_PROFILE_5_0m;
   8151             entry_p = &entry_nontcp_red;
   8152         } else {
   8153             /* By default we will assume
   8154                BCM_COSQ_DISCARD_COLOR_GREEN */
   8155             mem = MMU_WRED_DROP_CURVE_PROFILE_3_0m;
   8156             entry_p = &entry_nontcp_green;
   8157         }
   8158     } else {
   8159         if (wred_flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   8160             mem = MMU_WRED_DROP_CURVE_PROFILE_7_0m;
   8161             entry_p = &entry_ecn_yellow;
   8162         } else if (wred_flags & BCM_COSQ_DISCARD_COLOR_RED) {
   8163             mem = MMU_WRED_DROP_CURVE_PROFILE_8_0m;
   8164             entry_p = &entry_ecn_red;
   8165         } else {
   8166             /* By default we will assume
   8167                BCM_COSQ_DISCARD_COLOR_GREEN */
   8168             mem = MMU_WRED_DROP_CURVE_PROFILE_6_0m;
   8169             entry_p = &entry_ecn_green;
   8170         }
   8171     }
   8172 
   8173     entries[0] = &entry_tcp_green;
   8174     entries[1] = &entry_tcp_yellow;
   8175     entries[2] = &entry_tcp_red;
   8176     entries[3] = &entry_nontcp_green;
   8177     entries[4] = &entry_nontcp_yellow;
   8178     entries[5] = &entry_nontcp_red;
   8179     entries[6] = &entry_ecn_green;
   8180     entries[7] = &entry_ecn_yellow;
   8181     entries[8] = &entry_ecn_red;
   8182 
   8183     BCM_IF_ERROR_RETURN
   8184         (soc_profile_mem_get(unit, _bcm_th3_wred_profile[unit],
   8185                              profile_index, 1, entries));
   8186     if (min_thresh != NULL) {
   8187         *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf);
   8188     }
   8189     if (max_thresh != NULL) {
   8190         *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf);
   8191     }
   8192     if (drop_probability != NULL) {
   8193         rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf);
   8194         *drop_probability = _bcm_th3_drop_prob_to_percent(rate);
   8195     }
   8196     if (gain) {
   8197         if (portsp_setting || queue_setting) {
   8198             *gain = soc_mem_field32_get(unit, wred_config_mem, &entry, WEIGHTf);
   8199         } else { /* device_setting */
   8200             *gain = soc_reg_field_get(unit, wred_config_reg, entry, WEIGHTf);
   8201         }
   8202     }
   8203 
   8204     /* Get the Time Domain value */
   8205     if (refresh_time) {
   8206         if (portsp_setting || queue_setting) {
   8207             time_id = soc_mem_field32_get(unit, wred_config_mem, &entry,
   8208                                           TIME_DOMAIN_SELf);
   8209         } else { /* device_setting */
   8210             time_id = soc_reg_field_get(unit, wred_config_reg, entry,
   8211                                           TIME_DOMAIN_SELf);
   8212         }
   8213         BCM_IF_ERROR_RETURN
   8214             (_bcm_th3_cosq_time_domain_get(unit,time_id,&time));
   8215         *refresh_time = time + 1;
   8216     }
   8217 
   8218     /* Get flags */
   8219     if (flags) {
   8220         *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE |
   8221                     BCM_COSQ_DISCARD_MARK_CONGESTION);
   8222         if (portsp_setting || queue_setting) {
   8223             if (soc_mem_field32_get(unit, wred_config_mem, &entry, CAP_AVERAGEf)) {
   8224                 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   8225             }
   8226             if (soc_mem_field32_get(unit, wred_config_mem, &entry, WRED_ENf)) {
   8227                 *flags |= BCM_COSQ_DISCARD_ENABLE;
   8228             }
   8229         } else { /* device_setting */
   8230             if (soc_reg_field_get(unit, wred_config_reg, entry, CAP_AVERAGEf)) {
   8231                 *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   8232             }
   8233             if (soc_reg_field_get(unit, wred_config_reg, entry, WRED_ENf)) {
   8234                 *flags |= BCM_COSQ_DISCARD_ENABLE;
   8235             }
   8236         }
   8237         if (queue_setting) {
   8238             if (soc_mem_field32_get(unit, wred_config_mem, &entry, ECN_MARKING_ENf)) {
   8239                 *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION;
   8240             }
   8241         }
   8242     }
   8243 
   8244     /* Get resolution table index */
   8245     if (resolution_id) {
   8246         if (queue_setting) {
   8247             if (soc_mem_field32_get(unit, wred_config_mem, &entry, ECN_MARKING_ENf)) {
   8248                 *resolution_id = soc_mem_field32_get(unit, wred_config_mem, &entry,
   8249                     WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf);
   8250             } else {
   8251                 *resolution_id = soc_mem_field32_get(unit, wred_config_mem, &entry,
   8252                     WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf);
   8253             }
   8254         }
   8255     }
   8256 
   8257     return BCM_E_NONE;
   8258 }
   8259 
   8260 
   8261 
   8262 /*
   8263  * Function:
   8264  *     bcm_th3_cosq_discard_set
   8265  * Purpose:
   8266  *     Get COS queue bandwidth control configuration
   8267  * Parameters:
   8268  *     unit          - (IN) unit number
   8269  *     flags         - (IN) DISCARD flags
   8270  * Returns:
   8271  *     BCM_E_XXX
   8272  * Notes:
   8273  *     Set the WRED discard flags
   8274  */
   8275 
   8276 int
   8277 bcm_th3_cosq_discard_set(int unit, uint32 flags)
   8278 {
   8279     bcm_port_t port;
   8280 
   8281     if (_bcm_th3_cosq_port_info[unit] == NULL) {
   8282         return BCM_E_INIT;
   8283     }
   8284 
   8285     if (flags & ~(BCM_COSQ_DISCARD_DEVICE |
   8286                   BCM_COSQ_DISCARD_NONTCP |
   8287                   BCM_COSQ_DISCARD_COLOR_ALL |
   8288                   BCM_COSQ_DISCARD_PORT |
   8289                   BCM_COSQ_DISCARD_TCP |
   8290                   BCM_COSQ_DISCARD_COLOR_GREEN |
   8291                   BCM_COSQ_DISCARD_COLOR_YELLOW |
   8292                   BCM_COSQ_DISCARD_COLOR_RED |
   8293                   BCM_COSQ_DISCARD_CAP_AVERAGE |
   8294                   BCM_COSQ_DISCARD_ENABLE |
   8295                   BCM_COSQ_DISCARD_MARK_CONGESTION)) {
   8296         return BCM_E_PARAM;
   8297     }
   8298 
   8299     flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL);
   8300 
   8301     PBMP_PORT_ITER(unit, port) {
   8302         /* cosq(0), buffer(INVALID), flags, min_thresh(0)
   8303            max_thresh(0), drop_prob(0), gain(0), ignore_enable_flags(0),
   8304            lflags(BCM_COSQ_DISCARD_PORT), refresh_time(1), resolution_id(0) */
   8305         BCM_IF_ERROR_RETURN
   8306             (_bcm_th3_cosq_wred_set(unit, port, 0, BCM_COSQ_BUFFER_ID_INVALID,
   8307                                    flags, 0, 0, 0, 0,
   8308                                    FALSE, BCM_COSQ_DISCARD_PORT, 1, 0));
   8309     }
   8310 
   8311     return BCM_E_NONE;
   8312 }
   8313 
   8314 /*
   8315  * Function:
   8316  *     bcm_th3_cosq_discard_get
   8317  * Purpose:
   8318  *     Get COS queue bandwidth control configuration
   8319  * Parameters:
   8320  *     unit          - (IN) unit number
   8321  *     flags         - (OUT) DISCARD flags
   8322  * Returns:
   8323  *     BCM_E_XXX
   8324  * Notes:
   8325  *     Get the WRED discard flags
   8326  */
   8327 
   8328 int
   8329 bcm_th3_cosq_discard_get(int unit, uint32 *flags)
   8330 {
   8331     bcm_port_t port;
   8332 
   8333     PBMP_PORT_ITER(unit, port) {
   8334         *flags = 0;
   8335         /* use setting from hardware cosq index 0 of the first port */
   8336         return _bcm_th3_cosq_wred_get(unit, port, 0, BCM_COSQ_BUFFER_ID_INVALID,
   8337                                      flags, NULL, NULL, NULL,
   8338                                      NULL, BCM_COSQ_DISCARD_PORT, NULL, NULL);
   8339     }
   8340 
   8341     return BCM_E_NOT_FOUND;
   8342 }
   8343 
   8344 /*
   8345  * Function:
   8346  *     bcm_th3_cosq_discard_port_set
   8347  * Purpose:
   8348  *     Configure port WRED setting
   8349  * Parameters:
   8350  *     unit          - (IN) unit number
   8351  *     port          - (IN) port number or GPORT identifier
   8352  *     cosq          - (IN) COS queue number
   8353  *     color         - (IN)
   8354  *     drop_start    - (IN)
   8355  *     drop_slot     - (IN)
   8356  *     average_time  - (IN)
   8357  * Returns:
   8358  *     BCM_E_XXX
   8359  * Notes:
   8360  *     If port is any form of local port, cosq is the hardware queue index.
   8361  *     Same as TD2 except for Reg changes.
   8362  */
   8363 int
   8364 bcm_th3_cosq_discard_port_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8365                              uint32 color, int drop_start, int drop_slope,
   8366                              int average_time)
   8367 {
   8368     bcm_port_t local_port;
   8369     bcm_pbmp_t pbmp;
   8370     int gain;
   8371     uint32 min_thresh, max_thresh, shared_limit, itm_map;
   8372     uint32 bits, flags = 0;
   8373 
   8374     if (drop_start < 0 || drop_start > 100 ||
   8375         drop_slope < 0 || drop_slope > 90) {
   8376         return BCM_E_PARAM;
   8377     }
   8378 
   8379     /*
   8380      * average queue size is reculated every 1us, the formula is
   8381      * avg_qsize(t + 1) =
   8382      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   8383      * gain = log2(average_time)
   8384      */
   8385     bits = average_time & 0xffff;
   8386     if (bits != 0) {
   8387         bits |= bits >> 1;
   8388         bits |= bits >> 2;
   8389         bits |= bits >> 4;
   8390         bits |= bits >> 8;
   8391         gain = _shr_popcount(bits) - 1;
   8392     } else {
   8393         gain = 0;
   8394     }
   8395 
   8396     /*
   8397      * per-port cell limit may be disabled.
   8398      * per-port per-cos cell limit may be set to use dynamic method.
   8399      * therefore drop_start percentage is based on per-device total shared
   8400      * cells.
   8401      */
   8402     itm_map = SOC_INFO(unit).itm_map;
   8403     _TH3_ARRAY_MIN(_BCM_TH3_MMU_INFO(unit)->shared_limit, NUM_ITM(unit),
   8404                   itm_map, shared_limit);
   8405     min_thresh = ((drop_start * shared_limit) + (100 - 1)) / 100;
   8406 
   8407     /* Calculate the max threshold. For a given slope (angle in
   8408      * degrees), determine how many packets are in the range from
   8409      * 0% drop probability to 100% drop probability. Add that
   8410      * number to the min_treshold to the the max_threshold.
   8411      */
   8412     max_thresh = min_thresh + _bcm_th3_angle_to_cells(drop_slope);
   8413     if (max_thresh > TH3_WRED_CELL_FIELD_MAX) {
   8414         max_thresh = TH3_WRED_CELL_FIELD_MAX;
   8415     }
   8416 
   8417     if (BCM_GPORT_IS_SET(port)) {
   8418         BCM_IF_ERROR_RETURN
   8419             (_bcm_th3_cosq_wred_set(unit, port, cosq,
   8420                                    BCM_COSQ_BUFFER_ID_INVALID, color,
   8421                                    min_thresh, max_thresh, 100, gain,
   8422                                    TRUE, flags, 1, 0));
   8423     } else {
   8424         if (port == -1) {
   8425             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   8426         } else if (!SOC_PORT_VALID(unit, port)) {
   8427             return BCM_E_PORT;
   8428         } else {
   8429             BCM_PBMP_PORT_SET(pbmp, port);
   8430         }
   8431 
   8432         BCM_PBMP_ITER(pbmp, local_port) {
   8433             BCM_IF_ERROR_RETURN
   8434                 (_bcm_th3_cosq_wred_set(unit, local_port, cosq,
   8435                                        BCM_COSQ_BUFFER_ID_INVALID, color,
   8436                                        min_thresh, max_thresh, 100, gain,
   8437                                        TRUE, 0, 1, 0));
   8438         }
   8439     }
   8440 
   8441     return BCM_E_NONE;
   8442 }
   8443 
   8444 /*
   8445  * Function:
   8446  *     bcm_th3_cosq_discard_port_get
   8447  * Purpose:
   8448  *     Get port WRED setting
   8449  * Parameters:
   8450  *     unit          - (IN) unit number
   8451  *     port          - (IN) port number or GPORT identifier
   8452  *     cosq          - (IN) COS queue number
   8453  *     color         - (OUT)
   8454  *     drop_start    - (OUT)
   8455  *     drop_slot     - (OUT)
   8456  *     average_time  - (OUT)
   8457  * Returns:
   8458  *     BCM_E_XXX
   8459  * Notes:
   8460  *     If port is any form of local port, cosq is the hardware queue index.
   8461  *     Same as TD2 except for Reg changes.
   8462  */
   8463 int
   8464 bcm_th3_cosq_discard_port_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   8465                              uint32 color, int *drop_start, int *drop_slope,
   8466                              int *average_time)
   8467 {
   8468     bcm_port_t local_port;
   8469     bcm_pbmp_t pbmp;
   8470     int gain, drop_prob;
   8471     uint32 min_thresh, max_thresh, shared_limit, itm_map;
   8472     int refresh_time = 0;
   8473 
   8474     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   8475         return BCM_E_PARAM;
   8476     }
   8477 
   8478     if (BCM_GPORT_IS_SET(port)) {
   8479         local_port = port;
   8480     } else {
   8481         if (port == -1) {
   8482             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   8483         } else if (!SOC_PORT_VALID(unit, port)) {
   8484             return BCM_E_PORT;
   8485         } else {
   8486             BCM_PBMP_PORT_SET(pbmp, port);
   8487         }
   8488         BCM_PBMP_ITER(pbmp, local_port) {
   8489             break;
   8490         }
   8491     }
   8492 
   8493     BCM_IF_ERROR_RETURN
   8494         (_bcm_th3_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq,
   8495                                BCM_COSQ_BUFFER_ID_INVALID,
   8496                                &color, &min_thresh, &max_thresh, &drop_prob,
   8497                                &gain, 0, &refresh_time, NULL));
   8498 
   8499     /*
   8500      * average queue size is reculated every 8us, the formula is
   8501      * avg_qsize(t + 1) =
   8502      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   8503      */
   8504     *average_time = (1 << gain);
   8505 
   8506     itm_map = SOC_INFO(unit).itm_map;
   8507     _TH3_ARRAY_MIN(_BCM_TH3_MMU_INFO(unit)->shared_limit, NUM_ITM(unit),
   8508                   itm_map, shared_limit);
   8509 
   8510     if (min_thresh > shared_limit) {
   8511         min_thresh = shared_limit;
   8512     }
   8513 
   8514     if (max_thresh > shared_limit) {
   8515         max_thresh = shared_limit;
   8516     }
   8517 
   8518     *drop_start = min_thresh * 100 / shared_limit;
   8519 
   8520     /* Calculate the slope using the min and max threshold.
   8521      * The angle is calculated knowing drop probability at min
   8522      * threshold is 0% and drop probability at max threshold is 100%.
   8523      */
   8524     *drop_slope = _bcm_th3_cells_to_angle(max_thresh - min_thresh);
   8525 
   8526     return BCM_E_NONE;
   8527 }
   8528 
   8529 /*
   8530  * Function:
   8531  *     bcm_th3_cosq_gport_discard_set
   8532  * Purpose:
   8533  *     Configure port WRED setting
   8534  * Parameters:
   8535  *     unit    - (IN) unit number
   8536  *     port    - (IN) GPORT identifier
   8537  *     cosq    - (IN) COS queue to configure, -1 for all COS queues
   8538  *     buffer  - (IN) ITM ID
   8539  *     discard - (IN) discard settings
   8540  * Returns:
   8541  *     BCM_E_XXX
   8542  */
   8543 int
   8544 bcm_th3_cosq_gport_discard_set(int unit, bcm_gport_t gport,
   8545                               bcm_cos_queue_t cosq,
   8546                               bcm_cosq_buffer_id_t buffer,
   8547                               bcm_cosq_gport_discard_t *discard)
   8548 {
   8549     uint32 min_thresh, max_thresh, flags = 0;
   8550     int cell_size, cell_field_max;
   8551     bcm_port_t local_port = -1;
   8552 
   8553     LOG_INFO(BSL_LS_BCM_COSQ,
   8554         (BSL_META_U(unit, "bcm_th3_cosq_gport_discard_set: gport: %d cosq: %d buffer: %d \n"),
   8555             gport, cosq, buffer));
   8556     /* Time Domain */
   8557     /* the reasonable range of refresh_time  is from 1 to 64 */
   8558     if (discard == NULL ||
   8559         discard->gain < 0 || discard->gain > 15 ||
   8560         discard->drop_probability < 0 || discard->drop_probability > 100 ||
   8561         discard->profile_id > 3 ||
   8562         discard->refresh_time <= 0 || discard->refresh_time > 64) {
   8563         LOG_INFO(BSL_LS_BCM_COSQ,
   8564             (BSL_META_U(unit, "bcm_th3_cosq_gport_discard_set: Incorrect Parameter 1 gport: %d cosq: %d\n"),
   8565                 gport, cosq));
   8566         return BCM_E_PARAM;
   8567     }
   8568 
   8569     if (discard == NULL ||
   8570         discard->gain < 0 || discard->gain > 15 ||
   8571         discard->drop_probability < 0 || discard->drop_probability > 100 ||
   8572         (discard->min_thresh > discard->max_thresh) ||
   8573         (discard->min_thresh < 0)) {
   8574         LOG_INFO(BSL_LS_BCM_COSQ,
   8575             (BSL_META_U(unit, "bcm_th3_cosq_gport_discard_set: Incorrect Parameter 2 gport: %d cosq: %d\n"),
   8576                 gport, cosq));
   8577         return BCM_E_PARAM;
   8578     }
   8579 
   8580     cell_size = _TH3_MMU_BYTES_PER_CELL;
   8581     cell_field_max = 0x7ffff;
   8582 
   8583     min_thresh = discard->min_thresh;
   8584     max_thresh = discard->max_thresh;
   8585     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   8586         /* Convert bytes to cells */
   8587         min_thresh += (cell_size - 1);
   8588         min_thresh /= cell_size;
   8589 
   8590         max_thresh += (cell_size - 1);
   8591         max_thresh /= cell_size;
   8592         LOG_INFO(BSL_LS_BCM_COSQ,
   8593             (BSL_META_U(unit, "bcm_th3_cosq_gport_discard_set: gport: %d cosq: %d min_thres: %d max_thresh: %d\n"),
   8594                 gport, cosq, min_thresh, max_thresh));
   8595 
   8596         if ((min_thresh > cell_field_max) ||
   8597             (max_thresh > cell_field_max)) {
   8598             LOG_INFO(BSL_LS_BCM_COSQ,
   8599                 (BSL_META_U(unit, "bcm_th3_cosq_gport_discard_set: Incorrect Parameter 3 gport: %d cosq: %d\n"),
   8600                 gport, cosq));
   8601             return BCM_E_PARAM;
   8602         }
   8603     } else if (discard->flags & BCM_COSQ_DISCARD_PACKETS) {
   8604         /* Packet mode not supported */
   8605         LOG_INFO(BSL_LS_BCM_COSQ,
   8606             (BSL_META_U(unit, "bcm_th3_cosq_gport_discard_set: Incorrect Parameter 4 gport: %d cosq: %d\n"),
   8607             gport, cosq));
   8608         return BCM_E_PARAM;
   8609     } else {
   8610         /* Lower layer function will update thresh when these flags are
   8611          * configured, this interface only allow such opration when
   8612          * BCM_COSQ_DISCARD_BYTES is also configured.
   8613          */
   8614         if (discard->flags & (BCM_COSQ_DISCARD_COLOR_ALL |
   8615             BCM_COSQ_DISCARD_TCP |
   8616             BCM_COSQ_DISCARD_NONTCP |
   8617             BCM_COSQ_DISCARD_ECT_MARKED |
   8618             BCM_COSQ_DISCARD_RESPONSIVE_DROP |
   8619             BCM_COSQ_DISCARD_NON_RESPONSIVE_DROP)) {
   8620         LOG_INFO(BSL_LS_BCM_COSQ,
   8621             (BSL_META_U(unit, "bcm_th3_cosq_gport_discard_set: Incorrect Parameter 5 gport: %d cosq: %d\n"),
   8622             gport, cosq));
   8623             return BCM_E_PARAM;
   8624         }
   8625     }
   8626 
   8627     if (gport != BCM_GPORT_INVALID) {
   8628         BCM_IF_ERROR_RETURN
   8629             (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   8630         if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) {
   8631         LOG_INFO(BSL_LS_BCM_COSQ,
   8632             (BSL_META_U(unit, "bcm_th3_cosq_gport_discard_set: Incorrect Parameter 6 gport: %d cosq: %d\n"),
   8633             gport, cosq));
   8634             return BCM_E_PORT;
   8635         }
   8636         if ((cosq < -1) || (cosq >= _bcm_th3_get_num_ucq(unit))) {
   8637         LOG_INFO(BSL_LS_BCM_COSQ,
   8638             (BSL_META_U(unit, "bcm_th3_cosq_gport_discard_set: Incorrect Parameter 7 gport: %d cosq: %d\n"),
   8639             gport, cosq));
   8640             return BCM_E_PARAM;
   8641         }
   8642     }
   8643 
   8644     BCM_IF_ERROR_RETURN
   8645         (_bcm_th3_cosq_wred_set(unit, gport, cosq, buffer,
   8646                                discard->flags, min_thresh, max_thresh,
   8647                                discard->drop_probability, discard->gain,
   8648                                FALSE, flags, discard->refresh_time,
   8649                                discard->profile_id));
   8650 
   8651     return BCM_E_NONE;
   8652 }
   8653 
   8654 /*
   8655  * Function:
   8656  *     bcm_th3_cosq_gport_discard_get
   8657  * Purpose:
   8658  *     Get port WRED setting
   8659  * Parameters:
   8660  *     unit    - (IN) unit number
   8661  *     port    - (IN) GPORT identifier
   8662  *     cosq    - (IN) COS queue to get, -1 for any queue
   8663  *     buffer  - (IN) ITM ID
   8664  *     discard - (OUT) discard settings
   8665  * Returns:
   8666  *     BCM_E_XXX
   8667  */
   8668 int
   8669 bcm_th3_cosq_gport_discard_get(int unit, bcm_gport_t gport,
   8670                               bcm_cos_queue_t cosq,
   8671                               bcm_cosq_buffer_id_t buffer,
   8672                               bcm_cosq_gport_discard_t *discard)
   8673 {
   8674     uint32 min_thresh, max_thresh;
   8675     bcm_port_t local_port = -1;
   8676 
   8677     if (discard == NULL) {
   8678         return BCM_E_PARAM;
   8679     }
   8680 
   8681     if (discard->flags & BCM_COSQ_DISCARD_PACKETS) {
   8682         /* Packet mode not supported */
   8683         return BCM_E_PARAM;
   8684     }
   8685 
   8686     if (gport != BCM_GPORT_INVALID) {
   8687         BCM_IF_ERROR_RETURN
   8688             (_bcm_th3_cosq_localport_resolve(unit, gport, &local_port));
   8689         if (IS_CPU_PORT(unit,local_port) || IS_LB_PORT(unit,local_port)) {
   8690             return BCM_E_PORT;
   8691         }
   8692         if ((cosq < -1) || (cosq >= _BCM_TH3_COS_MAX)) {
   8693             return BCM_E_PARAM;
   8694         }
   8695     }
   8696 
   8697     BCM_IF_ERROR_RETURN
   8698         (_bcm_th3_cosq_wred_get(unit, gport, cosq == -1 ? 0 : cosq, buffer,
   8699                                &discard->flags, &min_thresh, &max_thresh,
   8700                                &discard->drop_probability, &discard->gain,
   8701                                0, &discard->refresh_time,
   8702                                &discard->profile_id));
   8703 
   8704     /* Convert number of cells to number of bytes */
   8705     discard->min_thresh = min_thresh * _TH3_MMU_BYTES_PER_CELL;
   8706     discard->max_thresh = max_thresh * _TH3_MMU_BYTES_PER_CELL;
   8707 
   8708     return BCM_E_NONE;
   8709 }
   8710 
   8711 /*
   8712  * Function:
   8713  *     bcm_th3_cosq_wred_resolution_id_create
   8714  * Purpose:
   8715  *     Assign a unused entry. Default drop rules are WRED drop.
   8716  * Parameters:
   8717  *     unit                - (IN) unit number
   8718  *     index               - (OUT) entry index
   8719  * Returns:
   8720  *     BCM_E_XXX
   8721  */
   8722 int
   8723 bcm_th3_cosq_wred_resolution_entry_create(int unit, int *index)
   8724 {
   8725     uint32 i, rval = 0;
   8726     soc_reg_t reg = MMU_WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   8727 
   8728     for (i = 0; i < _BCM_TH3_NUM_WRED_RESOLUTION_TABLE; i++) {
   8729         if (_bcm_th3_wred_resolution_tbl[i] == 0) {
   8730             /* hw reset value */
   8731             soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, 0xAAA);
   8732             BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, i, rval));
   8733             _bcm_th3_wred_resolution_tbl[i] ++;
   8734             *index = i;
   8735             return SOC_E_NONE;
   8736         }
   8737     }
   8738 
   8739     return SOC_E_RESOURCE;
   8740 }
   8741 
   8742 /*
   8743  * Function:
   8744  *     bcm_th3_cosq_wred_resolution_id_destroy
   8745  * Purpose:
   8746  *     Callback an entry and set its drop rules to WRED drop.
   8747  * Parameters:
   8748  *     unit                - (IN) unit number
   8749  *     index               - (IN) entry index
   8750  * Returns:
   8751  *     BCM_E_XXX
   8752  */
   8753 int
   8754 bcm_th3_cosq_wred_resolution_entry_destroy(int unit, int index)
   8755 {
   8756     uint32 rval = 0;
   8757     soc_reg_t reg = MMU_WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   8758 
   8759     if ((index < 0) || (index >= _BCM_TH3_NUM_WRED_RESOLUTION_TABLE)) {
   8760         return SOC_E_PARAM;
   8761     }
   8762 
   8763     if (_bcm_th3_wred_resolution_tbl[index] == 0) {
   8764         return SOC_E_NOT_FOUND;
   8765     }
   8766 
   8767     /* hw reset value */
   8768     soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, 0xAAA);
   8769     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval));
   8770     _bcm_th3_wred_resolution_tbl[index] = 0;
   8771 
   8772     return SOC_E_NONE;
   8773 }
   8774 
   8775 /*
   8776  * Function:
   8777  *     bcm_th3_cosq_wred_resolution_set
   8778  * Purpose:
   8779  *     Set one rule of a resolution table entry
   8780  * Parameters:
   8781  *     unit                - (IN) unit number
   8782  *     index               - (IN) entry index
   8783  *     rule                - (IN) drop rule
   8784  * Returns:
   8785  *     BCM_E_XXX
   8786  * Notes:
   8787  *     One entry has 12 bits, equals to 6 rules
   8788  */
   8789 int
   8790 bcm_th3_cosq_wred_resolution_set(int unit, int index, bcm_cosq_discard_rule_t *rule)
   8791 {
   8792     uint32 offset, sp, qmin;
   8793     uint32 rval, fval, drop;
   8794     soc_reg_t reg = MMU_WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   8795 
   8796     if ((index < 0) || (index >= _BCM_TH3_NUM_WRED_RESOLUTION_TABLE)) {
   8797         return SOC_E_PARAM;
   8798     }
   8799 
   8800     if (_bcm_th3_wred_resolution_tbl[index] == 0) {
   8801         return BCM_E_NOT_FOUND;
   8802     }
   8803 
   8804     switch (rule->egress_pool_congestion_state) {
   8805         case BCM_COSQ_DISCARD_CONGESTION_LOW:
   8806             sp = 0;
   8807             break;
   8808         case BCM_COSQ_DISCARD_CONGESTION_MEDIUM:
   8809             sp = 1;
   8810             break;
   8811         case BCM_COSQ_DISCARD_CONGESTION_HIGH:
   8812             sp = 2;
   8813             break;
   8814         default:
   8815             return SOC_E_PARAM;
   8816     }
   8817     switch (rule->queue_min_congestion_state) {
   8818         case BCM_COSQ_DISCARD_CONGESTION_LOW:
   8819             qmin = 0;
   8820             break;
   8821         case BCM_COSQ_DISCARD_CONGESTION_HIGH:
   8822             qmin = 1;
   8823             break;
   8824         default:
   8825             return SOC_E_PARAM;
   8826     }
   8827 
   8828     switch (rule->action) {
   8829         case BCM_COSQ_DISCARD_ACTION_WRED_DROP:
   8830             drop = 0x2;
   8831             break;
   8832         case BCM_COSQ_DISCARD_ACTION_FORCE_DROP:
   8833             drop = 0x3;
   8834             break;
   8835         case BCM_COSQ_DISCARD_ACTION_FORCE_NO_DROP:
   8836             drop = 0x0;
   8837             break;
   8838         default:
   8839             return SOC_E_PARAM;
   8840     }
   8841 
   8842     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval));
   8843     fval = soc_reg_field_get(unit, reg, rval, MMU_CONGESTION_EXPERIENCEf);
   8844 
   8845     offset = (sp * 2 + qmin) * 2;       /* 2 bits per rule */
   8846     fval = (fval & (~(0x3 << offset))) | (drop << offset);
   8847 
   8848     soc_reg_field_set(unit, reg, &rval, MMU_CONGESTION_EXPERIENCEf, fval);
   8849     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval));
   8850 
   8851     return SOC_E_NONE;
   8852 }
   8853 
   8854 /*
   8855  * Function:
   8856  *     bcm_th3_cosq_wred_resolution_get
   8857  * Purpose:
   8858  *     Get all rules of a resolution table entry
   8859  * Parameters:
   8860  *     unit                - (IN) unit number
   8861  *     index               - (IN) entry index
   8862  *     max                 - (IN) rule array size
   8863  *     rule                - (OUT) rule array
   8864  *     count               - (OUT) actual rules count
   8865  * Returns:
   8866  *     BCM_E_XXX
   8867  * Notes:
   8868  *     One entry has 12 bits, equals to 6 rules
   8869  */
   8870 int
   8871 bcm_th3_cosq_wred_resolution_get(int unit, int index, int max,
   8872                                  bcm_cosq_discard_rule_t *rule, int *count)
   8873 {
   8874     uint32 offset, sp, qmin, i = 0;
   8875     uint32 rval, fval, action;
   8876     soc_reg_t reg = MMU_WRED_CONG_NOTIFICATION_RESOLUTION_TABLEr;
   8877     uint32 sp_map[3] = {
   8878         BCM_COSQ_DISCARD_CONGESTION_LOW,
   8879         BCM_COSQ_DISCARD_CONGESTION_MEDIUM,
   8880         BCM_COSQ_DISCARD_CONGESTION_HIGH,
   8881     };
   8882     uint32 qmin_map[2] = {
   8883         BCM_COSQ_DISCARD_CONGESTION_LOW,
   8884         BCM_COSQ_DISCARD_CONGESTION_HIGH,
   8885     };
   8886     uint32 action_map[4] = {
   8887         BCM_COSQ_DISCARD_ACTION_FORCE_NO_DROP,
   8888         -1,
   8889         BCM_COSQ_DISCARD_ACTION_WRED_DROP,
   8890         BCM_COSQ_DISCARD_ACTION_FORCE_DROP,
   8891     };
   8892     if ((!count) ||
   8893         (index < 0) || (index >= _BCM_TH3_NUM_WRED_RESOLUTION_TABLE)) {
   8894         return SOC_E_PARAM;
   8895     }
   8896 
   8897     *count = 3 * 2;
   8898 
   8899     if (!rule) {
   8900         return SOC_E_NONE;
   8901     }
   8902 
   8903     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval));
   8904     fval = soc_reg_field_get(unit, reg, rval, MMU_CONGESTION_EXPERIENCEf);
   8905 
   8906     for (sp = 0; sp < 3; sp ++) {
   8907         for (qmin = 0; qmin < 2; qmin ++) {
   8908             offset = (sp * 2 + qmin) * 2;       /* 2 bits per rule */
   8909             action = (fval >> offset) & 0x3;
   8910             if (i < max) {
   8911                 rule[i].egress_pool_congestion_state = sp_map[sp];
   8912                 rule[i].queue_min_congestion_state = qmin_map[qmin];
   8913                 rule[i].action = action_map[action];
   8914                 i++;
   8915             }
   8916         }
   8917     }
   8918 
   8919     return SOC_E_NONE;
   8920 }
   8921 
   8922 /* Shaper APIs */
   8923 /*
   8924  * Function:
   8925  *     bcm_th3_cosq_gport_bandwidth_get
   8926  * Purpose:
   8927  *     Get COS queue bandwidth control configuration
   8928  * Parameters:
   8929  *     unit   - (IN) unit number
   8930  *     gport  - (IN) GPORT identifier
   8931  *     cosq   - (IN) COS queue to get, -1 for any COS queue
   8932  *     kbits_sec_min - (OUT) minimum bandwidth, kbits/sec
   8933  *     kbits_sec_max - (OUT) maximum bandwidth, kbits/sec
   8934  *     flags  - (OUT) BCM_COSQ_BW_*
   8935  * Returns:
   8936  *     BCM_E_XXX
   8937  */
   8938 int
   8939 bcm_th3_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
   8940                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
   8941                                 uint32 *kbits_sec_max, uint32 *flags)
   8942 {
   8943     uint32 kbits_sec_burst;
   8944 
   8945     BCM_IF_ERROR_RETURN
   8946         (_bcm_th3_cosq_bucket_get(unit, gport, cosq,
   8947                                  kbits_sec_min, kbits_sec_max,
   8948                                  &kbits_sec_burst, &kbits_sec_burst, flags));
   8949     return BCM_E_NONE;
   8950 }
   8951 
   8952 /*
   8953  * Function:
   8954  *     bcm_th3_cosq_gport_bandwidth_set
   8955  * Purpose:
   8956  *     Configure COS queue bandwidth control
   8957  * Parameters:
   8958  *     unit   - (IN) unit number
   8959  *     gport  - (IN) GPORT identifier
   8960  *     cosq   - (IN) COS queue to configure, -1 for all COS queues
   8961  *     kbits_sec_min - (IN) minimum bandwidth, kbits/sec
   8962  *     kbits_sec_max - (IN) maximum bandwidth, kbits/sec
   8963  *     flags  - (IN) BCM_COSQ_BW_*
   8964  * Returns:
   8965  *     BCM_E_XXX
   8966  */
   8967 int
   8968 bcm_th3_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
   8969                                 bcm_cos_queue_t cosq, uint32 kbits_sec_min,
   8970                                 uint32 kbits_sec_max, uint32 flags)
   8971 {
   8972     int i, start_cos=0, end_cos=0, local_port;
   8973     _bcm_th3_cosq_node_t *node = NULL;
   8974     uint32 burst_min, burst_max;
   8975 
   8976     BCM_IF_ERROR_RETURN(_bcm_th3_cosq_localport_resolve(unit, gport,
   8977                                                        &local_port));
   8978     if (BCM_GPORT_IS_SET(gport)) {
   8979         if ((BCM_GPORT_IS_SCHEDULER(gport)) ||
   8980           BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport) ||
   8981           BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
   8982             BCM_IF_ERROR_RETURN
   8983                 (_bcm_th3_cosq_node_get(unit, gport, NULL,
   8984                                         NULL, NULL, &node));
   8985             if (node != NULL) {
   8986                 start_cos = end_cos = node->hw_index;
   8987             } else {
   8988                 cosq = 0;
   8989             }
   8990         } else {
   8991             if (cosq < 0) {
   8992                 return BCM_E_PARAM;
   8993             }
   8994             start_cos = end_cos = cosq;
   8995         }
   8996     } else {
   8997         if (cosq < 0) {
   8998             return BCM_E_PARAM;
   8999         }
   9000         start_cos = end_cos = cosq;
   9001     }
   9002 
   9003     burst_min = (kbits_sec_min > 0) ?
   9004           _bcm_th3_default_burst_size(unit, local_port, kbits_sec_min) : 0;
   9005 
   9006     burst_max = (kbits_sec_max > 0) ?
   9007           _bcm_th3_default_burst_size(unit, local_port, kbits_sec_max) : 0;
   9008 
   9009     for (i = start_cos; i <= end_cos; i++) {
   9010         BCM_IF_ERROR_RETURN
   9011             (_bcm_th3_cosq_bucket_set(unit, gport, i, kbits_sec_min,
   9012                          kbits_sec_max, burst_min, burst_max, flags));
   9013     }
   9014 
   9015     return BCM_E_NONE;
   9016 }
   9017 
   9018 STATIC int
   9019 _bcm_th3_cosq_cpu_port_info_dump(int unit)
   9020 {
   9021     _bcm_th3_cosq_cpu_port_info_t *port_info;
   9022     bcm_port_t port = 0; /* CPU Port */
   9023     _bcm_th3_cosq_node_t *node;
   9024     int index;
   9025     soc_th3_sched_mode_e sched_mode = 0;
   9026     int weight = 0;
   9027     char *sched_modes[] = {"X", "SP", "WRR", "WERR"};
   9028 
   9029     if (!SOC_PORT_VALID(unit, port)) {
   9030         return BCM_E_PORT;
   9031     }
   9032     port_info = _bcm_th3_cosq_cpu_port_info[unit];
   9033 
   9034     LOG_CLI((BSL_META_U(unit,
   9035                         "=== CPU PORT ===\n")));
   9036 
   9037     LOG_CLI((BSL_META_U(unit,
   9038                         "L0 Nodes\n")));
   9039     for (index = 0; index < _BCM_TH3_NUM_SCHEDULER_PER_PORT; index++) {
   9040         /* Node */
   9041         node = &port_info->sched[index];
   9042 
   9043         BCM_IF_ERROR_RETURN(
   9044                 soc_th3_cosq_sched_mode_get(unit, port, node->level, index,
   9045                                            &sched_mode, &weight, 0));
   9046         LOG_CLI((BSL_META_U(unit,
   9047                             "    LO.%d: GPORT=0x%x MODE=%s WT=%d\n"),
   9048                              index, node->gport,
   9049                              sched_modes[sched_mode], weight));
   9050     }
   9051 
   9052     LOG_CLI((BSL_META_U(unit,
   9053                         "\nMC Queues\n")));
   9054     for (index = 0; index < _BCM_TH3_NUM_CPU_MCAST_QUEUE; index++) {
   9055         int parent_id = 0;
   9056         /* MC Queue */
   9057         node = &port_info->mcast[index];
   9058         BCM_IF_ERROR_RETURN(
   9059                 soc_th3_cosq_sched_mode_get(unit, port, node->level, index,
   9060                                            &sched_mode, &weight, 1));
   9061         BCM_IF_ERROR_RETURN(
   9062             _bcm_th3_cosq_node_get(unit, node->parent_gport, NULL, NULL,
   9063                                   &parent_id, NULL));
   9064         LOG_CLI((BSL_META_U(unit,
   9065                             "    MC.%d: GPORT=0x%x MODE=%s WT=%d"
   9066                             " PARENT=L0.%d\n"),
   9067                              index, node->gport,
   9068                              sched_modes[sched_mode], weight,
   9069                              parent_id));
   9070     }
   9071     LOG_CLI((BSL_META_U(unit,
   9072                         "=========== \n")));
   9073 
   9074     return BCM_E_NONE;
   9075 }
   9076 
   9077 STATIC int
   9078 _bcm_th3_cosq_port_info_dump(int unit, bcm_port_t port)
   9079 {
   9080     _bcm_th3_cosq_port_info_t *port_info;
   9081     _bcm_th3_cosq_node_t *node;
   9082     soc_th3_cosq_node_t *l1_node;
   9083     int index, empty;
   9084     soc_th3_sched_mode_e sched_mode = 0;
   9085     int weight = 0;
   9086     char *sched_modes[] = {"X", "SP", "WRR", "WERR"};
   9087     int l1_parent = -1;
   9088 
   9089     if (!SOC_PORT_VALID(unit, port)) {
   9090         return BCM_E_PORT;
   9091     }
   9092     port_info = &_bcm_th3_cosq_port_info[unit][port];
   9093 
   9094     empty = TRUE;
   9095     for (index = 0; index < _BCM_TH3_NUM_SCHEDULER_PER_PORT; index++) {
   9096         if (port_info->sched[index].numq > 0) {
   9097             empty = FALSE;
   9098             break;
   9099         }
   9100     }
   9101     if (empty) {
   9102         for (index = 0; index < _bcm_th3_get_num_ucq(unit); index++) {
   9103             if (port_info->ucast[index].numq > 0) {
   9104                 empty = FALSE;
   9105                 break;
   9106             }
   9107         }
   9108     }
   9109     if (empty) {
   9110         for (index = 0; index < _bcm_th3_get_num_mcq(unit); index++) {
   9111             if (port_info->mcast[index].numq > 0) {
   9112                 empty = FALSE;
   9113                 break;
   9114             }
   9115         }
   9116     }
   9117 
   9118     if (empty == TRUE) {
   9119         return BCM_E_NOT_FOUND;
   9120     }
   9121 
   9122     LOG_CLI((BSL_META_U(unit,
   9123                         "=== PORT %d\n"), port));
   9124 
   9125     for (index = 0; index < _BCM_TH3_NUM_SCHEDULER_PER_PORT; index++) {
   9126         /* Node */
   9127         node = &port_info->sched[index];
   9128         if (node->in_use == 0 || node->numq == 0) {
   9129             continue;
   9130         }
   9131 
   9132         BCM_IF_ERROR_RETURN(
   9133                 soc_th3_cosq_sched_mode_get(unit, port, node->level, index,
   9134                                            &sched_mode, &weight, 0));
   9135         LOG_CLI((BSL_META_U(unit,
   9136                             "LO.%d: GPORT=0x%x MODE=%s WT=%d, COS=%d\n"),
   9137                              index, node->gport,
   9138                              sched_modes[sched_mode], weight, node->cos));
   9139     }
   9140 
   9141     for (index = 0; index < _bcm_th3_get_num_ucq(unit); index++) {
   9142         /* UC Queue */
   9143         int parent_id;
   9144         node = &port_info->ucast[index];
   9145         l1_node =
   9146             th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[index].parent;
   9147         BCM_IF_ERROR_RETURN(soc_th3_cosq_parent_get(unit, port, index,
   9148                     node->level, &l1_parent));
   9149         BCM_IF_ERROR_RETURN(
   9150             soc_th3_cosq_sched_mode_get(unit, port, l1_node->level,
   9151                 l1_parent, &sched_mode, &weight, 0));
   9152         BCM_IF_ERROR_RETURN(
   9153             _bcm_th3_cosq_node_get(unit, node->parent_gport, NULL, NULL,
   9154                                   &parent_id, NULL));
   9155         LOG_CLI((BSL_META_U(unit,
   9156                         "UC.%d: GPORT=0x%x MODE=%s WT=%d PARENT=%d\n"),
   9157                          index, node->gport,
   9158                          sched_modes[sched_mode], weight, parent_id));
   9159     }
   9160 
   9161     for (index = 0; index < _bcm_th3_get_num_mcq(unit); index++) {
   9162         /* MC Queue */
   9163         int parent_id;
   9164         node = &port_info->mcast[index];
   9165         l1_node =
   9166             th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[(index +
   9167             _bcm_th3_get_num_ucq(unit))].parent; 
   9168         BCM_IF_ERROR_RETURN(soc_th3_cosq_parent_get(unit, port,
   9169                     (index + _bcm_th3_get_num_ucq(unit)),
   9170                     node->level, &l1_parent));
   9171         BCM_IF_ERROR_RETURN(
   9172             soc_th3_cosq_sched_mode_get(unit, port, l1_node->level,
   9173                 l1_parent, &sched_mode, &weight, 1));
   9174         BCM_IF_ERROR_RETURN(
   9175             _bcm_th3_cosq_node_get(unit, node->parent_gport, NULL, NULL,
   9176                                   &parent_id, NULL));
   9177         LOG_CLI((BSL_META_U(unit,
   9178                         "MC.%d: GPORT=0x%x MODE=%s WT=%d PARENT=%d\n"),
   9179                          index, node->gport,
   9180                          sched_modes[sched_mode], weight, parent_id));
   9181     }
   9182     LOG_CLI((BSL_META_U(unit,
   9183                         "=========== \n")));
   9184 
   9185     return BCM_E_NONE;
   9186 }
   9187 
   9188 
   9189 /*
   9190  * Function:
   9191  *     bcm_th3_cosq_sw_dump
   9192  * Purpose:
   9193  *     Displays COS Queue information maintained by software.
   9194  * Parameters:
   9195  *     unit - Device unit number
   9196  * Returns:
   9197  *     None
   9198  */
   9199 void
   9200 bcm_th3_cosq_sw_dump(int unit)
   9201 {
   9202     bcm_port_t port;
   9203     int ii;
   9204     LOG_CLI((BSL_META_U(unit,
   9205                         "\nSW Information COSQ - Unit %d\n"), unit));
   9206     PBMP_ALL_ITER(unit, port) {
   9207         if (IS_CPU_PORT(unit, port)) {
   9208             (void)_bcm_th3_cosq_cpu_port_info_dump(unit);
   9209         }
   9210         (void)_bcm_th3_cosq_port_info_dump(unit, port);
   9211     }
   9212     for (ii = 0; ii <  _BCM_TH3_NUM_TIME_DOMAIN; ii++) {
   9213         LOG_CLI((BSL_META_U(unit,
   9214                             "\nTIME_DOMAIN[%d] - refcnt %d\n"), ii,
   9215                             th3_time_domain_info[unit][ii].ref_count));
   9216     }
   9217 
   9218     return;
   9219 }
   9220 
   9221 
   9222 /*
   9223  * Function:
   9224  *      _bcm_th3_cosq_port_guarantee_reset
   9225  * Purpose:
   9226  *      Reset the guarantee of priority group, uc queue, mc queue to the default
   9227  * Parameters:
   9228  *      unit    - (IN) Unit number.
   9229  *      port    - (IN) Logical port.
   9230  * Returns:
   9231  *      BCM_E_XXX
   9232  */
   9233 STATIC int
   9234 _bcm_th3_cosq_port_guarantee_reset(int unit, bcm_port_t port)
   9235 {
   9236     _soc_mmu_device_info_t devcfg;
   9237     int lossless, override, default_mtu_cells, idx, numq;
   9238     int pg_guarantee, uc_guarantee, mc_guarantee;
   9239     int qgroup_uc_guarantee, qgroup_mc_guarantee;
   9240 
   9241     lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 0);
   9242     override = soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1);
   9243 
   9244     _soc_th3_mmu_init_dev_config(unit, &devcfg, lossless);
   9245     default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg.default_mtu_size +
   9246                                                     devcfg.mmu_hdr_byte,
   9247                                                     devcfg.mmu_cell_size);
   9248 
   9249     /* priority group */
   9250     for (idx = 0; idx < _TH3_MMU_NUM_PG; idx++) {
   9251         pg_guarantee = 0;
   9252         if ((idx == 7) && lossless) {
   9253             pg_guarantee = default_mtu_cells;
   9254         }
   9255         if (!override) {
   9256             _soc_mmu_cfg_property_get_cells
   9257                 (unit, port, spn_PRIGROUP, idx, spn_GUARANTEE, FALSE,
   9258                  &pg_guarantee, devcfg.mmu_cell_size,
   9259                  _MMU_DEFAULT_THRES_TYPE);
   9260             pg_guarantee *= devcfg.mmu_cell_size;
   9261         }
   9262         BCM_IF_ERROR_RETURN
   9263             (_bcm_th3_cosq_ing_res_set(unit, port, idx,
   9264                                       bcmCosqControlIngressPortPGMinLimitBytes,
   9265                                       pg_guarantee));
   9266     }
   9267 
   9268     /* UC */
   9269     numq = _bcm_th3_get_num_ucq(unit);
   9270     for (idx = 0; idx < numq; idx++) {
   9271         uc_guarantee = 0;
   9272         if (!override) {
   9273             _soc_mmu_cfg_property_get_cells
   9274                 (unit, port, spn_QUEUE, idx, spn_GUARANTEE, FALSE,
   9275                  &uc_guarantee, devcfg.mmu_cell_size,
   9276                  _MMU_DEFAULT_THRES_TYPE);
   9277             uc_guarantee *= devcfg.mmu_cell_size;
   9278         }
   9279         BCM_IF_ERROR_RETURN
   9280             (_bcm_th3_cosq_egr_queue_set(unit, port, idx,
   9281                                        bcmCosqControlEgressUCQueueMinLimitBytes,
   9282                                        uc_guarantee));
   9283     }
   9284 
   9285     /* MC */
   9286     numq = _bcm_th3_get_num_ucq(unit) + _bcm_th3_get_num_mcq(unit);
   9287     for (idx = _bcm_th3_get_num_ucq(unit); idx < numq; idx++) {
   9288         mc_guarantee = 0;
   9289         if (!override) {
   9290             _soc_mmu_cfg_property_get_cells
   9291                 (unit, port, spn_MQUEUE, idx, spn_GUARANTEE, FALSE,
   9292                  &mc_guarantee, devcfg.mmu_cell_size,
   9293                  _MMU_DEFAULT_THRES_TYPE);
   9294             mc_guarantee *= devcfg.mmu_cell_size;
   9295         }
   9296         BCM_IF_ERROR_RETURN
   9297             (_bcm_th3_cosq_egr_queue_set(unit, port, idx,
   9298                                        bcmCosqControlEgressMCQueueMinLimitBytes,
   9299                                        mc_guarantee));
   9300     }
   9301 
   9302     /* QGROUP UC */
   9303     numq = _bcm_th3_get_num_ucq(unit);
   9304     for (idx = 0; idx < numq; idx++) {
   9305         qgroup_uc_guarantee = 0;
   9306         if (!override) {
   9307             _soc_mmu_cfg_property_get_cells
   9308                 (unit, -1, spn_QGROUP, idx, spn_GUARANTEE, FALSE,
   9309                  &qgroup_uc_guarantee, devcfg.mmu_cell_size,
   9310                  _MMU_DEFAULT_THRES_TYPE);
   9311             qgroup_uc_guarantee *= devcfg.mmu_cell_size;
   9312         }
   9313         BCM_IF_ERROR_RETURN
   9314             (_bcm_th3_cosq_qgroup_limit_set(unit, port, idx,
   9315                                        bcmCosqControlEgressUCQueueGroupMinLimitBytes,
   9316                                        qgroup_uc_guarantee));
   9317     }
   9318 
   9319     /* QGROUP MC */
   9320     numq = _bcm_th3_get_num_ucq(unit) + _bcm_th3_get_num_mcq(unit);
   9321     for (idx = _bcm_th3_get_num_ucq(unit); idx < numq; idx++) {
   9322         qgroup_mc_guarantee = 0;
   9323         if (!override) {
   9324             _soc_mmu_cfg_property_get_cells
   9325                 (unit, -1, spn_QGROUP, idx, spn_GUARANTEE_MC, FALSE,
   9326                  &qgroup_mc_guarantee, devcfg.mmu_cell_size,
   9327                  _MMU_DEFAULT_THRES_TYPE);
   9328             qgroup_mc_guarantee *= devcfg.mmu_cell_size;
   9329         }
   9330         BCM_IF_ERROR_RETURN
   9331             (_bcm_th3_cosq_qgroup_limit_set(unit, port, idx,
   9332                                        bcmCosqControlEgressMCQueueGroupMinLimitBytes,
   9333                                        qgroup_mc_guarantee));
   9334     }
   9335 
   9336     return BCM_E_NONE;
   9337 }
   9338 
   9339 /*
   9340  * Function:
   9341  *      bcm_th3_cosq_port_detach
   9342  * Purpose:
   9343  *      Clear cosq configuration of port
   9344  * Parameters:
   9345  *      unit    - (IN) Unit number.
   9346  *      port    - (IN) Logical port.
   9347  * Returns:
   9348  *      SOC_E_XXX
   9349  */
   9350 int
   9351 bcm_th3_cosq_port_detach(int unit, bcm_port_t port)
   9352 {
   9353     soc_info_t *si = &SOC_INFO(unit);
   9354     _bcm_th3_cosq_port_info_t *port_info = NULL;
   9355     uint32 profile_index;
   9356     uint32 entry[SOC_MAX_MEM_WORDS];
   9357 
   9358     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
   9359         IS_MANAGEMENT_PORT(unit, port)) {
   9360         return BCM_E_PARAM;
   9361     }
   9362     LOG_INFO(BSL_LS_BCM_COSQ,
   9363              (BSL_META_U(unit,
   9364                          "bcm_th3_cosq_port_detach port %d\n"),
   9365               port));
   9366 
   9367     /* When update guarantee of PG/UC/MC via API, the shared limit is adjusted
   9368      * accordingly. So MUST reset the gurarntee to the default value before
   9369      * deleting the port to recover the shared limit. */
   9370     BCM_IF_ERROR_RETURN
   9371         (_bcm_th3_cosq_port_guarantee_reset(unit, port));
   9372 
   9373     /* Destroy cosq gport tree on port */
   9374     port_info = &_bcm_th3_cosq_port_info[unit][port];
   9375     sal_memset(port_info, 0, sizeof(_bcm_th3_cosq_port_info_t));
   9376 
   9377     /* Reset soc gport tree on port */
   9378     BCM_IF_ERROR_RETURN(soc_tomahawk3_cosq_port_info_init(unit, port));
   9379 
   9380     /* Decrease the reference of COS_MAP_PROFILE */
   9381     SOC_IF_ERROR_RETURN
   9382         (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry));
   9383     profile_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
   9384     SOC_IF_ERROR_RETURN
   9385         (soc_profile_mem_delete(unit, _bcm_th3_cos_map_profile[unit],
   9386                                 profile_index * 16));
   9387 
   9388     /* Clear cosq */
   9389     si->port_num_cosq[port] = 0;
   9390     si->port_cosq_base[port] = 0;
   9391     si->port_num_uc_cosq[port] = 0;
   9392     si->port_uc_cosq_base[port] = 0;
   9393     si->port_num_ext_cosq[port] = 0;
   9394 
   9395     return BCM_E_NONE;
   9396 }
   9397 
   9398 
   9399 /*
   9400  * Function:
   9401  *      bcm_th3_cosq_port_attach
   9402  * Purpose:
   9403  *      Initialize Cosq for newly added port
   9404  * Parameters:
   9405  *      unit    - (IN) Unit number.
   9406  *      port    - (IN) Logical port.
   9407  * Returns:
   9408  *      SOC_E_XXX
   9409  */
   9410 int
   9411 bcm_th3_cosq_port_attach(int unit, bcm_port_t port)
   9412 {
   9413     soc_info_t *si = &SOC_INFO(unit);
   9414     _bcm_th3_cosq_port_info_t *port_info = NULL;
   9415     int default_mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN, default_weight = 1;
   9416     int i, itm_map, shd_size, pipe;
   9417     int L0[_BCM_TH3_COS_MAX];
   9418     int schedq[_BCM_TH3_COS_MAX];
   9419     int mmuq[_BCM_TH3_COS_MAX];
   9420     int cos_list[_BCM_TH3_COS_MAX];
   9421     soc_reg_t reg;
   9422     uint64 rval_64;
   9423     soc_field_t mmuq_field[12] = {
   9424         MMU_Q_NUM_0f, MMU_Q_NUM_1f,
   9425         MMU_Q_NUM_2f, MMU_Q_NUM_3f,
   9426         MMU_Q_NUM_4f, MMU_Q_NUM_5f,
   9427         MMU_Q_NUM_6f, MMU_Q_NUM_7f,
   9428         MMU_Q_NUM_8f, MMU_Q_NUM_9f,
   9429         MMU_Q_NUM_10f, MMU_Q_NUM_11f,
   9430     };
   9431 
   9432     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) ||
   9433         IS_MANAGEMENT_PORT(unit, port)) {
   9434         return BCM_E_PARAM;
   9435     }
   9436     LOG_INFO(BSL_LS_BCM_COSQ,
   9437              (BSL_META_U(unit,
   9438                          "bcm_th3_cosq_port_attach port %d\n"),
   9439               port));
   9440 
   9441     /* Increase the reference of default COS_MAP_PROFILE */
   9442     BCM_IF_ERROR_RETURN
   9443         (soc_mem_field32_modify(unit, COS_MAP_SELm, port, SELECTf, 0));
   9444     BCM_IF_ERROR_RETURN
   9445         (soc_profile_mem_reference(unit, _bcm_th3_cos_map_profile[unit], 0, 0));
   9446 
   9447     /* set scheduler profile to port 0 */
   9448     reg = MMU_PPSCH_SCHQ_MMUQ_PROFILEr;
   9449     SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval_64));
   9450 
   9451     for (i = 0; i < _BCM_TH3_NUM_SCHEDULER_PER_PORT; i++) {
   9452         L0[i] = L1_TO_L0_MAPPING[unit][0][i];
   9453         schedq[i] = i;
   9454         mmuq[i] = soc_reg64_field32_get(unit, reg, rval_64, mmuq_field[i]);
   9455         cos_list[i] = L0_TO_COSQ_MAPPING[unit][0][i];
   9456     }
   9457     soc_tomahawk3_sched_update_flex_per_port(unit, port, 0, L0, schedq, mmuq, cos_list);
   9458 
   9459     /* Create gport tree */
   9460     _BCM_TH3_MMU_INFO(unit)->gport_tree_created = FALSE;
   9461     BCM_IF_ERROR_RETURN(_bcm_th3_cosq_gport_tree_create(unit, port));
   9462     _BCM_TH3_MMU_INFO(unit)->gport_tree_created = TRUE;
   9463 
   9464     /* Set Default Scheduler Configuration on the ports */
   9465     port_info = &_bcm_th3_cosq_port_info[unit][port];
   9466     for (i = 0; i < _BCM_TH3_NUM_SCHEDULER_PER_PORT; i++) {
   9467         if (port_info->sched[i].in_use == 0 || port_info->sched[i].numq == 0) {
   9468             continue;
   9469         }
   9470 
   9471         BCM_IF_ERROR_RETURN(
   9472                 bcm_th3_cosq_gport_sched_set(unit, port_info->sched[i].gport,
   9473                 -1, default_mode, default_weight));
   9474     }
   9475     for (i = 0; i < _bcm_th3_get_num_ucq(unit); i++) {
   9476         BCM_IF_ERROR_RETURN
   9477             (bcm_th3_cosq_gport_sched_set(unit, port_info->ucast[i].gport,
   9478                 -1, default_mode, default_weight));
   9479     }
   9480     for (i = 0; i < _bcm_th3_get_num_mcq(unit); i++) {
   9481         BCM_IF_ERROR_RETURN
   9482             (bcm_th3_cosq_gport_sched_set(unit, port_info->mcast[i].gport,
   9483                 -1, default_mode, default_weight));
   9484     }
   9485 
   9486     /* Set MMU threshold and scheduler profiles to profile 0
   9487      * Customer can change the profile after flexport sequence is done */
   9488     BCM_IF_ERROR_RETURN(bcm_tomahawk3_cosq_port_profile_set(unit, port,
   9489                        bcmCosqProfilePGProperties, 0));
   9490     BCM_IF_ERROR_RETURN(bcm_tomahawk3_cosq_port_profile_set(unit, port,
   9491                        bcmCosqProfileIntPriToPGMap, 0));
   9492     BCM_IF_ERROR_RETURN(bcm_tomahawk3_cosq_port_profile_set(unit, port,
   9493                        bcmCosqProfilePFCAndQueueHierarchy, 0));
   9494 
   9495     /* Update shared limit of new ports in case the shared limit has been
   9496      * adjusted by bcm_cosq_control_set() API */
   9497     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, port, &pipe));
   9498     shd_size = 0;
   9499     for (i = 0; i < NUM_ITM(unit); i++) {
   9500         itm_map = si->itm_ipipe_map[i];
   9501         if (itm_map & (1 << pipe)) {
   9502             shd_size = _BCM_TH3_MMU_INFO(unit)->shared_limit[i];
   9503         }
   9504     }
   9505 
   9506     BCM_IF_ERROR_RETURN(
   9507         soc_th3_mmu_config_flex_thresholds(unit, port, shd_size));
   9508 
   9509     return BCM_E_NONE;
   9510 }
   9511 
   9512 int
   9513 bcm_th3_cosq_gport_mapping_set(int unit, bcm_port_t ing_port,
   9514                               bcm_cos_t int_pri, uint32 flags,
   9515                               bcm_gport_t gport, bcm_cos_queue_t cosq)
   9516 {
   9517     bcm_port_t local_port;
   9518 
   9519     if ((int_pri < 0) || (int_pri >= _TH3_MMU_NUM_INT_PRI)) {
   9520         return BCM_E_PARAM;
   9521     }
   9522 
   9523     BCM_IF_ERROR_RETURN(_bcm_th3_cosq_localport_resolve(unit, ing_port,
   9524                                                        &local_port));
   9525 
   9526     if ((cosq < 0) || (cosq >= _TH3_PORT_NUM_COS(unit, local_port))) {
   9527         return BCM_E_PARAM;
   9528     }
   9529 
   9530     return _bcm_th3_cosq_mapping_set(unit, ing_port, int_pri, flags, gport,
   9531                                     cosq, cosq);
   9532 }
   9533 
   9534 int
   9535 bcm_th3_cosq_gport_mapping_get(int unit, bcm_port_t ing_port,
   9536                               bcm_cos_t int_pri, uint32 flags,
   9537                               bcm_gport_t *gport, bcm_cos_queue_t *cosq)
   9538 {
   9539     if (gport == NULL || cosq == NULL) {
   9540         return BCM_E_PARAM;
   9541     }
   9542 
   9543     if ((int_pri < 0) || (int_pri >= _TH3_MMU_NUM_INT_PRI)) {
   9544         return BCM_E_PARAM;
   9545     }
   9546 
   9547     return _bcm_th3_cosq_mapping_get(unit, ing_port, int_pri, flags, gport,
   9548                                     cosq);
   9549 }
   9550 
   9551 /*Function to return the number of child nodes and child node gport array for
   9552  * scheduler gport */
   9553 int
   9554 _bcm_th3_cosq_sched_node_child_get(int unit, bcm_gport_t sched_gport, int
   9555         *num_uc_child, int *uc_queue, int *num_mc_child, int *mc_queue)
   9556 {
   9557     _bcm_th3_cosq_port_info_t *port_info = NULL;
   9558     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
   9559 
   9560     int local_port, id;
   9561     _bcm_th3_cosq_index_style_t style = _BCM_TH3_COSQ_INDEX_STYLE_COS;
   9562     int num_mc, num_uc;
   9563     int cpu_mc_base;
   9564     soc_info_t *si = &SOC_INFO(unit);
   9565 
   9566     if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) {
   9567         /* Function valid only scheduler gport*/
   9568         return BCM_E_INTERNAL;
   9569     }
   9570     if ((num_uc_child == NULL) || (uc_queue == NULL) || (num_mc_child == NULL)
   9571             || (mc_queue == NULL)) {
   9572         return BCM_E_INTERNAL;
   9573     }
   9574 
   9575     BCM_IF_ERROR_RETURN
   9576             (_bcm_th3_cosq_index_resolve
   9577             (unit, sched_gport, -1, style, &local_port, NULL, NULL));
   9578 
   9579     if (!IS_CPU_PORT(unit, local_port)) {
   9580         port_info = &_bcm_th3_cosq_port_info[unit][local_port];
   9581         num_uc = 0;
   9582         num_mc = 0;
   9583         for (id = 0; id < si->port_num_uc_cosq[local_port]; id++) {
   9584             if (port_info->ucast[id].numq == 0) {
   9585                 continue;
   9586             }
   9587             if (port_info->ucast[id].parent_gport == sched_gport) {
   9588                 uc_queue[num_uc] = port_info->ucast[id].hw_index %
   9589                     si->port_num_uc_cosq[local_port];
   9590                 num_uc++;
   9591             }
   9592         }
   9593         for (id = 0; id < si->port_num_cosq[local_port]; id++) {
   9594             if (port_info->mcast[id].numq == 0) {
   9595                 continue;
   9596             }
   9597             if (port_info->mcast[id].parent_gport == sched_gport) {
   9598                     mc_queue[num_mc] = port_info->mcast[id].hw_index %
   9599                         si->port_num_cosq[local_port];
   9600                 num_mc++;
   9601             }
   9602         }
   9603     } else {
   9604         /* CPU port */
   9605         num_uc = -1;
   9606         num_mc = 0;
   9607         cpu_port_info = _bcm_th3_cosq_cpu_port_info[unit];
   9608         for (id = 0; id < _BCM_TH3_NUM_CPU_MCAST_QUEUE; id++) {
   9609             if (cpu_port_info->mcast[id].numq == 0) {
   9610                 continue;
   9611             }
   9612             if (cpu_port_info->mcast[id].parent_gport == sched_gport) {
   9613                 cpu_mc_base = si->port_cosq_base[CMIC_PORT(unit)];
   9614                 mc_queue[num_mc] = (cpu_port_info->mcast[id].hw_index -
   9615                         cpu_mc_base) % NUM_CPU_COSQ(unit);
   9616                 num_mc++;
   9617             }
   9618         }
   9619     }
   9620     *num_mc_child = num_mc;
   9621     *num_uc_child = num_uc;
   9622 
   9623     return BCM_E_NONE;
   9624 }
   9625 
   9626 
   9627 /*
   9628  * Function:
   9629  *      bcm_th3_cosq_field_classifier_get
   9630  * Purpose:
   9631  *      Get classifier type information.
   9632  * Parameters:
   9633  *      unit          - (IN) Unit number.
   9634  *      classifier_id - (IN) Classifier ID
   9635  *      classifier    - (OUT) Classifier info
   9636  * Returns:
   9637  *      BCM_E_xxx
   9638  */
   9639 int
   9640 bcm_th3_cosq_field_classifier_get(
   9641     int unit,
   9642     int classifier_id,
   9643     bcm_cosq_classifier_t *classifier)
   9644 {
   9645     if (classifier == NULL) {
   9646         return BCM_E_PARAM;
   9647     }
   9648     sal_memset(classifier, 0, sizeof(bcm_cosq_classifier_t));
   9649 
   9650     if (_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
   9651         classifier->flags |= BCM_COSQ_CLASSIFIER_FIELD;
   9652     }
   9653 
   9654     return BCM_E_NONE;
   9655 }
   9656 
   9657 /*
   9658  * Function:
   9659  *      bcm_th3_cosq_field_classifier_id_create
   9660  * Purpose:
   9661  *      Create a cosq classifier.
   9662  * Parameters:
   9663  *      unit          - (IN) Unit number.
   9664  *      classifier    - (IN) Classifier attributes
   9665  *      classifier_id - (OUT) Classifier ID
   9666  * Returns:
   9667  *      BCM_E_xxx
   9668  */
   9669 int
   9670 bcm_th3_cosq_field_classifier_id_create(
   9671     int unit,
   9672     bcm_cosq_classifier_t *classifier,
   9673     int *classifier_id)
   9674 {
   9675     int rv;
   9676     int ref_count = 0;
   9677     int ent_per_set = _TH3_MMU_NUM_INT_PRI;
   9678     int i;
   9679 
   9680     if (NULL == classifier || NULL == classifier_id) {
   9681         return BCM_E_PARAM;
   9682     }
   9683 
   9684     for (i = 0; i < (SOC_MEM_SIZE(unit, IFP_COS_MAPm) - ent_per_set) ; i += ent_per_set) {
   9685         rv = soc_profile_mem_ref_count_get(
   9686                 unit, _bcm_th3_ifp_cos_map_profile[unit], i, &ref_count);
   9687         if (SOC_FAILURE(rv)) {
   9688             return rv;
   9689         }
   9690         if (0 == ref_count) {
   9691             break;
   9692         }
   9693     }
   9694 
   9695     if (i >= (SOC_MEM_SIZE(unit, IFP_COS_MAPm) - ent_per_set) && ref_count != 0) {
   9696         *classifier_id = 0;
   9697         return BCM_E_RESOURCE;
   9698     }
   9699 
   9700     _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, (i / ent_per_set));
   9701 
   9702     return BCM_E_NONE;
   9703 }
   9704 
   9705 /*
   9706  * Function:
   9707  *      bcm_th3_cosq_field_classifier_map_set
   9708  * Purpose:
   9709  *      Set internal priority to ingress field processor CoS queue
   9710  *      override mapping.
   9711  * Parameters:
   9712  *      unit           - (IN) Unit number.
   9713  *      classifier_id  - (IN) Classifier ID
   9714  *      count          - (IN) Number of elements in priority_array and
   9715  *                            cosq_array.
   9716  *      priority_array - (IN) Array of internal priorities
   9717  *      cosq_array     - (IN) Array of COS queues
   9718  * Returns:
   9719  *      BCM_E_xxx
   9720  * Notes:
   9721  *      Supported count value is [0-16] and 48
   9722  *      When count = [0-16]
   9723  *          Array Index [15-0] : Maps Prio[15-0] to UC, MC
   9724  *                               and RQE cos[15-0]
   9725  *      When count = 48
   9726  *      Prio Array Index Map
   9727  *          Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0]
   9728  *          Array Index [31-16] : Maps Prio[15-0] to MC cos[15-0]
   9729  *          Array Index [47-32] : Maps Prio[15-0] to RQE cos[15-0]
   9730  */
   9731 int
   9732 bcm_th3_cosq_field_classifier_map_set(
   9733     int unit,
   9734     int classifier_id,
   9735     int count,
   9736     bcm_cos_t *priority_array,
   9737     bcm_cos_queue_t *cosq_array)
   9738 {
   9739     int rv;
   9740     int i;
   9741     int max_entries = _TH3_MMU_NUM_INT_PRI;
   9742     uint32 index, new_index;
   9743     void *entries[1];
   9744     ifp_cos_map_entry_t ent_buf[_TH3_MMU_NUM_INT_PRI];
   9745     soc_field_t field = -1;
   9746     int min_max_qnum;
   9747     uint16 dev_id;
   9748     uint8 rev_id;
   9749 
   9750     soc_cm_get_id(unit, &dev_id, &rev_id);
   9751 
   9752     /* Input parameter check. */
   9753     if (!_BCM_COSQ_CLASSIFIER_IS_FIELD(classifier_id)) {
   9754         return BCM_E_PARAM;
   9755     }
   9756 
   9757     if (NULL == priority_array || NULL == cosq_array) {
   9758         return BCM_E_PARAM;
   9759     }
   9760 
   9761     if ((count > max_entries) && (count != (max_entries * 3))) {
   9762         return BCM_E_PARAM;
   9763     }
   9764 
   9765     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * max_entries);
   9766     entries[0] = ent_buf;
   9767 
   9768     if (rev_id == BCM56980_A0_REV_ID) {
   9769         min_max_qnum = MIN(MIN(_bcm_th3_get_num_mcq(unit), _bcm_th3_get_num_ucq(unit)),
   9770                            _TH3_A0_MMU_NUM_RQE_QUEUES);
   9771     } else {
   9772         min_max_qnum = MIN(MIN(_bcm_th3_get_num_mcq(unit), _bcm_th3_get_num_ucq(unit)),
   9773                            _TH3_MMU_NUM_RQE_QUEUES);
   9774     }
   9775 
   9776     if (count != (max_entries * 3)) {
   9777         for (i = 0; i < count; i++) {
   9778             if (priority_array[i] < max_entries) {
   9779                 /* When count != max_entries * 3
   9780                    We program the same mapping for all three
   9781                    fields UC/MC/RQE queues.
   9782                    Hence cos_array[i] cannot have value more than
   9783                    equal to MIN(MAX UC_COS, MAX MC_COS, MAX RQE_NUM) */
   9784                 if ((cosq_array[i] < 0) ||
   9785                     (cosq_array[i] >= min_max_qnum)) {
   9786                     return BCM_E_PARAM;
   9787                 }
   9788                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
   9789                                     IFP_MC_COSf, cosq_array[i]);
   9790                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
   9791                                     IFP_UC_COSf, cosq_array[i]);
   9792                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
   9793                                     IFP_RQE_Q_NUMf, cosq_array[i]);
   9794             }
   9795         }
   9796     } else {
   9797         for (i = 0; i < count; i++) {
   9798             if (priority_array[i] < max_entries) {
   9799                 if (i < max_entries) {
   9800                     /* Number of UCAST queue per port can be 6,8,10,12 based on
   9801                        MCQ mode */
   9802                     if ((cosq_array[i] < 0) ||
   9803                         (cosq_array[i] >= _bcm_th3_get_num_ucq(unit))) {
   9804                         return BCM_E_PARAM;
   9805                     }
   9806                     field = IFP_UC_COSf;
   9807                 } else if (i < (max_entries * 2)) {
   9808                     /* Number of MCAST queue per port can be 0,2,4,6 based on
   9809                        MCQ MODE */
   9810                     if ((cosq_array[i] < 0) ||
   9811                         (cosq_array[i] >= _bcm_th3_get_num_mcq(unit))) {
   9812                         return BCM_E_PARAM;
   9813                     }
   9814                     field = IFP_MC_COSf;
   9815                 } else {
   9816                     /* Number of RQE queue per unit = 3 */
   9817                     if (rev_id == BCM56980_A0_REV_ID) {
   9818                         if ((cosq_array[i] < 0) ||
   9819                             (cosq_array[i] >= _TH3_A0_MMU_NUM_RQE_QUEUES)) {
   9820                             return BCM_E_PARAM;
   9821                         }
   9822                     } else {
   9823                         if ((cosq_array[i] < 0) ||
   9824                             (cosq_array[i] >= _TH3_MMU_NUM_RQE_QUEUES)) {
   9825                             return BCM_E_PARAM;
   9826                         }
   9827                     }
   9828                     field = IFP_RQE_Q_NUMf;
   9829                 }
   9830                 soc_mem_field32_set(unit, IFP_COS_MAPm, &ent_buf[priority_array[i]],
   9831                                     field, cosq_array[i]);
   9832             }
   9833         }
   9834     }
   9835 
   9836     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
   9837 
   9838     rv = soc_profile_mem_delete(unit, _bcm_th3_ifp_cos_map_profile[unit],
   9839                                 index * max_entries);
   9840 
   9841     /* If rv = SOC_E_NONE means that there exists a
   9842      * mapping for given classifier_id which is now
   9843      * successfully deleted and we can overwrite.
   9844      * rv = SOC_E_NOT_FOUND means there was no mapping
   9845      * for given classifier_id and we can create a new mapping
   9846      * Otherwise there is something else wrong and we return
   9847      * the error value returned by soc_profile_mem_delete()
   9848      */
   9849     if ((rv != SOC_E_NONE) && (rv != SOC_E_NOT_FOUND)) {
   9850         return rv;
   9851     }
   9852 
   9853     SOC_IF_ERROR_RETURN
   9854         (soc_profile_mem_add(unit, _bcm_th3_ifp_cos_map_profile[unit],
   9855                              entries, max_entries, &new_index));
   9856 
   9857     /* If we get (index == new_index / max_entries) means we have
   9858      * a successful mapping operation.
   9859      * But if they are not equal which means there already exists
   9860      * a similar mapping associated with other classifier_id hence
   9861      * we return BCM_E_EXISTS.
   9862      */
   9863 
   9864     if (index != (new_index / max_entries)) {
   9865         SOC_IF_ERROR_RETURN
   9866             (soc_profile_mem_delete(unit, _bcm_th3_ifp_cos_map_profile[unit],
   9867                                     new_index));
   9868         return BCM_E_EXISTS;
   9869     }
   9870 
   9871     return BCM_E_NONE;
   9872 }
   9873 
   9874 /*
   9875  * Function:
   9876  *      bcm_th3_cosq_field_classifier_map_get
   9877  * Purpose:
   9878  *      Get internal priority to ingress field processor CoS queue
   9879  *      override mapping information.
   9880  * Parameters:
   9881  *      unit           - (IN) Unit number.
   9882  *      classifier_id  - (IN) Classifier ID
   9883  *      array_max      - (IN) Size of priority_array and cosq_array
   9884  *      priority_array - (IN) Array of internal priorities
   9885  *      cosq_array     - (OUT) Array of COS queues
   9886  *      array_count    - (OUT) Size of cosq_array
   9887  * Returns:
   9888  *      BCM_E_xxx
   9889  * Notes:
   9890  *      Supported array_max = [0-16] and 48
   9891  *      When array_max = [0-16]
   9892  *          Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0]
   9893  *      When array_max = 48
   9894  *      Prio Array Index Map
   9895  *          Array Index [15-0] : Maps Prio[15-0] to UC cos[15-0]
   9896  *          Array Index [31-16] : Maps Prio[15-0] to MC cos[15-0]
   9897  *          Array Index [47-32] : Maps Prio[15-0] to RQE cos[15-0]
   9898  */
   9899 int
   9900 bcm_th3_cosq_field_classifier_map_get(
   9901     int unit,
   9902     int classifier_id,
   9903     int array_max,
   9904     bcm_cos_t *priority_array,
   9905     bcm_cos_queue_t *cosq_array,
   9906     int *array_count)
   9907 {
   9908     int rv;
   9909     int i;
   9910     int ent_per_set = _TH3_MMU_NUM_INT_PRI;
   9911     uint32 index;
   9912     void *entries[1];
   9913     ifp_cos_map_entry_t ent_buf[_TH3_MMU_NUM_INT_PRI];
   9914     soc_field_t field = -1;
   9915 
   9916     /* Input parameter check. */
   9917     if (NULL == priority_array || NULL == cosq_array || NULL == array_count) {
   9918         return BCM_E_PARAM;
   9919     }
   9920 
   9921     sal_memset(ent_buf, 0, sizeof(ifp_cos_map_entry_t) * ent_per_set);
   9922     entries[0] = ent_buf;
   9923 
   9924     /* Get profile table entry set base index. */
   9925     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
   9926 
   9927     /* Read out entries from profile table into allocated buffer. */
   9928     rv = soc_profile_mem_get(unit, _bcm_th3_ifp_cos_map_profile[unit],
   9929                              index * ent_per_set, ent_per_set, entries);
   9930     if (SOC_FAILURE(rv)) {
   9931         return rv;
   9932     }
   9933 
   9934     if (array_max <= ent_per_set) {
   9935         *array_count = array_max;
   9936     } else if ((array_max > ent_per_set) && (array_max < (ent_per_set * 3))) {
   9937         return BCM_E_PARAM;
   9938     } else {
   9939         *array_count = ent_per_set * 3;
   9940     }
   9941         /* Copy values into API OUT parameters. */
   9942     for (i = 0; i < *array_count; i++) {
   9943         if (priority_array[i % 16] >= _TH3_MMU_NUM_INT_PRI) {
   9944             return BCM_E_PARAM;
   9945         }
   9946         if (i < ent_per_set) {
   9947             field = IFP_UC_COSf;
   9948         } else if (i < (ent_per_set * 2)) {
   9949             field = IFP_MC_COSf;
   9950         } else {
   9951             field = IFP_RQE_Q_NUMf;
   9952         }
   9953         cosq_array[i] = soc_mem_field32_get(unit, IFP_COS_MAPm,
   9954                                             &ent_buf[priority_array[i]],
   9955                                             field);
   9956     }
   9957 
   9958     return BCM_E_NONE;
   9959 }
   9960 
   9961 /*
   9962  * Function:
   9963  *      bcm_th3_cosq_field_classifier_map_clear
   9964  * Purpose:
   9965  *      Delete an internal priority to ingress field processor CoS queue
   9966  *      override mapping profile set.
   9967  * Parameters:
   9968  *      unit          - (IN) Unit number.
   9969  *      classifier_id - (IN) Classifier ID
   9970  * Returns:
   9971  *      BCM_E_xxx
   9972  */
   9973 int
   9974 bcm_th3_cosq_field_classifier_map_clear(int unit, int classifier_id)
   9975 {
   9976     int ent_per_set = _TH3_MMU_NUM_INT_PRI;
   9977     uint32 index;
   9978 
   9979     /* Get profile table entry set base index. */
   9980     index = _BCM_COSQ_CLASSIFIER_FIELD_GET(classifier_id);
   9981 
   9982     /* Delete the profile entries set. */
   9983     SOC_IF_ERROR_RETURN
   9984         (soc_profile_mem_delete(unit,
   9985                                 _bcm_th3_ifp_cos_map_profile[unit],
   9986                                 index * ent_per_set));
   9987     return BCM_E_NONE;
   9988 }
   9989 
   9990 /*
   9991  * Function:
   9992  *      bcm_th3_cosq_field_classifier_id_destroy
   9993  * Purpose:
   9994  *      Free resource associated with this field classifier id.
   9995  * Parameters:
   9996  *      unit          - (IN) Unit number.
   9997  *      classifier_id - (IN) Classifier ID
   9998  * Returns:
   9999  *      BCM_E_xxx
  10000  */
  10001 int
  10002 bcm_th3_cosq_field_classifier_id_destroy(int unit, int classifier_id)
  10003 {
  10004     return BCM_E_NONE;
  10005 }
  10006 
  10007 /*
  10008  * Function:
  10009  *      _bcm_th3_cosq_field_reserved_classifier_get
  10010  * Purpose:
  10011  *      Get reserved field classifier id.
  10012  * Parameters:
  10013  *      unit          - (IN) Unit number.
  10014  *      classifier_id - (OUT) Classifier ID.
  10015  *      port          - (OUT) Port reserved.
  10016  * Returns:
  10017  *      BCM_E_xxx
  10018  */
  10019 int
  10020 _bcm_th3_cosq_field_reserved_classifier_get(int unit, int *classifier_id,
  10021                                             bcm_port_t *port)
  10022 {
  10023     _BCM_COSQ_CLASSIFIER_FIELD_SET(*classifier_id, _TH3_IFP_COS_MAP_RSVD_PROF);
  10024     *port = _TH3_MMU_SPARE_DST_PORT;
  10025     return BCM_E_NONE;
  10026 }
  10027 
  10028 /*
  10029  * Function:
  10030  *      bcm_th3_cosq_cpu_cosq_enable_set
  10031  * Purpose:
  10032  *      To enable/disable Rx of packets on the specified CPU cosq.
  10033  * Parameters:
  10034  *      unit          - (IN) Unit number.
  10035  *      cosq          - (IN) CPU Cosq ID
  10036  *      enable        - (IN) Enable/Disable
  10037  * Returns:
  10038  *      BCM_E_xxx
  10039  */
  10040 int
  10041 bcm_th3_cosq_cpu_cosq_enable_set(int unit, bcm_cos_queue_t cosq, int enable)
  10042 {
  10043     uint32 entry[SOC_MAX_MEM_WORDS];
  10044     int index, enable_status;
  10045     _bcm_th3_cosq_cpu_cosq_config_t *cpu_cosq_config;
  10046     soc_info_t *si;
  10047 
  10048     si = &SOC_INFO(unit);
  10049 
  10050     if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) {
  10051         return BCM_E_PARAM;
  10052     }
  10053 
  10054     cpu_cosq_config = _bcm_th3_cosq_cpu_cosq_config[unit][cosq];
  10055 
  10056     if (!cpu_cosq_config) {
  10057         return BCM_E_INTERNAL;
  10058     }
  10059     if (enable) {
  10060         enable = 1;
  10061     }
  10062 
  10063     BCM_IF_ERROR_RETURN(bcm_th3_cosq_cpu_cosq_enable_get(unit, cosq,
  10064                                                          &enable_status));
  10065     if (enable == enable_status) {
  10066         return BCM_E_NONE;
  10067     }
  10068 
  10069     index = si->port_cosq_base[CMIC_PORT(unit)] + cosq;
  10070 
  10071     /* To set DB and QE entries */
  10072     BCM_IF_ERROR_RETURN
  10073         (soc_mem_read(unit, MMU_THDO_QUEUE_CONFIGm, MEM_BLOCK_ALL, index, &entry));
  10074 
  10075     /* When enabled, restore the Min and Shared from the cached value */
  10076     if (!enable) {
  10077         cpu_cosq_config->q_min_limit = soc_mem_field32_get(unit,
  10078                                                        MMU_THDO_QUEUE_CONFIGm,
  10079                                                        &entry,
  10080                                                        MIN_LIMITf);
  10081         cpu_cosq_config->q_shared_limit = soc_mem_field32_get(unit,
  10082                                                           MMU_THDO_QUEUE_CONFIGm,
  10083                                                           &entry,
  10084                                                           SHARED_LIMITf);
  10085         cpu_cosq_config->q_limit_dynamic = soc_mem_field32_get(unit,
  10086                                                            MMU_THDO_QUEUE_CONFIGm,
  10087                                                            &entry,
  10088                                                            LIMIT_DYNAMICf);
  10089         cpu_cosq_config->q_limit_enable = soc_mem_field32_get(unit,
  10090                                                           MMU_THDO_QUEUE_CONFIGm,
  10091                                                           &entry,
  10092                                                           LIMIT_ENABLEf);
  10093         cpu_cosq_config->q_color_limit_enable = soc_mem_field32_get(unit,
  10094                                                           MMU_THDO_QUEUE_CONFIGm,
  10095                                                           &entry,
  10096                                                           COLOR_ENABLEf);
  10097     }
  10098     soc_mem_field32_set(unit, MMU_THDO_QUEUE_CONFIGm, &entry, LIMIT_DYNAMICf,
  10099                         enable ? cpu_cosq_config->q_limit_dynamic : 0);
  10100     soc_mem_field32_set(unit, MMU_THDO_QUEUE_CONFIGm, &entry, LIMIT_ENABLEf,
  10101                         enable ? cpu_cosq_config->q_limit_enable : 1);
  10102     soc_mem_field32_set(unit, MMU_THDO_QUEUE_CONFIGm, &entry, COLOR_ENABLEf,
  10103                         enable ? cpu_cosq_config->q_color_limit_enable : 1);
  10104     soc_mem_field32_set(unit, MMU_THDO_QUEUE_CONFIGm, &entry, MIN_LIMITf,
  10105                         enable ? cpu_cosq_config->q_min_limit : 0);
  10106     soc_mem_field32_set(unit, MMU_THDO_QUEUE_CONFIGm, &entry, SHARED_LIMITf,
  10107                         enable ? cpu_cosq_config->q_shared_limit : 0);
  10108     cpu_cosq_config->enable = enable;
  10109     BCM_IF_ERROR_RETURN(
  10110         soc_mem_write(unit, MMU_THDO_QUEUE_CONFIGm, MEM_BLOCK_ALL, index, &entry));
  10111 
  10112     return BCM_E_NONE;
  10113 }
  10114 
  10115 
  10116 /*
  10117  * Function:
  10118  *      bcm_th3_cosq_cpu_cosq_enable_get
  10119  * Purpose:
  10120  *      To get enable/disable status on Rx of packets on the specified CPU cosq.
  10121  * Parameters:
  10122  *      unit          - (IN) Unit number.
  10123  *      cosq          - (IN) CPU Cosq ID
  10124  *      enable        - (OUT) Enable/Disable
  10125  * Returns:
  10126  *      BCM_E_xxx
  10127  */
  10128 int
  10129 bcm_th3_cosq_cpu_cosq_enable_get(int unit, bcm_cos_queue_t cosq, int *enable)
  10130 {
  10131     _bcm_th3_cosq_cpu_cosq_config_t *cpu_cosq;
  10132     soc_info_t *si;
  10133     int index, hw_enable;
  10134     uint32 entry[SOC_MAX_MEM_WORDS];
  10135     soc_field_t min_limit, shared_limit, limit_enable, dynamic_enable;
  10136 
  10137     si = &SOC_INFO(unit);
  10138 
  10139     if ((cosq < 0) || (cosq >= NUM_CPU_COSQ(unit))) {
  10140         return BCM_E_PARAM;
  10141     }
  10142 
  10143     cpu_cosq = _bcm_th3_cosq_cpu_cosq_config[unit][cosq];
  10144     if (!cpu_cosq) {
  10145         return BCM_E_INTERNAL;
  10146     }
  10147 
  10148     index = si->port_cosq_base[CMIC_PORT(unit)] + cosq;
  10149     hw_enable = 1;
  10150 
  10151     /* Sync up software record with hardware status. */
  10152     BCM_IF_ERROR_RETURN(soc_mem_read(unit, MMU_THDO_QUEUE_CONFIGm, MEM_BLOCK_ALL,
  10153                                      index, &entry));
  10154     min_limit = soc_mem_field32_get(unit, MMU_THDO_QUEUE_CONFIGm, &entry,
  10155                                     MIN_LIMITf);
  10156     shared_limit = soc_mem_field32_get(unit, MMU_THDO_QUEUE_CONFIGm, &entry,
  10157                                     SHARED_LIMITf);
  10158     limit_enable = soc_mem_field32_get(unit, MMU_THDO_QUEUE_CONFIGm, &entry,
  10159                                     LIMIT_ENABLEf);
  10160     dynamic_enable = soc_mem_field32_get(unit, MMU_THDO_QUEUE_CONFIGm, &entry,
  10161                                     LIMIT_DYNAMICf);
  10162     if ((limit_enable != 0) && (dynamic_enable == 0) &&
  10163         (min_limit == 0) && (shared_limit == 0)) {
  10164         hw_enable = 0;
  10165     }
  10166     cpu_cosq->enable = hw_enable;
  10167 
  10168     *enable = cpu_cosq->enable;
  10169     return BCM_E_NONE;
  10170 }
  10171 
  10172 /*
  10173  * Function:
  10174  *      bcm_th3_cosq_buffer_id_multi_get
  10175  * Purpose:
  10176  *      Get mutliple buffer ids associated with a specified port.
  10177  * Parameters:
  10178  *      unit - (IN) BCM device number.
  10179  *      gport - (IN) Port
  10180  *      cosq - (IN) Reserved field
  10181  *      direction - (IN) Specify ingress or egress direction
  10182  *      array_max - (IN) number of entries to be retrieved
  10183  *      buf_id_array - (OUT) Buffer id array
  10184  *      array_count - (OUT) Actural buffer id count in buf_id_array
  10185  * Returns:
  10186  *      BCM_E_XXX
  10187  */
  10188 int
  10189 bcm_th3_cosq_buffer_id_multi_get(int unit, bcm_gport_t gport,
  10190                               bcm_cos_queue_t cosq, bcm_cosq_dir_t direction,
  10191                               int array_max, bcm_cosq_buffer_id_t *buf_id_array,
  10192                               int *array_count)
  10193 {
  10194     bcm_port_t local_port;
  10195     int pipe, i, idx;
  10196     int itm_map;
  10197     int itm;
  10198     int ibuf_arr[_TH3_ITMS_PER_DEV] = {0};
  10199     int ebuf_arr[_TH3_ITMS_PER_DEV] = {0};
  10200 
  10201     if ((direction < bcmCosqIngress) ||
  10202         (direction >= bcmCosqDirectionMaxCount)) {
  10203         return BCM_E_PARAM;
  10204     }
  10205 
  10206     if (buf_id_array == NULL) {
  10207         return BCM_E_PARAM;
  10208     }
  10209 
  10210     if (array_count == NULL) {
  10211         return BCM_E_PARAM;
  10212     }
  10213 
  10214     if (!BCM_GPORT_IS_SET(gport)) {
  10215         local_port = gport;
  10216     } else if (BCM_GPORT_IS_LOCAL(gport)) {
  10217         local_port = BCM_GPORT_LOCAL_GET(gport);
  10218     } else if (BCM_GPORT_IS_MODPORT(gport)) {
  10219         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, gport, &local_port));
  10220     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(gport)) {
  10221         BCM_IF_ERROR_RETURN(_bcm_th3_cosq_index_resolve(unit, gport, cosq,
  10222             _BCM_TH3_COSQ_INDEX_STYLE_UCAST_QUEUE, &local_port, &idx, NULL));
  10223     } else if (BCM_GPORT_IS_MCAST_QUEUE_GROUP(gport)) {
  10224         BCM_IF_ERROR_RETURN(_bcm_th3_cosq_index_resolve(unit, gport, cosq,
  10225             _BCM_TH3_COSQ_INDEX_STYLE_MCAST_QUEUE, &local_port, &idx, NULL));
  10226     } else {
  10227         return BCM_E_PARAM;
  10228     }
  10229 
  10230     if (!SOC_PORT_VALID(unit, local_port)) {
  10231         return BCM_E_PORT;
  10232     }
  10233 
  10234     SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, local_port, &pipe));
  10235 
  10236     if (array_max <= 0) {
  10237         return BCM_E_PARAM;
  10238     } else {
  10239         *array_count = (direction == bcmCosqIngress) ? 1 :
  10240                              MIN(array_max, NUM_ITM(unit));
  10241     }
  10242 
  10243     itm_map = SOC_INFO(unit).ipipe_itm_map[pipe];
  10244     idx = 0;
  10245     for (itm = 0; itm < NUM_ITM(unit); itm++) {
  10246         ebuf_arr[itm] = itm;
  10247         if (itm_map & (1 << itm)) {
  10248             ibuf_arr[idx] = itm;
  10249             idx++;
  10250         }
  10251     }
  10252 
  10253     for (i = 0; i < *array_count; i++) {
  10254         if (bcmCosqIngress == direction) {
  10255             buf_id_array[i] = ibuf_arr[i];
  10256         } else {
  10257             buf_id_array[i] = ebuf_arr[i];
  10258         }
  10259     }
  10260     for (i = *array_count; i < array_max; i++) {
  10261         buf_id_array[i] = BCM_COSQ_INVALID_BUF_ID;
  10262     }
  10263 
  10264     return BCM_E_NONE;
  10265 }
  10266 
  10267 int bcm_th3_cosq_burst_monitor_dma_config_reset(int unit)
  10268 {
  10269     uint32  qcm_app_status[2], qcm_host_status, qcm_uc_status, time_count;
  10270     uint32  *read_addr_ptr, read_addr;
  10271 
  10272     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  10273     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  10274 
  10275     /* Validation check whether core 0 R5 is loaded with CM app srec file
  10276      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  10277      */
  10278     if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) ||
  10279         (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) {
  10280         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  10281                   "load CM APP srec file to core 0\n")));
  10282         return BCM_E_UNAVAIL;
  10283     }
  10284 
  10285     qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)));
  10286     if (!(qcm_host_status & SHR_QCM_INIT_STATUS_BIT)) {
  10287         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  10288                   "shared memory not allocated yet\n")));
  10289         return BCM_E_INIT;
  10290     }
  10291     read_addr = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr)));
  10292     read_addr_ptr = (uint32 *)soc_cm_p2l(unit, read_addr);
  10293 
  10294     qcm_host_status = (qcm_host_status & (~SHR_QCM_INIT_STATUS_BIT));
  10295     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)), (uint32)qcm_host_status);
  10296 
  10297     time_count = 0;
  10298     while (1) {
  10299         qcm_uc_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(uc_status)));
  10300         qcm_uc_status = qcm_uc_status & SHR_QCM_INIT_STATUS_BIT;
  10301         if (!qcm_uc_status) {
  10302             break;
  10303         }
  10304         ++time_count;
  10305         if ((time_count * QCM_UC_STATUS_TIMEOUT) > QCM_UC_MSG_TIMEOUT) {
  10306             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  10307                       "CM APP R5 core 0 does not responded\n")));
  10308             return BCM_E_TIMEOUT;
  10309         }
  10310         sal_usleep(QCM_UC_STATUS_TIMEOUT);
  10311     }
  10312     soc_cm_sfree(unit, read_addr_ptr);
  10313 
  10314     return BCM_E_NONE;
  10315 }
  10316 
  10317 int bcm_th3_cosq_burst_monitor_dma_config_set(int unit,
  10318                                              uint32 host_mem_size,
  10319                                              uint32 **host_mem_add)
  10320 {
  10321     uint32 qcm_app_status[2], qcm_host_status, qcm_uc_status, shared_mem_size, share_mem_add, endianess;
  10322     int    time_count, rv;
  10323 
  10324     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  10325     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  10326 
  10327     /* Validation check whether core 0 R5 is loaded with QCM app srec file
  10328      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  10329      */
  10330     if ((qcm_app_status[0] != SHR_QCM_APP_STATUS_1) ||
  10331         (qcm_app_status[1] != SHR_QCM_APP_STATUS_2)) {
  10332         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  10333                   "load QCM app srec file to core 0\n")));
  10334         return BCM_E_UNAVAIL;
  10335     }
  10336 
  10337     qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)));
  10338     if (qcm_host_status & SHR_QCM_INIT_STATUS_BIT) {
  10339         if (host_mem_size == 0) {
  10340             rv = bcm_th3_cosq_burst_monitor_dma_config_reset(unit);
  10341             *host_mem_add = NULL;
  10342             soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr)), (uint32)0);
  10343             soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size)), (uint32)0);
  10344             return rv;
  10345         } else {
  10346             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  10347                       "already configured\n")));
  10348             return BCM_E_PARAM;
  10349         }
  10350     }
  10351 
  10352     qcm_host_status = qcm_host_status | SHR_QCM_INIT_STATUS_BIT;
  10353     shared_mem_size = (uint32)sizeof(struct bcm_cosq_burst_output_s);
  10354     shared_mem_size = host_mem_size - (host_mem_size % shared_mem_size);
  10355 
  10356     if (shared_mem_size < SHR_QCM_MEM_MIN_SIZE) {
  10357         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  10358                   "except's minimum shared memory size : %x\n"),
  10359                   SHR_QCM_MEM_MIN_SIZE));
  10360         return BCM_E_PARAM;
  10361     }
  10362 
  10363     /* Ensure QCM app host memory is not NULL */
  10364     *host_mem_add = (uint32 *) soc_cm_salloc(unit, host_mem_size, "Host buffer");
  10365     if (*host_mem_add == NULL) {
  10366         LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  10367                   "host memory address NULL\n")));
  10368         return BCM_E_PARAM;
  10369     }
  10370 
  10371     sal_memset(*host_mem_add, 0, host_mem_size);
  10372     share_mem_add = (uint32)soc_cm_l2p(unit, *host_mem_add);
  10373 
  10374     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_start_addr)), (uint32)share_mem_add);
  10375     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size)), (uint32)shared_mem_size);
  10376 
  10377 
  10378     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)), (uint32)qcm_host_status);
  10379 
  10380     time_count = 0;
  10381     while (1) {
  10382         qcm_uc_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(uc_status)));
  10383         qcm_uc_status = qcm_uc_status & SHR_QCM_INIT_STATUS_BIT;
  10384         if (qcm_host_status == qcm_uc_status) {
  10385             break;
  10386         }
  10387         ++time_count;
  10388         if ((time_count * QCM_UC_STATUS_TIMEOUT) > QCM_UC_MSG_TIMEOUT) {
  10389             LOG_ERROR(BSL_LS_BCM_COSQ, (BSL_META_U(unit,
  10390                       "QCM app R5 core 0 does not responded\n")));
  10391             return BCM_E_TIMEOUT;
  10392         }
  10393         sal_usleep(QCM_UC_STATUS_TIMEOUT);
  10394     }
  10395     if (*host_mem_add[0] == 0x1000000) {
  10396         endianess = 1;
  10397     } else {
  10398         endianess = 0;
  10399     }
  10400     soc_uc_mem_write(unit, (SRAM_BASEADDR(unit) + sram_offset(endianess)), (uint32)endianess);
  10401 
  10402     return BCM_E_NONE;
  10403 }
  10404 
  10405 #ifdef BCM_WARM_BOOT_SUPPORT
  10406 STATIC int
  10407 _bcm_th3_cosq_rx_queue_channel_reinit(int unit)
  10408 {
  10409     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
  10410     int idx;
  10411     /*
  10412     * L0.0 is associated with CMC0 CH1(Rx)
  10413     * L0.1 is associated with CMC0 CH2(Rx)
  10414     * L0.2 is associated with CMC0 CH3(Rx)
  10415     * L0.3 is associated with CMC0 CH4(Rx)
  10416     * L0.4 is associated with CMC0 CH5(Rx)
  10417     * L0.5 is associated with CMC0 CH6(Rx)
  10418     * L0.6 is associated with CMC0 CH7(Rx)
  10419     */
  10420     bcm_gport_t sched_gport[7];
  10421     bcm_cos_queue_t parent_cos;
  10422 
  10423     cpu_port_info = _bcm_th3_cosq_cpu_port_info[unit];
  10424     if (cpu_port_info == NULL) {
  10425         return BCM_E_INIT;
  10426     }
  10427 
  10428     for (idx = 0; idx < 7; idx++) {
  10429         sched_gport[idx] = cpu_port_info->sched[idx].gport;
  10430     }
  10431 
  10432     for (idx = 0; idx < _BCM_TH3_NUM_CPU_MCAST_QUEUE; idx++) {
  10433         parent_cos = -1;
  10434         if (cpu_port_info->mcast[idx].parent_gport == sched_gport[0]) {
  10435             parent_cos = 0;
  10436         } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[1]) {
  10437             parent_cos = 1;
  10438         } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[2]) {
  10439             parent_cos = 2;
  10440         } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[3]) {
  10441             parent_cos = 3;
  10442         } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[4]) {
  10443             parent_cos = 4;
  10444         } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[5]) {
  10445             parent_cos = 5;
  10446         } else if (cpu_port_info->mcast[idx].parent_gport == sched_gport[6]) {
  10447             parent_cos = 6;
  10448         }
  10449         if ((parent_cos >= 0) && (parent_cos < 7)) {
  10450             BCM_IF_ERROR_RETURN
  10451                 (_bcm_th3_cosq_rx_queue_channel_set(unit, parent_cos, idx, 1));
  10452         }
  10453     }
  10454     return BCM_E_NONE;
  10455 }
  10456 #endif /* BCM_WARM_BOOT_SUPPORT */
  10457 
  10458 
  10459 #ifdef BCM_WARM_BOOT_SUPPORT
  10460 int
  10461 bcm_th3_cosq_reinit(int unit)
  10462 {
  10463     soc_scache_handle_t scache_handle;
  10464     uint8 *scache_ptr = NULL;
  10465     int *int_scache_ptr = NULL;
  10466     uint16 *u16_scache_ptr = NULL;
  10467     uint32 *u32_scache_ptr = NULL;
  10468     _bcm_th3_mmu_info_t *mmu_info = NULL;
  10469     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
  10470     int alloc_size = 0, i, j, pipe = -1, itm;
  10471     soc_profile_mem_t *profile_mem;
  10472     soc_mem_t wred_config_mem = INVALIDm;
  10473     int index, profile_index, resolution_index;
  10474     int stable_size, rv, num, set_index;
  10475     mmu_wred_config_entry_t *qentry;
  10476     uint8 * mmu_wred_config_buf[8][2];
  10477     uint32 entry[SOC_MAX_MEM_WORDS];
  10478     bcm_port_t port;
  10479     _bcm_bst_device_handlers_t bst_callbks;
  10480     
  10481     _bcm_th3_cosq_cpu_cosq_config_t *cpu_cosq_config_p;
  10482     uint16 recovered_ver = 0;
  10483     int index_min, index_max;
  10484     int additional_scache_sz = 0;
  10485     int profile_idx, qidx;
  10486     uint32  qcm_app_status[2], host_mem_size;
  10487     uint32  *host_mem_add;
  10488     uint32 pipe_map;
  10489     int ii;
  10490     int itm_map;
  10491     uint16 dev_id;
  10492     uint8  rev_id;
  10493 
  10494     soc_cm_get_id(unit, &dev_id, &rev_id);
  10495     itm_map = SOC_INFO(unit).itm_map;
  10496 
  10497     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  10498     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
  10499         /* COSQ warmboot requires extended scache support i.e. level2 warmboot*/
  10500         return BCM_E_NONE;
  10501     }
  10502 
  10503     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
  10504     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, &scache_ptr,
  10505                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
  10506     if (BCM_FAILURE(rv)) {
  10507         return rv;
  10508     }
  10509 
  10510     mmu_info = _bcm_th3_mmu_info[unit];
  10511 
  10512     if (mmu_info == NULL) {
  10513         return BCM_E_INIT;
  10514     }
  10515 
  10516     cpu_port_info = _bcm_th3_cosq_cpu_port_info[unit];
  10517     if (cpu_port_info == NULL) {
  10518         return BCM_E_INIT;
  10519     }
  10520 
  10521     /* Update mmu_info shared limit parameters */
  10522     int_scache_ptr = (int *) scache_ptr;
  10523     /* shared limits are now recovered from hw */
  10524     int_scache_ptr += 1;
  10525     BCM_IF_ERROR_RETURN(
  10526         soc_th3_mmu_get_shared_size(unit,
  10527              mmu_info->shared_limit));
  10528 
  10529     alloc_size = sizeof(_bcm_th3_cosq_cpu_port_info_t);
  10530     scache_ptr = (uint8*) int_scache_ptr;
  10531     sal_memcpy(cpu_port_info, scache_ptr, alloc_size);
  10532 
  10533     /* Restore the Queue to Channel Mapping */
  10534     BCM_IF_ERROR_RETURN
  10535         (_bcm_th3_cosq_rx_queue_channel_reinit(unit));
  10536 
  10537     scache_ptr += alloc_size;
  10538 
  10539     /* Update IFP_COS_MAP memory profile reference counter */
  10540     profile_mem = _bcm_th3_ifp_cos_map_profile[unit];
  10541     num = SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TH3_MMU_NUM_INT_PRI - 1;
  10542     u16_scache_ptr = (uint16 *)scache_ptr;
  10543     for (i = 0; i < num; i++) {
  10544         for (j = 0; j < *u16_scache_ptr; j++) {
  10545             SOC_IF_ERROR_RETURN(
  10546                 soc_profile_mem_reference(unit, profile_mem,
  10547                                           i * _TH3_MMU_NUM_INT_PRI,
  10548                                           _TH3_MMU_NUM_INT_PRI));
  10549         }
  10550         u16_scache_ptr++;
  10551     }
  10552 
  10553     /* Recover CPU queue config information from scache */
  10554     cpu_cosq_config_p = _bcm_th3_cosq_cpu_cosq_config[unit][0];
  10555     if (cpu_cosq_config_p == NULL) {
  10556         return BCM_E_INIT;
  10557     }
  10558     alloc_size = (SOC_TH3_NUM_CPU_QUEUES *
  10559                    sizeof(_bcm_th3_cosq_cpu_cosq_config_t));
  10560     scache_ptr = (uint8*) u16_scache_ptr;
  10561     sal_memcpy(cpu_cosq_config_p, scache_ptr, alloc_size);
  10562     scache_ptr += alloc_size;
  10563 
  10564     /* Retriving num_cos value */
  10565     int_scache_ptr = (int *) scache_ptr;
  10566     _TH3_NUM_COS(unit) = *int_scache_ptr++;
  10567     scache_ptr = (uint8*) int_scache_ptr;
  10568 
  10569     /*
  10570      * Retriving th3_sched_profile_info struture for all scheduler profiles
  10571      * size = sizeof(soc_th3_sched_profile_info_t) * SOC_TH3_MAX_NUM_SCHED_PROFILE * SOC_TH3_NUM_GP_QUEUES;
  10572      */
  10573     int_scache_ptr = (int*) scache_ptr;
  10574     for (profile_idx = 0; profile_idx < SOC_TH3_MAX_NUM_SCHED_PROFILE; profile_idx++) {
  10575         for (qidx = 0; qidx < SOC_TH3_NUM_GP_QUEUES; qidx++) {
  10576             th3_sched_profile_info[unit][profile_idx][qidx].cos = *int_scache_ptr++;
  10577             th3_sched_profile_info[unit][profile_idx][qidx].mmuq[0] = *int_scache_ptr++;
  10578             th3_sched_profile_info[unit][profile_idx][qidx].mmuq[1] = *int_scache_ptr++;
  10579             th3_sched_profile_info[unit][profile_idx][qidx].strict_priority = *int_scache_ptr++;
  10580             th3_sched_profile_info[unit][profile_idx][qidx].fc_is_uc_only = *int_scache_ptr++;
  10581         }
  10582     }
  10583     scache_ptr = (uint8 *)int_scache_ptr;
  10584 
  10585     BCM_IF_ERROR_RETURN(_bcm_th3_cosq_scheduler_reinit(unit));
  10586 
  10587     /* PFC Deadlock recovery should be initialized
  10588        irrespective of scache version to handle
  10589        upgrades. */
  10590     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  10591         BCM_IF_ERROR_RETURN(_bcm_th3_pfc_deadlock_init(unit));
  10592         BCM_IF_ERROR_RETURN(_bcm_th3_pfc_deadlock_reinit(unit, &scache_ptr));
  10593         BCM_IF_ERROR_RETURN(_bcm_th3_pfc_deadlock_recovery_reset(unit));
  10594     }
  10595 
  10596     /* Update PRIO2COS_PROFILE register profile reference counter */
  10597     
  10598 
  10599     /* Update PORT_COS_MAP memory profile reference counter */
  10600     profile_mem = _bcm_th3_cos_map_profile[unit];
  10601     PBMP_ALL_ITER(unit, port) {
  10602         SOC_IF_ERROR_RETURN
  10603             (soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL, port, &entry));
  10604         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
  10605         SOC_IF_ERROR_RETURN
  10606             (soc_profile_mem_reference(unit, profile_mem, set_index * _TH3_MMU_NUM_INT_PRI,
  10607                        _TH3_MMU_NUM_INT_PRI));
  10608     }
  10609     if (SOC_INFO(unit).cpu_hg_index != -1) {
  10610         SOC_IF_ERROR_RETURN(soc_mem_read(unit, COS_MAP_SELm, MEM_BLOCK_ALL,
  10611                                          SOC_INFO(unit).cpu_hg_index, &entry));
  10612         set_index = soc_mem_field32_get(unit, COS_MAP_SELm, &entry, SELECTf);
  10613         SOC_IF_ERROR_RETURN
  10614             (soc_profile_mem_reference(unit, profile_mem, set_index * _TH3_MMU_NUM_INT_PRI,
  10615                               _TH3_MMU_NUM_INT_PRI));
  10616     }
  10617 
  10618     index_min = soc_mem_index_min(unit, MMU_WRED_QUEUE_CONFIGm);
  10619     index_max = soc_mem_index_max(unit, MMU_WRED_QUEUE_CONFIGm);
  10620     /* index_max = soc_mem_index_max(unit, SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit,
  10621                                                 MMU_WRED_QUEUE_CONFIGm, 0, 0));*/
  10622 
  10623     wred_config_mem = MMU_WRED_QUEUE_CONFIGm;
  10624 
  10625     soc_tomahawk3_pipe_map_get(unit, &pipe_map);
  10626     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  10627         if (!(pipe_map & (1 << pipe))) {
  10628             continue;
  10629         }
  10630         for (itm = 0; itm < SOC_MMU_CFG_ITM_MAX; itm++) {
  10631             if (!(itm_map & 1 << itm)) {
  10632                 continue;
  10633             }
  10634                 mmu_wred_config_buf[pipe][itm] = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit,
  10635                                                     wred_config_mem),
  10636                                                     "mmu_wred");
  10637                 BCM_IF_ERROR_RETURN
  10638                         (soc_tomahawk3_itm_mem_read_range(unit, wred_config_mem,
  10639                             itm, pipe, MEM_BLOCK_ALL, index_min, index_max, mmu_wred_config_buf[pipe][itm]));
  10640         }
  10641     }
  10642 
  10643     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  10644         for (itm = 0; itm < SOC_MMU_CFG_ITM_MAX; itm++) {
  10645             if (!(itm_map & 1 << itm)) {
  10646                 continue;
  10647             }
  10648             if (pipe_map & (1 << pipe)) {
  10649                 for (index = index_min; index < index_max; index++) {
  10650 
  10651                     qentry = soc_mem_table_idx_to_pointer(unit, wred_config_mem, mmu_wred_config_entry_t *,
  10652                             mmu_wred_config_buf[pipe][itm], index);
  10653 
  10654                     profile_index = soc_mem_field32_get(unit, wred_config_mem,
  10655                                                     qentry, PROFILE_INDEXf);
  10656                     rv = (soc_profile_mem_reference
  10657                         (unit, _bcm_th3_wred_profile[unit], profile_index, 1));
  10658 
  10659                     if (SOC_FAILURE(rv)) {
  10660                         goto cleanup;
  10661                     }
  10662 
  10663                     if (soc_mem_field32_get(unit, wred_config_mem, qentry,
  10664                         ECN_MARKING_ENf)) {
  10665                         resolution_index = soc_mem_field32_get(
  10666                             unit, wred_config_mem, qentry,
  10667                             WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_MARKING_INDEXf);
  10668                     } else {
  10669                         resolution_index = soc_mem_field32_get(
  10670                             unit, wred_config_mem, qentry,
  10671                             WRED_CONG_NOTIFICATION_RESOLUTION_TABLE_DROPPING_INDEXf);
  10672                     }
  10673                     _bcm_th3_wred_resolution_tbl[resolution_index] = 1;
  10674                 }
  10675             }
  10676         }
  10677     }
  10678 cleanup:
  10679     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  10680         if (!(pipe_map & (1 << pipe))) {
  10681             continue;
  10682         }
  10683         for (itm = 0; itm < SOC_MMU_CFG_ITM_MAX; itm++) {
  10684             if (!(itm_map & 1 << itm)) {
  10685                 continue;
  10686             }
  10687             if (mmu_wred_config_buf[pipe][itm]) {
  10688                 soc_cm_sfree(unit, mmu_wred_config_buf[pipe][itm]);
  10689                 mmu_wred_config_buf[pipe][itm] = NULL;
  10690             }
  10691         }
  10692     }
  10693     if (SOC_FAILURE(rv)) {
  10694         return rv;
  10695     }
  10696 
  10697     /* Create gport tree */
  10698     _BCM_TH3_MMU_INFO(unit)->gport_tree_created = FALSE;
  10699     PBMP_ALL_ITER(unit, port) {
  10700         if (IS_LB_PORT(unit, port) || IS_CPU_PORT(unit, port)) {
  10701             continue;
  10702         }
  10703         BCM_IF_ERROR_RETURN
  10704             (_bcm_th3_cosq_gport_tree_create(unit, port));
  10705     }
  10706 
  10707     _BCM_TH3_MMU_INFO(unit)->gport_tree_created = TRUE;
  10708 
  10709     /* BST reinit */
  10710 
  10711     sal_memset(&bst_callbks, 0, sizeof(_bcm_bst_device_handlers_t));
  10712     bst_callbks.resolve_index = &bcm_bst_th3_index_resolve;
  10713     bst_callbks.reverse_resolve_index = NULL;
  10714 
  10715     BCM_IF_ERROR_RETURN(_bcm_bst_attach(unit, &bst_callbks));
  10716 
  10717 #if defined(INCLUDE_PSTATS)
  10718     if (soc_feature(unit, soc_feature_pstats)) {
  10719         rv = _bcm_pstats_init(unit);
  10720         if (rv != BCM_E_NONE) {
  10721             if (cpu_cosq_config_p != NULL) {
  10722                 sal_free(cpu_cosq_config_p);
  10723                 cpu_cosq_config_p = NULL;
  10724             }
  10725             _bcm_th3_cosq_cleanup(unit);
  10726             return rv;
  10727         }
  10728     }
  10729 #endif /* INCLUDE_PSTATS */
  10730 
  10731     /* Recovery TIME_DOMAINr count reference */
  10732     for (ii = 0; ii <  _BCM_TH3_NUM_TIME_DOMAIN; ii++) {
  10733         alloc_size =  sizeof(uint32);
  10734         sal_memcpy(&th3_time_domain_info[unit][ii].ref_count, scache_ptr, alloc_size);
  10735         scache_ptr += alloc_size;
  10736     }
  10737 
  10738 #ifdef BCM_TOMAHAWK3_SUPPORT
  10739     if (soc_feature(unit, soc_feature_ecn_wred)) {
  10740         BCM_IF_ERROR_RETURN(bcmi_xgs5_ecn_reinit(unit, &scache_ptr));
  10741     }
  10742 #endif
  10743 
  10744 
  10745     /* Retriving _bcm_th3_wred_resolution_tbl value */
  10746     u32_scache_ptr = (uint32 *) scache_ptr;
  10747     for (i = 0; i < _BCM_TH3_NUM_WRED_RESOLUTION_TABLE; i++) {
  10748         _bcm_th3_wred_resolution_tbl[i] = *u32_scache_ptr++;
  10749     }
  10750 
  10751     /* realloc scache_handle resource*/
  10752     if (additional_scache_sz != 0) {
  10753         rv = soc_scache_realloc(unit, scache_handle, additional_scache_sz);
  10754         if (SOC_FAILURE(rv)) {
  10755             return rv;
  10756         }
  10757     }
  10758 
  10759     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  10760     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  10761 
  10762     /* Validation check whether core 0 R5 is loaded with QCM app srec file
  10763      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  10764      */
  10765     if ((qcm_app_status[0] == SHR_QCM_APP_STATUS_1) &&
  10766         (qcm_app_status[1] == SHR_QCM_APP_STATUS_2)) {
  10767         host_mem_size = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_buf_size)));
  10768         if (host_mem_size >= SHR_QCM_MEM_MIN_SIZE) {
  10769             bcm_th3_cosq_burst_monitor_dma_config_set(unit, host_mem_size, &host_mem_add);
  10770         }
  10771     }
  10772 
  10773     return BCM_E_NONE;
  10774 }
  10775 
  10776 int
  10777 bcm_th3_cosq_sync(int unit)
  10778 {
  10779     soc_scache_handle_t scache_handle;
  10780     uint8 *scache_ptr;
  10781     uint32 *u32_scache_ptr;
  10782     uint16 *u16_scache_ptr;
  10783     int *int_scache_ptr;
  10784     _bcm_th3_mmu_info_t *mmu_info = NULL;
  10785     _bcm_th3_cosq_cpu_port_info_t *cpu_port_info = NULL;
  10786     int size = 0, ii;
  10787     int shared_limit_min;
  10788     int itm_map;
  10789     int rv = BCM_E_NONE, ref_count, val = 0, pri, port;
  10790     _bcm_th3_cosq_cpu_cosq_config_t **cpu_cosq_config_p;
  10791     int profile_idx, qidx;
  10792     uint32  qcm_app_status[2], qcm_host_status;
  10793 
  10794     mmu_info = _bcm_th3_mmu_info[unit];
  10795     if (mmu_info == NULL) {
  10796         return BCM_E_INIT;
  10797     }
  10798 
  10799     cpu_port_info = _bcm_th3_cosq_cpu_port_info[unit];
  10800     if (cpu_port_info == NULL) {
  10801         return BCM_E_INIT;
  10802     }
  10803 
  10804     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
  10805     BCM_IF_ERROR_RETURN
  10806         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
  10807                                  &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL));
  10808 
  10809     /* Cache minimal ing_shared_limit/egr_db_shared_limit/egr_qe_shared_limit */
  10810     itm_map = SOC_INFO(unit).itm_map;
  10811     _TH3_ARRAY_MIN(_BCM_TH3_MMU_INFO(unit)->shared_limit, NUM_ITM(unit),
  10812                   itm_map, shared_limit_min);
  10813     u32_scache_ptr = (uint32*) scache_ptr;
  10814     *u32_scache_ptr++ = shared_limit_min;
  10815 
  10816     /* Cache _bcm_th3_cosq_cpu_port_info_t structure */
  10817     size = sizeof(_bcm_th3_cosq_cpu_port_info_t);
  10818     scache_ptr = (uint8*)u32_scache_ptr;
  10819     sal_memcpy(scache_ptr, cpu_port_info, size);
  10820     scache_ptr += size/sizeof(uint8);
  10821 
  10822     /* Cache _bcm_th3_ifp_cos_map_profile reference count */
  10823     u16_scache_ptr = (uint16 *)scache_ptr;
  10824     for (ii = 0;
  10825          ii < ((SOC_MEM_SIZE(unit, IFP_COS_MAPm) / _TH3_MMU_NUM_INT_PRI) - 1);
  10826          ii++) {
  10827         rv = soc_profile_mem_ref_count_get(unit,
  10828                                            _bcm_th3_ifp_cos_map_profile[unit],
  10829                                            ii * _TH3_MMU_NUM_INT_PRI,
  10830                                            &ref_count);
  10831         if (!(rv == SOC_E_NOT_FOUND || rv == SOC_E_NONE)) {
  10832             return rv;
  10833         }
  10834         *u16_scache_ptr++ = (uint16)(ref_count & 0xffff);
  10835     }
  10836 
  10837     /* Sync CPU Queue info */
  10838     cpu_cosq_config_p = _bcm_th3_cosq_cpu_cosq_config[unit];
  10839     size = (SOC_TH3_NUM_CPU_QUEUES * sizeof(_bcm_th3_cosq_cpu_cosq_config_t));
  10840     scache_ptr = (uint8*) u16_scache_ptr;
  10841     sal_memcpy(scache_ptr, *cpu_cosq_config_p, size);
  10842     scache_ptr += (size / sizeof(uint8));
  10843 
  10844     /* Sync num_cos value */
  10845     int_scache_ptr = (int*) scache_ptr;
  10846     *int_scache_ptr++ = _TH3_NUM_COS(unit);
  10847     scache_ptr = (uint8 *)int_scache_ptr;
  10848 
  10849     /*
  10850      * Sync th3_sched_profile_info struture for all scheduler profiles
  10851      * size = sizeof(soc_th3_sched_profile_info_t) * SOC_TH3_MAX_NUM_SCHED_PROFILE * SOC_TH3_NUM_GP_QUEUES;
  10852      */
  10853     int_scache_ptr = (int*) scache_ptr;
  10854     for (profile_idx = 0; profile_idx < SOC_TH3_MAX_NUM_SCHED_PROFILE; profile_idx++) {
  10855         for (qidx = 0; qidx < SOC_TH3_NUM_GP_QUEUES; qidx++) {
  10856             *int_scache_ptr++ = th3_sched_profile_info[unit][profile_idx][qidx].cos;
  10857             *int_scache_ptr++ = th3_sched_profile_info[unit][profile_idx][qidx].mmuq[0];
  10858             *int_scache_ptr++ = th3_sched_profile_info[unit][profile_idx][qidx].mmuq[1];
  10859             *int_scache_ptr++ = th3_sched_profile_info[unit][profile_idx][qidx].strict_priority;
  10860             *int_scache_ptr++ = th3_sched_profile_info[unit][profile_idx][qidx].fc_is_uc_only;
  10861         }
  10862     }
  10863     scache_ptr = (uint8 *)int_scache_ptr;
  10864 
  10865     /* Sync PFC deadlock recovery timer period. */
  10866     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  10867         u16_scache_ptr = (uint16 *)scache_ptr;
  10868         for (port = 0; port <  SOC_MAX_NUM_PORTS; port++) {
  10869             for (pri = 0; pri < TH3_PFC_PRIORITY_NUM; pri++) {
  10870                 if (bcm_tomahawk3_cosq_pfc_deadlock_control_get(unit,
  10871                                                       port, pri,
  10872                                                       bcmCosqPFCDeadlockRecoveryTimer,
  10873                                                       &val) == BCM_E_NONE) {
  10874                     *u16_scache_ptr++ = (uint16) val;
  10875                 } else {
  10876                     *u16_scache_ptr++ = 0;
  10877                 }
  10878             }
  10879         }
  10880     }
  10881     scache_ptr = (uint8*)u16_scache_ptr;
  10882     u32_scache_ptr = (uint32*) scache_ptr;
  10883 
  10884     if (soc_feature(unit, soc_feature_pfc_deadlock)) {
  10885         u32_scache_ptr = (uint32 *)scache_ptr;
  10886         for (port = 0; port <  SOC_MAX_NUM_PORTS; port++) {
  10887             for (pri = 0; pri < TH3_PFC_PRIORITY_NUM; pri++) {
  10888                  if (bcm_tomahawk3_cosq_pfc_deadlock_control_get(unit,
  10889                                             port, pri,
  10890                                             bcmCosqPFCDeadlockRecoveryOccurrences,
  10891                                             &val) == BCM_E_NONE) {
  10892                     *u32_scache_ptr++ = val;
  10893                 } else {
  10894                     *u32_scache_ptr++ = 0;
  10895                 }
  10896             }
  10897         }
  10898     }
  10899     scache_ptr = (uint8*)u32_scache_ptr;
  10900 
  10901     /* Sync TIME_DOMAINr field and count reference */
  10902     u32_scache_ptr = (uint32*) scache_ptr;
  10903     size = sizeof(uint32);
  10904     for (ii = 0; ii <  _BCM_TH3_NUM_TIME_DOMAIN; ii++) {
  10905         sal_memcpy(u32_scache_ptr, &th3_time_domain_info[unit][ii].ref_count, size);
  10906         u32_scache_ptr++;
  10907     }
  10908 
  10909     scache_ptr = (uint8*)u32_scache_ptr;
  10910 #ifdef BCM_TOMAHAWK3_SUPPORT
  10911     if (soc_feature(unit, soc_feature_ecn_wred)) {
  10912         BCM_IF_ERROR_RETURN(bcmi_xgs5_ecn_sync(unit, &scache_ptr));
  10913     }
  10914 #endif
  10915 
  10916     u32_scache_ptr = (uint32*) scache_ptr;
  10917     for (ii = 0; ii < _BCM_TH3_NUM_WRED_RESOLUTION_TABLE; ii++) {
  10918         *u32_scache_ptr++ = _bcm_th3_wred_resolution_tbl[ii];
  10919     }
  10920     scache_ptr = (uint8 *)u32_scache_ptr;
  10921 
  10922     qcm_app_status[0] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status)));
  10923     qcm_app_status[1] = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(app_status) + 4));
  10924 
  10925     /* Validation check whether core 0 R5 is loaded with QCM app srec file
  10926      * ASCII of word QCM_(SHR_QCM_APP_STATUS_1) and _APP(SHR_QCM_APP_STATUS_2)
  10927      */
  10928     if ((qcm_app_status[0] == SHR_QCM_APP_STATUS_1) &&
  10929         (qcm_app_status[1] == SHR_QCM_APP_STATUS_2)) {
  10930 
  10931         qcm_host_status = soc_uc_mem_read(unit, (SRAM_BASEADDR(unit) + sram_offset(host_status)));
  10932         if (qcm_host_status & SHR_QCM_INIT_STATUS_BIT) {
  10933             bcm_th3_cosq_burst_monitor_dma_config_reset(unit);
  10934         }
  10935     }
  10936 
  10937     return BCM_E_NONE;
  10938 }
  10939 
  10940 int
  10941 _bcm_th3_cosq_scheduler_reinit(int unit)
  10942 {
  10943     _soc_mmu_cfg_scheduler_profile_t *sched_profile;
  10944     int idx, cosq_idx,profile_idx;
  10945     int L0[_BCM_TH3_COS_MAX];
  10946     int schedq[_BCM_TH3_COS_MAX];
  10947     int mmuq[_BCM_TH3_COS_MAX];
  10948     int cos_list[_BCM_TH3_COS_MAX];
  10949     int strict_priority[_BCM_TH3_COS_MAX];
  10950     int fc_is_uc_only[_BCM_TH3_COS_MAX];
  10951     int rv = BCM_E_NONE;
  10952 
  10953     sched_profile = soc_mmu_cfg_scheduler_profile_alloc(unit);
  10954 
  10955     for (profile_idx = 0; profile_idx < _BCM_TH3_NUM_QSCHED_PROFILES; profile_idx++) {
  10956         cosq_idx = 0;
  10957         for (idx = 0; idx < _BCM_TH3_COS_MAX; idx++) {
  10958             sched_profile[profile_idx].num_unicast_queue[idx] = 0;
  10959             sched_profile[profile_idx].num_multicast_queue[idx] = 0;
  10960             sched_profile[profile_idx].strict_priority[idx] = 0;
  10961             sched_profile[profile_idx].flow_control_only_unicast[idx] = 0;
  10962         }
  10963         for (idx = 0; idx < _BCM_TH3_COS_MAX; idx++) {
  10964             if (th3_sched_profile_info[unit][profile_idx][idx].cos == -1) {
  10965                 continue;
  10966             }
  10967             if (th3_sched_profile_info[unit][profile_idx][idx].mmuq[0] != -1) {
  10968                 if (th3_sched_profile_info[unit][profile_idx][idx].mmuq[0] <
  10969                     _bcm_th3_get_num_ucq(unit)) {
  10970                     sched_profile[profile_idx].num_unicast_queue[cosq_idx]++;
  10971                 }
  10972                 else {
  10973                     sched_profile[profile_idx].num_multicast_queue[cosq_idx]++;
  10974                 }
  10975 
  10976             }
  10977             if (th3_sched_profile_info[unit][profile_idx][idx].mmuq[1] != -1) {
  10978                 if (th3_sched_profile_info[unit][profile_idx][idx].mmuq[1] <
  10979                     _bcm_th3_get_num_ucq(unit)) {
  10980                     sched_profile[profile_idx].num_unicast_queue[cosq_idx]++;
  10981                 }
  10982                 else {
  10983                     sched_profile[profile_idx].num_multicast_queue[cosq_idx]++;
  10984                 }
  10985 
  10986             }
  10987             sched_profile[profile_idx].strict_priority[cosq_idx] =
  10988                 th3_sched_profile_info[unit][profile_idx][idx].strict_priority;
  10989             sched_profile[profile_idx].flow_control_only_unicast[cosq_idx] =
  10990                 th3_sched_profile_info[unit][profile_idx][idx].fc_is_uc_only;
  10991             cosq_idx++;
  10992         }
  10993         rv = _soc_mmu_tomahawk3_scheduler_profile_config_check(unit,
  10994                         profile_idx, sched_profile);
  10995 
  10996         if (rv != BCM_E_NONE) {
  10997             goto exit;
  10998         }
  10999 
  11000         rv = _soc_scheduler_profile_mapping_setup(unit,
  11001                         sched_profile, profile_idx, L0, schedq, mmuq, cos_list,
  11002                         strict_priority, fc_is_uc_only);
  11003 
  11004         if (rv != BCM_E_NONE) {
  11005             goto exit;
  11006         }
  11007 
  11008         /*initilization of L0.i->schedq.i->mmuq.i*/
  11009         LOG_INFO(BSL_LS_BCM_COSQ,
  11010             (BSL_META_U(unit, "Profile %d cos %d L0 %d schedq %d mmuq %d cos_list %d\n"),
  11011              profile_idx, cosq_idx, L0[cosq_idx], schedq[cosq_idx], mmuq[cosq_idx], cos_list[cosq_idx]));
  11012         rv = soc_tomahawk3_sched_update_reinit(unit, profile_idx, L0, schedq, mmuq, cos_list, strict_priority, fc_is_uc_only);
  11013         if (rv != BCM_E_NONE) {
  11014             goto exit;
  11015         }
  11016 
  11017     }
  11018 
  11019 exit:
  11020     soc_mmu_cfg_scheduler_profile_free(unit, sched_profile);
  11021     return rv;;
  11022 }
  11023 
  11024 #endif /* BCM_WARM_BOOT_SUPPORT */
  11025 
  11026 
  11027 #endif /* BCM_TOMAHAWK3_SUPPORT */
  11028