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


      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 <sal/core/libc.h>
     12 #include <shared/bsl.h>
     13 #include <soc/defs.h>
     14 #if defined(BCM_TRIUMPH2_SUPPORT)
     15 #include <soc/drv.h>
     16 #include <soc/scache.h>
     17 #include <soc/profile_mem.h>
     18 
     19 #include <bcm/error.h>
     20 #include <bcm/cosq.h>
     21 
     22 #include <bcm_int/esw/cosq.h>
     23 #include <bcm_int/esw/mbcm.h>
     24 #include <bcm_int/esw/firebolt.h>
     25 #include <bcm_int/esw/triumph2.h>
     26 #include <bcm_int/esw/stack.h>
     27 
     28 #include <bcm_int/esw_dispatch.h>
     29 
     30 #ifdef BCM_WARM_BOOT_SUPPORT
     31 #include <bcm_int/esw/switch.h>
     32 #endif /* BCM_WARM_BOOT_SUPPORT */
     33 
     34 #define TR2_DRR_WEIGHT_MAX       0x7f
     35 #define TR2_WRR_WEIGHT_MAX       0x7f
     36 
     37 #define TR2_PACKET_FIELD_MAX     0x3fff
     38 #define TR2_CELL_FIELD_MAX       0x7fff
     39 
     40 #define TR2_PKT_REFRESH_MAX      0xfffff
     41 #define TR2_PKT_THD_MAX          0x7ff
     42 
     43 /* COSQ where output of hierarchical COSQs scheduler is attached */
     44 #define TR2_SCHEDULER_COSQ       8
     45 
     46 /* MMU cell size in bytes */
     47 #define _BCM_TR2_COSQ_CELLSIZE   128
     48 
     49 /* Number of ports */
     50 #define TR2_PORT_COUNT           52
     51 
     52 /* COS Map profile entries per set */
     53 #define TR2_COS_MAP_ENTRIES_PER_SET    16
     54 
     55 /* Cache of COS_MAP Profile Table */
     56 STATIC soc_profile_mem_t *_tr2_cos_map_profile[BCM_MAX_NUM_UNITS] = {NULL};
     57 /* Cache of COS_EGR_MAP Profile Table */
     58 STATIC soc_profile_mem_t *_tr2_cos_egr_map_profile[BCM_MAX_NUM_UNITS] = {NULL};
     59 
     60 /* Number of COSQs configured for this device */
     61 STATIC int _tr2_num_cosq[SOC_MAX_NUM_DEVICES];
     62 
     63 /* Port Bitmap which includes ports capable of hierarchical queueing */
     64 STATIC soc_pbmp_t _tr2_cosq_24q_ports[SOC_MAX_NUM_DEVICES];
     65 
     66 /* Array to keep track of the number of hierarchical COSQs added per port */
     67 STATIC uint8 *_tr2_num_port_cosq[SOC_MAX_NUM_DEVICES] = {NULL};
     68 
     69 /* Forward declarations */
     70 STATIC int _bcm_tr2_cosq_gport_delete(int unit, bcm_port_t port);
     71 STATIC int _bcm_tr2_cosq_port_sched_set(int unit, soc_reg_t config_reg, 
     72                                        soc_reg_t weight_reg, soc_reg_t minsp_reg,
     73                                        bcm_port_t port, bcm_cos_queue_t start_cosq,
     74                                        int num_weights, const int weights[], 
     75                                        int mode);
     76 STATIC int _bcm_tr2_cosq_discard_set(int unit, bcm_port_t port, uint32 flags,
     77                                     bcm_cos_queue_t cosq, soc_reg_t config_reg,
     78                                     soc_reg_t thresh_reg_green,
     79                                     soc_reg_t thresh_reg_yellow,
     80                                     soc_reg_t thresh_reg_red,
     81                                     soc_reg_t thresh_reg_non_tcp,
     82                                     uint32 min_thresh, uint32 max_thresh,
     83                                     int drop_probability, int gain);
     84 
     85 
     86 /*
     87  * Function:
     88  *      _bcm_tr2_egr_cpu_cos_map
     89  * Purpose:
     90  *      Set the initial one to one mapping for he EGR_CPU_COS_MAP table
     91  * Parameters:
     92  *      unit - Unit number.
     93  *      numq - Number of cosq provided
     94  * Returns:
     95  *      BCM_E_XXX
     96  */
     97 STATIC int 
     98 _bcm_tr2_egr_cpu_cos_map(int unit, int numq)
     99 {
    100     int i, imin, imax, bytes, nent, rv;
    101     egr_cpu_cos_map_entry_t *entblk, *entryp;
    102     int cos, ratio, remain;
    103     
    104     imin = soc_mem_index_min(unit, EGR_CPU_COS_MAPm);
    105     imax = soc_mem_index_max(unit, EGR_CPU_COS_MAPm);
    106     nent = soc_mem_index_count(unit, EGR_CPU_COS_MAPm);
    107     bytes = soc_mem_entry_words(unit, EGR_CPU_COS_MAPm);
    108     bytes = WORDS2BYTES(bytes);
    109     entblk = soc_cm_salloc(unit, nent * sizeof(egr_cpu_cos_map_entry_t), 
    110                           "EGR_CPU_COS_MAP");
    111     if (entblk == NULL) {
    112         return BCM_E_MEMORY;
    113     }
    114 
    115     soc_mem_lock(unit, EGR_CPU_COS_MAPm);
    116     rv = soc_mem_read_range(unit, EGR_CPU_COS_MAPm, MEM_BLOCK_ANY,
    117                             imin, imax, entblk);
    118     if (BCM_FAILURE(rv)) {
    119         soc_mem_unlock(unit, EGR_CPU_COS_MAPm);
    120         soc_cm_sfree(unit, entblk);
    121         return rv;
    122     }
    123     
    124     ratio = nent / numq;
    125     remain = nent % numq;
    126     
    127     cos = 0;
    128     for(i = 0; i < nent; i++) {
    129         entryp = soc_mem_table_idx_to_pointer(unit, EGR_CPU_COS_MAPm,
    130                         egr_cpu_cos_map_entry_t *, entblk, i);
    131 
    132         soc_mem_field32_set(unit, EGR_CPU_COS_MAPm, (uint32 *) entryp,
    133                             REDIRECT_COSf, cos);
    134 
    135         if ((i + 1) == (((cos + 1) * ratio) + 
    136                         ((remain < (numq - cos)) ? 0 :
    137                          (remain - (numq - cos) + 1)))) {
    138             cos++;
    139         }
    140 
    141     }
    142 
    143     rv = soc_mem_write_range(unit, EGR_CPU_COS_MAPm, MEM_BLOCK_ALL, 
    144                              imin, imax, entblk);
    145     soc_mem_unlock(unit, EGR_CPU_COS_MAPm);
    146     soc_cm_sfree(unit, entblk);
    147 
    148     return rv;
    149 }
    150 
    151 #ifdef BCM_WARM_BOOT_SUPPORT
    152 
    153 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    154 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
    155 
    156 /*
    157  * Function:
    158  *      bcm_tr2_cosq_sync
    159  * Purpose:
    160  *      Record COSQ module persistent info for Level 2 Warm Boot.
    161  * Parameters:
    162  *      unit - Unit number.
    163  * Returns:
    164  *      BCM_E_XXX
    165  */
    166 int
    167 bcm_tr2_cosq_sync(int unit)
    168 {
    169     soc_scache_handle_t scache_handle;
    170     uint8               *cosq_scache_ptr;
    171     uint32              num_cosq;
    172 
    173     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    174     BCM_IF_ERROR_RETURN
    175         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    176                                  0, &cosq_scache_ptr, 
    177                                  BCM_WB_DEFAULT_VERSION, NULL));
    178     
    179     /* Number COSQ */
    180     num_cosq = _tr2_num_cosq[unit];
    181     sal_memcpy(cosq_scache_ptr, &num_cosq, sizeof(num_cosq));
    182     cosq_scache_ptr += sizeof(num_cosq);
    183         
    184     /* Number of hierarchical COSQs added per port */
    185     if (_tr2_num_port_cosq[unit] != NULL) {
    186         sal_memcpy(cosq_scache_ptr, _tr2_num_port_cosq[unit],
    187                    sizeof(uint8) * TR2_PORT_COUNT);
    188     }
    189 
    190     return BCM_E_NONE;
    191 }
    192 
    193 /*
    194  * Function:
    195  *      _bcm_tr2_cosq_reinit
    196  * Purpose:
    197  *      Recover COSQ software state.
    198  * Parameters:
    199  *      unit - Unit number.
    200  * Returns:
    201  *      BCM_E_XXX
    202  */
    203 STATIC int
    204 _bcm_tr2_cosq_reinit(int unit)
    205 {
    206     int                 rv;
    207     soc_scache_handle_t scache_handle;
    208     uint8               *cosq_scache_ptr;
    209     uint32              num_cosq;
    210  	 
    211     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    212     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    213                                  0, &cosq_scache_ptr, 
    214                                  BCM_WB_DEFAULT_VERSION, NULL);
    215 
    216     if (rv == BCM_E_NOT_FOUND) {
    217         cosq_scache_ptr = NULL;
    218     } else if (BCM_FAILURE(rv)) {
    219         return rv;
    220     }
    221 
    222     if (cosq_scache_ptr != NULL) {
    223         /* Number COSQ */
    224         sal_memcpy(&num_cosq, cosq_scache_ptr, sizeof(num_cosq));
    225         _tr2_num_cosq[unit] = num_cosq;
    226         cosq_scache_ptr += sizeof(num_cosq);
    227 
    228         /* Number of hierarchical COSQs added per port */
    229         if (_tr2_num_port_cosq[unit] != NULL) {
    230             sal_memcpy(_tr2_num_port_cosq[unit], cosq_scache_ptr,
    231                        sizeof(uint8) * TR2_PORT_COUNT);
    232         }
    233 
    234     } else {
    235         _tr2_num_cosq[unit] = _bcm_esw_cosq_config_property_get(unit);
    236     }
    237     
    238     return BCM_E_NONE;
    239 }
    240 #endif /* BCM_WARM_BOOT_SUPPORT */
    241 
    242 /*
    243  * Function:
    244  *      bcm_cosq_init
    245  * Purpose:
    246  *      Initialize (clear) all COS schedule/mapping state.
    247  * Parameters:
    248  *      unit - StrataSwitch unit number.
    249  * Returns:
    250  *      BCM_E_XXX
    251  */
    252 
    253 int
    254 bcm_tr2_cosq_init(int unit)
    255 {
    256     STATIC int _tr2_max_cosq = -1;
    257     int num_cos;
    258 #ifdef BCM_WARM_BOOT_SUPPORT
    259     int                 rv;
    260     soc_scache_handle_t scache_handle;
    261     uint32              cosq_scache_size;
    262     uint8               *cosq_scache_ptr;
    263 #endif /* BCM_WARM_BOOT_SUPPORT */
    264 
    265     if (_tr2_max_cosq < 0) {
    266         _tr2_max_cosq = NUM_COS(unit);
    267         NUM_COS(unit) = 8;
    268     }
    269 
    270     if (!SOC_WARM_BOOT(unit)) {    /* Cold Boot */
    271         BCM_IF_ERROR_RETURN (bcm_tr2_cosq_detach(unit, 0));
    272     }
    273 
    274     num_cos = _bcm_esw_cosq_config_property_get(unit);
    275 
    276     SOC_PBMP_CLEAR(_tr2_cosq_24q_ports[unit]);
    277     /* Keep track of ports that support 24 (16 + 8) queues */
    278     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 26);
    279     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 27);
    280     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 28);
    281     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 29);
    282     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 30);
    283     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 31);
    284     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 34);
    285     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 38);
    286     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 39);
    287     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 42);
    288     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 43);
    289     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 46);
    290     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 50);
    291     SOC_PBMP_PORT_ADD(_tr2_cosq_24q_ports[unit], 51);
    292     if (_tr2_num_port_cosq[unit] == NULL) {
    293         _tr2_num_port_cosq[unit] = sal_alloc(sizeof(uint8) * TR2_PORT_COUNT,
    294                                      "_tr2_num_port_cosq");
    295         if (_tr2_num_port_cosq[unit] == NULL) {
    296                 return BCM_E_MEMORY;
    297         }
    298     }
    299     sal_memset(_tr2_num_port_cosq[unit], 0, sizeof(uint8) * TR2_PORT_COUNT);
    300 
    301 #ifdef BCM_WARM_BOOT_SUPPORT
    302     /* Warm boot level 2 cache size */
    303     cosq_scache_size = sizeof(uint32); /* Number COSQ */
    304     if (_tr2_num_port_cosq[unit] != NULL) {  /* Number of COSQs per port */
    305         cosq_scache_size += (sizeof(uint8) * TR2_PORT_COUNT);
    306     }
    307 
    308     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    309     rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
    310                                  (0 == SOC_WARM_BOOT(unit)),
    311                                  cosq_scache_size, &cosq_scache_ptr, 
    312                                  BCM_WB_DEFAULT_VERSION, NULL);
    313     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    314         return rv;
    315     }
    316 
    317     if (SOC_WARM_BOOT(unit)) {
    318         BCM_IF_ERROR_RETURN(_bcm_tr2_cosq_reinit(unit));
    319         num_cos = _tr2_num_cosq[unit];
    320     }
    321 #endif /* BCM_WARM_BOOT_SUPPORT */
    322 
    323     return bcm_tr2_cosq_config_set(unit, num_cos);
    324 }
    325 
    326 /*
    327  * Function:
    328  *      bcm_cosq_detach
    329  * Purpose:
    330  *      Discard all COS schedule/mapping state.
    331  * Parameters:
    332  *      unit - StrataSwitch unit number.
    333  * Returns:
    334  *      BCM_E_XXX
    335  */
    336 
    337 int
    338 bcm_tr2_cosq_detach(int unit, int software_state_only)
    339 {
    340     bcm_port_t port;
    341     int weights[8];
    342     int cosq;
    343 
    344     /* Delete any gports that were added */
    345     if (_tr2_num_port_cosq[unit]) {
    346         BCM_PBMP_ITER(_tr2_cosq_24q_ports[unit], port) {
    347             if (_tr2_num_port_cosq[unit][port])
    348             {
    349                 if (!software_state_only)
    350                 {
    351                     BCM_IF_ERROR_RETURN
    352                         (_bcm_tr2_cosq_gport_delete(unit, port));
    353                 }
    354             }
    355         } 
    356 
    357         /* Destroy profile table cache */
    358         BCM_IF_ERROR_RETURN
    359             (soc_profile_mem_destroy(unit, _tr2_cos_map_profile[unit]));
    360         sal_free(_tr2_cos_map_profile[unit]);
    361         _tr2_cos_map_profile[unit] = NULL;
    362 
    363         sal_free(_tr2_num_port_cosq[unit]);
    364         _tr2_num_port_cosq[unit] = NULL;
    365     }
    366 
    367     for (cosq = 0; cosq < 8; cosq++) {
    368         weights[cosq] = 0;
    369     }
    370 
    371     if (!software_state_only)
    372     {
    373         PBMP_ALL_ITER(unit, port) {
    374             if (IS_CPU_PORT(unit, port)) {
    375                 continue;
    376             }
    377 
    378             /* Clear bandwidth settings on port */
    379             for (cosq = 0; cosq < 8; cosq++) {
    380                  BCM_IF_ERROR_RETURN
    381                     (bcm_tr2_cosq_port_bandwidth_set(unit, port, cosq,
    382                                                      0, 0, 0, 0));
    383             }
    384 
    385             /* Clear scheduling settings on port */
    386             BCM_IF_ERROR_RETURN
    387                 (_bcm_tr2_cosq_port_sched_set(unit,
    388                                              ESCONFIGr, COSWEIGHTSr, MINSPCONFIGr,
    389                                              port, 0, 8, weights, 
    390                                              BCM_COSQ_WEIGHTED_ROUND_ROBIN));
    391             /* Clear discard settings on port */
    392      
    393             for (cosq = 0; cosq < 8; cosq++) {
    394                  BCM_IF_ERROR_RETURN
    395                     (_bcm_tr2_cosq_discard_set(unit, port, 
    396                                           BCM_COSQ_DISCARD_COLOR_ALL | 
    397                                           BCM_COSQ_DISCARD_NONTCP, cosq,
    398                                           WREDCONFIG_PACKETr,
    399                                           WREDPARAM_PACKETr,
    400                                           WREDPARAM_YELLOW_PACKETr,
    401                                           WREDPARAM_RED_PACKETr,
    402                                           WREDPARAM_NONTCP_PACKETr,
    403                                           TR2_PACKET_FIELD_MAX, 
    404                                           TR2_PACKET_FIELD_MAX, 100, 0));
    405             }
    406         }
    407 
    408         /* Disable WRED on all cosq level */
    409         BCM_IF_ERROR_RETURN (bcm_tr2_cosq_discard_set(unit, 0));
    410     }
    411 
    412 
    413     return BCM_E_NONE;
    414 }
    415 
    416 /*
    417  * Function:
    418  *      bcm_cosq_config_set
    419  * Purpose:
    420  *      Set the number of COS queues
    421  * Parameters:
    422  *      unit - Unit number.
    423  *      numq - number of COS queues (1-8).
    424  * Returns:
    425  *      BCM_E_XXX
    426  */
    427 
    428 int
    429 bcm_tr2_cosq_config_set(int unit, int numq)
    430 {
    431     int cos, prio, ratio, remain;
    432     uint32 index, egr_index, minsp;
    433     soc_mem_t mem = PORT_COS_MAPm; 
    434     soc_mem_t egr_mem = EGR_COS_MAPm;
    435     int entry_words;
    436     bcm_pbmp_t ports;
    437     bcm_port_t port;
    438     port_cos_map_entry_t cos_map_array[TR2_COS_MAP_ENTRIES_PER_SET];
    439     egr_cos_map_entry_t  egr_cos_map_array[TR2_COS_MAP_ENTRIES_PER_SET];
    440     void *entries[1], *egr_entries[1];
    441 
    442     /* Validate cosq num */
    443     if (numq < 1) {
    444         return BCM_E_PARAM;
    445     }
    446 
    447     /* Map the eight 802.1 priority levels to the active cosqs */
    448     if (numq > 8) {
    449         numq = 8;
    450     }
    451 
    452     sal_memset(cos_map_array, 0, 
    453                COUNTOF(cos_map_array) * sizeof(port_cos_map_entry_t));
    454     entries[0] = &cos_map_array;
    455     if (_tr2_cos_map_profile[unit] == NULL) {
    456         _tr2_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
    457                                           "COS_MAP Profile Mem");
    458         if (_tr2_cos_map_profile[unit] == NULL) {
    459             return BCM_E_MEMORY;
    460         }
    461         soc_profile_mem_t_init(_tr2_cos_map_profile[unit]);
    462     }
    463     /* Create profile table cache (or re-init if it already exists) */
    464     entry_words = sizeof(port_cos_map_entry_t)/ sizeof(uint32);
    465     SOC_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, &entry_words, 1,
    466                                                _tr2_cos_map_profile[unit]));
    467 
    468     sal_memset(egr_cos_map_array, 0, 
    469                COUNTOF(egr_cos_map_array) * sizeof(egr_cos_map_entry_t));
    470     egr_entries[0] = &egr_cos_map_array;
    471     if (_tr2_cos_egr_map_profile[unit] == NULL) {
    472         _tr2_cos_egr_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
    473                                           "EGR COS_MAP Profile Mem");
    474         if (_tr2_cos_egr_map_profile[unit] == NULL) {
    475             return BCM_E_MEMORY;
    476         }
    477         soc_profile_mem_t_init(_tr2_cos_egr_map_profile[unit]);
    478     }
    479     /* Create profile table cache (or re-init if it already exists) */
    480     entry_words = sizeof(egr_cos_map_entry_t)/ sizeof(uint32);
    481     SOC_IF_ERROR_RETURN(soc_profile_mem_create(unit, &egr_mem, &entry_words, 1,
    482                                                _tr2_cos_egr_map_profile[unit]));
    483 
    484     if (SOC_WARM_BOOT(unit)) {    /* Warm Boot */
    485         int     i;
    486         uint32  val;
    487         uint64  val64;
    488 
    489         /* Gather reference count for cosq map profile tables */
    490         BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
    491         PBMP_ITER(ports, port) {
    492             SOC_IF_ERROR_RETURN(READ_COS_MAP_SELr(unit, port, &val));
    493             index = soc_reg_field_get(unit, COS_MAP_SELr, val, SELECTf);
    494             index *= TR2_COS_MAP_ENTRIES_PER_SET;
    495             for (i = 0; i < TR2_COS_MAP_ENTRIES_PER_SET; i++) {
    496                 SOC_PROFILE_MEM_REFERENCE
    497                     (unit, _tr2_cos_map_profile[unit],
    498                      index + i, 1);
    499                 SOC_PROFILE_MEM_ENTRIES_PER_SET
    500                     (unit, _tr2_cos_map_profile[unit],
    501                      index + i, TR2_COS_MAP_ENTRIES_PER_SET);
    502             }
    503 
    504             if (soc_mem_field_valid(unit, EGR_COS_MAPm, REDIRECT_COSf)) {
    505                 SOC_IF_ERROR_RETURN
    506                     (READ_EGR_PORT_64r(unit, port, &val64));
    507                 index = soc_reg64_field32_get(unit, EGR_PORT_64r, val64,
    508                                               EGR_COS_MAP_SELf);
    509                 index *= TR2_COS_MAP_ENTRIES_PER_SET;
    510                 for (i = 0; i < TR2_COS_MAP_ENTRIES_PER_SET; i++) {
    511                     SOC_PROFILE_MEM_REFERENCE
    512                         (unit, _tr2_cos_egr_map_profile[unit],
    513                          index + i, 1);
    514                     SOC_PROFILE_MEM_ENTRIES_PER_SET
    515                         (unit, _tr2_cos_egr_map_profile[unit],
    516                          index + i, TR2_COS_MAP_ENTRIES_PER_SET);
    517                 }
    518             }
    519 
    520 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
    521             if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
    522                 SOC_IF_ERROR_RETURN(READ_ICOS_MAP_SELr(unit, port, &val));
    523                 index = soc_reg_field_get(unit, ICOS_MAP_SELr, val, SELECTf);
    524                 index *= TR2_COS_MAP_ENTRIES_PER_SET;
    525                 for (i = 0; i < TR2_COS_MAP_ENTRIES_PER_SET; i++) {
    526                     SOC_PROFILE_MEM_REFERENCE
    527                         (unit, _tr2_cos_map_profile[unit],
    528                          index + i, 1);
    529                     SOC_PROFILE_MEM_ENTRIES_PER_SET
    530                         (unit, _tr2_cos_map_profile[unit],
    531                          index + i, TR2_COS_MAP_ENTRIES_PER_SET);
    532                 }
    533 
    534                 if (soc_mem_field_valid(unit, EGR_COS_MAPm, REDIRECT_COSf)) {
    535                     SOC_IF_ERROR_RETURN
    536                         (READ_IEGR_PORT_64r(unit, port, &val64));
    537                     index = soc_reg64_field32_get(unit, IEGR_PORT_64r, val64,
    538                                                   EGR_COS_MAP_SELf);
    539                     index *= TR2_COS_MAP_ENTRIES_PER_SET;
    540                     for (i = 0; i < TR2_COS_MAP_ENTRIES_PER_SET; i++) {
    541                         SOC_PROFILE_MEM_REFERENCE
    542                             (unit, _tr2_cos_egr_map_profile[unit],
    543                              index + i, 1);
    544                         SOC_PROFILE_MEM_ENTRIES_PER_SET
    545                             (unit, _tr2_cos_egr_map_profile[unit],
    546                              index + i, TR2_COS_MAP_ENTRIES_PER_SET);
    547                     }
    548                 }
    549             }
    550 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
    551         }
    552 
    553         _tr2_num_cosq[unit] = numq;
    554 
    555         return BCM_E_NONE;
    556     }
    557 
    558     ratio = 8 / numq;
    559     remain = 8 % numq;
    560     cos = 0;
    561     for (prio = 0; prio < 8; prio++) {
    562         soc_mem_field32_set(unit, PORT_COS_MAPm,
    563                             &cos_map_array[prio], COSf, cos);
    564         if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
    565             soc_mem_field32_set(unit, PORT_COS_MAPm,
    566                                 &cos_map_array[prio], HG_COSf, 0);
    567         }
    568         if ((prio + 1) == (((cos + 1) * ratio) +
    569                            ((remain < (numq - cos)) ? 0 :
    570                             (remain - (numq - cos) + 1)))) {
    571             cos++;
    572         }
    573     }
    574 
    575     /* Map remaining internal priority levels to highest priority cosq */
    576     cos = numq - 1;
    577     for (prio = 8; prio < 16; prio++) {
    578         soc_mem_field32_set(unit, PORT_COS_MAPm,
    579                             &cos_map_array[prio], COSf, cos);
    580         if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
    581             soc_mem_field32_set(unit, PORT_COS_MAPm,
    582                             &cos_map_array[prio], HG_COSf, 0);
    583         }
    584     }
    585 
    586     /* Map internal priority levels to CPU CoS queues */
    587     BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq));
    588 
    589     /* Map egress priority */
    590     if (soc_mem_field_valid(unit, EGR_COS_MAPm, REDIRECT_COSf)) {
    591         ratio = 16 / numq;
    592         remain = 16 % numq;
    593         cos = 0;
    594         for (prio = 0; prio < 16; prio++) {
    595             soc_mem_field32_set(unit, EGR_COS_MAPm,
    596                                 &egr_cos_map_array[prio], REDIRECT_COSf, cos);
    597             if ((prio + 1) == (((cos + 1) * ratio) +
    598                                ((remain < (numq - cos)) ? 0 :
    599                                 (remain - (numq - cos) + 1)))) {
    600                 cos++;
    601             }
    602         }
    603         /* Map egress priority */
    604         if (soc_mem_field_valid(unit, EGR_CPU_COS_MAPm, REDIRECT_COSf)) {
    605             BCM_IF_ERROR_RETURN(
    606                                 _bcm_tr2_egr_cpu_cos_map(unit, numq));
    607         }
    608     }
    609 
    610     /* Add a profile mem entry for each port */
    611     BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
    612     PBMP_ITER(ports, port) {
    613         SOC_IF_ERROR_RETURN
    614             (soc_profile_mem_add(unit, _tr2_cos_map_profile[unit],
    615                                  (void *) &entries,
    616                                  TR2_COS_MAP_ENTRIES_PER_SET, &index));
    617         SOC_IF_ERROR_RETURN
    618             (soc_reg_field32_modify(unit, COS_MAP_SELr, port, SELECTf,
    619                                     index / TR2_COS_MAP_ENTRIES_PER_SET));
    620         if (soc_mem_field_valid(unit, EGR_COS_MAPm, REDIRECT_COSf)) {
    621             SOC_IF_ERROR_RETURN(
    622                 soc_profile_mem_add(unit, _tr2_cos_egr_map_profile[unit],
    623                                     (void *) &egr_entries,
    624                                     TR2_COS_MAP_ENTRIES_PER_SET, &egr_index));
    625                 SOC_IF_ERROR_RETURN
    626                       (soc_reg_field32_modify(unit, EGR_PORT_64r, port,  
    627                                               EGR_COS_MAP_SELf,
    628                                               egr_index / TR2_COS_MAP_ENTRIES_PER_SET));
    629         }
    630 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
    631         if ((IS_HG_PORT(unit, port) || port == CMIC_PORT(unit))) {
    632             SOC_IF_ERROR_RETURN
    633                 (soc_profile_mem_add(unit, _tr2_cos_map_profile[unit],
    634                                      (void *) &entries,
    635                                      TR2_COS_MAP_ENTRIES_PER_SET, &index));
    636             if (soc_mem_field_valid(unit, EGR_COS_MAPm, REDIRECT_COSf)) {
    637                 SOC_IF_ERROR_RETURN(
    638                     soc_profile_mem_add(unit, _tr2_cos_egr_map_profile[unit],
    639                                         (void *) &egr_entries,
    640                                         TR2_COS_MAP_ENTRIES_PER_SET,
    641                                         &egr_index));
    642                  SOC_IF_ERROR_RETURN
    643                       (soc_reg_field32_modify(unit, IEGR_PORT_64r, port,  
    644                                               EGR_COS_MAP_SELf,
    645                                               egr_index / TR2_COS_MAP_ENTRIES_PER_SET));
    646             }
    647 
    648             SOC_IF_ERROR_RETURN
    649                 (soc_reg_field32_modify(unit, ICOS_MAP_SELr, port, SELECTf,
    650                                         index / TR2_COS_MAP_ENTRIES_PER_SET));
    651         }
    652 #endif
    653     }
    654 
    655 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
    656     /* identity mapping for higig ports */
    657 
    658     /* map prio0->cos0, prio1->cos1, ... , prio7->cos7 */
    659     for (prio = 0; prio < 8; prio++) {
    660         soc_mem_field32_set(unit, PORT_COS_MAPm,
    661                             &cos_map_array[prio], COSf, prio);
    662         if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
    663             soc_mem_field32_set(unit, PORT_COS_MAPm,
    664                             &cos_map_array[prio], HG_COSf, 0);
    665         }
    666     }
    667     /* Map remaining internal priority levels to highest priority cosq */
    668     for (prio = 8; prio < 16; prio++) {
    669         soc_mem_field32_set(unit, PORT_COS_MAPm,
    670                             &cos_map_array[prio], COSf, 7);
    671         if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
    672             soc_mem_field32_set(unit, PORT_COS_MAPm,
    673                             &cos_map_array[prio], HG_COSf, 0);
    674         }
    675     }
    676     PBMP_ITER(ports, port) {
    677         if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
    678             SOC_IF_ERROR_RETURN
    679                 (soc_profile_mem_add(unit, _tr2_cos_map_profile[unit],
    680                                      (void *) &entries,
    681                                      TR2_COS_MAP_ENTRIES_PER_SET, &index));
    682             soc_reg_field32_modify(unit, ICOS_MAP_SELr, port, 
    683                                    SELECTf,
    684                                    (index / TR2_COS_MAP_ENTRIES_PER_SET));
    685         }
    686     }
    687 #endif
    688 
    689     /* Always strict priority for SC and QM COS queues */
    690     PBMP_ITER(ports, port) {
    691         SOC_IF_ERROR_RETURN
    692             (READ_MINSPCONFIGr(unit, port, &minsp));
    693         soc_reg_field_set(unit, MINSPCONFIGr, &minsp, COS8_IS_SPf, 1);
    694         soc_reg_field_set(unit, MINSPCONFIGr, &minsp, COS9_IS_SPf, 1);
    695         SOC_IF_ERROR_RETURN
    696             (WRITE_MINSPCONFIGr(unit, port, minsp));
    697     }
    698 
    699     _tr2_num_cosq[unit] = numq;
    700 
    701 #ifdef BCM_WARM_BOOT_SUPPORT
    702     SOC_CONTROL_LOCK(unit);
    703     SOC_CONTROL(unit)->scache_dirty = 1;
    704     SOC_CONTROL_UNLOCK(unit);
    705 #endif
    706 
    707     return BCM_E_NONE;
    708 }
    709 
    710 /*
    711  * Function:
    712  *      bcm_cosq_config_get
    713  * Purpose:
    714  *      Get the number of cos queues
    715  * Parameters:
    716  *      unit - StrataSwitch unit number.
    717  *      numq - (Output) number of cosq
    718  * Returns:
    719  *      BCM_E_XXX
    720  */
    721 
    722 int
    723 bcm_tr2_cosq_config_get(int unit, int *numq)
    724 {
    725     if (_tr2_num_cosq[unit] == 0) {
    726         return BCM_E_INIT;
    727     }
    728 
    729     if (numq != NULL) {
    730         *numq = _tr2_num_cosq[unit];
    731     }
    732 
    733     return BCM_E_NONE;
    734 }
    735 
    736 /*
    737  * Function:
    738  *      bcm_cosq_mapping_set
    739  * Purpose:
    740  *      Set which cosq a given priority should fall into
    741  * Parameters:
    742  *      unit - StrataSwitch unit number.
    743  *      priority - Priority value to map
    744  *      cosq - COS queue to map to
    745  * Returns:
    746  *      BCM_E_XXX
    747  */
    748 
    749 int
    750 bcm_tr2_cosq_mapping_set(int unit, bcm_port_t port,
    751                         bcm_cos_t priority, bcm_cos_queue_t cosq)
    752 {
    753     uint32 val, old_index, new_index;
    754     int i;
    755     port_cos_map_entry_t cos_map_array[TR2_COS_MAP_ENTRIES_PER_SET], *entry_p;
    756     void *entries[1];
    757     bcm_pbmp_t ports;
    758 
    759     if (priority < 0 || priority >= 16) {
    760         return (BCM_E_PARAM);
    761     }
    762 
    763     if (cosq < 0 || cosq >= 8) {
    764         return (BCM_E_PARAM);
    765     }
    766 
    767     if (port == -1) {	/* all ports */
    768         BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
    769     } else if (SOC_PORT_VALID(unit, port) && IS_ALL_PORT(unit, port)) {
    770         BCM_PBMP_CLEAR(ports);
    771         BCM_PBMP_PORT_ADD(ports, port);
    772     } else {
    773         return BCM_E_PORT;
    774     }
    775 
    776     entries[0] = &cos_map_array;
    777 
    778     PBMP_ITER(ports, port) {
    779         SOC_IF_ERROR_RETURN(READ_COS_MAP_SELr(unit, port, &val));
    780         old_index = soc_reg_field_get(unit, COS_MAP_SELr, val, SELECTf);
    781         old_index *= TR2_COS_MAP_ENTRIES_PER_SET;
    782 
    783         /* get current mapping profile values */
    784         for (i = 0; i < TR2_COS_MAP_ENTRIES_PER_SET; i++) {
    785             entry_p = SOC_PROFILE_MEM_ENTRY(unit, _tr2_cos_map_profile[unit],
    786                                             port_cos_map_entry_t *, (old_index + i));
    787             memcpy(&cos_map_array[i], entry_p, sizeof(*entry_p));
    788         }
    789         soc_mem_field32_set(unit, PORT_COS_MAPm,
    790                             &cos_map_array[priority], COSf, cosq);
    791         SOC_IF_ERROR_RETURN
    792             (soc_profile_mem_add(unit, _tr2_cos_map_profile[unit],
    793                                  (void *) &entries,
    794                                  TR2_COS_MAP_ENTRIES_PER_SET, &new_index));
    795         SOC_IF_ERROR_RETURN
    796             (soc_reg_field32_modify(unit, COS_MAP_SELr, port, 
    797                                     SELECTf,
    798                                     new_index / TR2_COS_MAP_ENTRIES_PER_SET));
    799         SOC_IF_ERROR_RETURN
    800             (soc_profile_mem_delete(unit, _tr2_cos_map_profile[unit], old_index));
    801 
    802 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
    803         if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
    804             SOC_IF_ERROR_RETURN
    805                 (soc_profile_mem_add(unit, _tr2_cos_map_profile[unit],
    806                                      (void *) &entries,
    807                                      TR2_COS_MAP_ENTRIES_PER_SET, &new_index));
    808             SOC_IF_ERROR_RETURN
    809                 (soc_reg_field32_modify(unit, ICOS_MAP_SELr, port, 
    810                                         SELECTf,
    811                                         new_index / TR2_COS_MAP_ENTRIES_PER_SET));
    812             SOC_IF_ERROR_RETURN
    813                 (soc_profile_mem_delete(unit, _tr2_cos_map_profile[unit], old_index));
    814         }
    815 #endif
    816     }
    817     return BCM_E_NONE;
    818 }
    819 
    820 /*
    821  * Function:
    822  *      bcm_cosq_mapping_get
    823  * Purpose:
    824  *      Determine which COS queue a given priority currently maps to.
    825  * Parameters:
    826  *      unit - StrataSwitch unit number.
    827  *      priority - Priority value
    828  *      cosq - (Output) COS queue number
    829  * Returns:
    830  *      BCM_E_XXX
    831  */
    832 
    833 int
    834 bcm_tr2_cosq_mapping_get(int unit, bcm_port_t port,
    835                         bcm_cos_t priority, bcm_cos_queue_t *cosq)
    836 {
    837     uint32 val;
    838     int index;
    839     port_cos_map_entry_t *entry_p;
    840 
    841     if (priority < 0 || priority >= 16) {
    842         return (BCM_E_PARAM);
    843     }
    844 
    845     if (port == -1) {
    846         port = REG_PORT_ANY;
    847     } else if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) {
    848         return BCM_E_PORT;
    849     }
    850 
    851     SOC_IF_ERROR_RETURN(READ_COS_MAP_SELr(unit, port, &val));
    852     index = soc_reg_field_get(unit, COS_MAP_SELr, val, SELECTf);
    853     index *= TR2_COS_MAP_ENTRIES_PER_SET;
    854 
    855     entry_p = SOC_PROFILE_MEM_ENTRY(unit, _tr2_cos_map_profile[unit],
    856                                     port_cos_map_entry_t *, 
    857                                     (index + priority));
    858     *cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, COSf);
    859     return BCM_E_NONE;
    860 }
    861 
    862 STATIC int
    863 _bcm_tr2_cosq_bucket_set(int unit, bcm_port_t port, 
    864                                 bcm_cos_queue_t cosq,
    865                                 uint32 min_quantum, /* kbps or packet/second */
    866                                 uint32 max_quantum, /* kbps or packet/second */
    867                                 uint32 kbits_burst_min, 
    868                                 uint32 kbits_burst_max, 
    869                                 uint32 flags)
    870 {
    871     uint32 regval;
    872     uint32 bucket_val = 0;
    873     uint64 regval_64, tmp;
    874     uint32 refresh_rate, bucketsize, granularity = 3, meter_flags = flags;
    875     int    refresh_bitsize, bucket_bitsize;
    876 
    877     /*
    878      * To set the new Bandwidth settings, the procedure adopted is
    879      * a. reset MAXBUCKETCONFIG, MINBUCKETCONFIG, MAXBUCKET,MINBUCKET
    880      * b. update MAXBUCKETCONFIG and MINBUCKETCONFIG with new values passed
    881      * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it.
    882      */
    883 
    884     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
    885     if (soc_reg_field_get(unit, MISCCONFIGr, regval, ITU_MODE_SELf)) {
    886         meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
    887     }
    888     meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
    889 
    890     /* Disable egress metering for this port */
    891     BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIG_64r(unit, port, cosq, &regval_64));
    892     soc_reg64_field32_set(unit, MAXBUCKETCONFIG_64r, &regval_64, MAX_REFRESHf, 0);
    893     soc_reg64_field32_set(unit, MAXBUCKETCONFIG_64r, &regval_64, MAX_THDf, 0);
    894     BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIG_64r(unit, port, cosq, regval_64));
    895 
    896     BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIG_64r(unit, port, cosq, &regval_64));
    897     soc_reg64_field32_set(unit, MINBUCKETCONFIG_64r, &regval_64, MIN_REFRESHf, 0);
    898     soc_reg64_field32_set(unit, MINBUCKETCONFIG_64r, &regval_64, MIN_THDf, 0);
    899     BCM_IF_ERROR_RETURN(WRITE_MINBUCKETCONFIG_64r(unit, port, cosq, regval_64));
    900 
    901     /*reset the MAXBUCKET register*/
    902     soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, MAX_BUCKETf, 0);
    903     soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, OUT_PROFILE_FLAGf, 0);
    904     BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETr(unit, port, cosq, bucket_val));
    905 
    906     /*reset the MINBUCKET register value*/
    907     soc_reg_field_set(unit, MINBUCKETr, &bucket_val, MIN_BUCKETf, 0);
    908     soc_reg_field_set(unit, MINBUCKETr, &bucket_val, OUT_PROFILE_FLAGf, 0);
    909     BCM_IF_ERROR_RETURN(WRITE_MINBUCKETr(unit, port, cosq, bucket_val));
    910 
    911     refresh_bitsize =
    912         soc_reg_field_length(unit, MINBUCKETCONFIG_64r, MIN_REFRESHf);
    913     bucket_bitsize =
    914         soc_reg_field_length(unit, MINBUCKETCONFIG_64r, MIN_THDf);
    915 
    916     BCM_IF_ERROR_RETURN
    917         (_bcm_xgs_kbits_to_bucket_encoding(min_quantum, kbits_burst_min,
    918                           meter_flags, refresh_bitsize, bucket_bitsize,
    919                           &refresh_rate, &bucketsize, &granularity));
    920 
    921     COMPILER_64_ZERO(regval_64);
    922     soc_reg64_field32_set(unit, MINBUCKETCONFIG_64r, &regval_64,
    923                           METER_GRANf, granularity);
    924     soc_reg64_field32_set(unit, MINBUCKETCONFIG_64r, &regval_64,
    925                           MIN_REFRESHf, refresh_rate);
    926     soc_reg64_field32_set(unit, MINBUCKETCONFIG_64r,
    927                           &regval_64, MIN_THDf, bucketsize);
    928     BCM_IF_ERROR_RETURN
    929         (WRITE_MINBUCKETCONFIG_64r(unit, port, cosq, regval_64));
    930 
    931     refresh_bitsize =
    932         soc_reg_field_length(unit, MAXBUCKETCONFIG_64r, MAX_REFRESHf);
    933     bucket_bitsize =
    934         soc_reg_field_length(unit, MAXBUCKETCONFIG_64r, MAX_THDf);
    935 
    936     BCM_IF_ERROR_RETURN
    937         (_bcm_xgs_kbits_to_bucket_encoding(max_quantum, kbits_burst_max,
    938                           meter_flags, refresh_bitsize, bucket_bitsize,
    939                           &refresh_rate, &bucketsize, &granularity));
    940 
    941     COMPILER_64_ZERO(regval_64);
    942     soc_reg64_field32_set(unit, MAXBUCKETCONFIG_64r, &regval_64,
    943                           METER_GRANf, granularity);
    944     soc_reg64_field32_set(unit, MAXBUCKETCONFIG_64r, &regval_64,
    945                           MAX_REFRESHf, refresh_rate);
    946     soc_reg64_field32_set(unit, MAXBUCKETCONFIG_64r, &regval_64, MAX_THDf,
    947                           bucketsize);
    948     BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIG_64r(unit, port, cosq, regval_64));
    949 
    950     if (flags & _BCM_XGS_METER_FLAG_PACKET_MODE) {
    951         BCM_IF_ERROR_RETURN(READ_SHAPING_MODEr(unit, port, &regval_64));
    952         COMPILER_64_SET(tmp, 0, 1);
    953         COMPILER_64_SHL(tmp, cosq);
    954         COMPILER_64_OR(regval_64, tmp);
    955         BCM_IF_ERROR_RETURN(WRITE_SHAPING_MODEr(unit, port, regval_64));
    956     } else {
    957         BCM_IF_ERROR_RETURN(READ_SHAPING_MODEr(unit, port, &regval_64));
    958         COMPILER_64_SET(tmp, 0, 1);
    959         COMPILER_64_SHL(tmp, cosq);
    960         COMPILER_64_NOT(tmp);
    961         COMPILER_64_AND(regval_64, tmp);
    962         BCM_IF_ERROR_RETURN(WRITE_SHAPING_MODEr(unit, port, regval_64));
    963     }
    964 
    965     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
    966 
    967     return BCM_E_NONE;
    968 }
    969 
    970 STATIC int
    971 _bcm_tr2_cosq_bucket_get(int unit, bcm_port_t port,
    972                                 bcm_cos_queue_t cosq,
    973                                 uint32 *min_quantum, /* kbps or packet/second */
    974                                 uint32 *max_quantum, /* kbps or packet/second */
    975                                 uint32 *kbits_burst_min, uint32 *kbits_burst_max,
    976                                 uint32 *flags)
    977 {
    978     uint32 regval;
    979     uint64 regval_64;
    980     uint32 refresh_rate = 0, bucketsize = 0, granularity = 3, meter_flags;
    981 
    982     if (!min_quantum || !max_quantum || !flags) {
    983         return (BCM_E_PARAM);
    984     }
    985 
    986     meter_flags = *flags;
    987 
    988     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
    989     if (soc_reg_field_get(unit, MISCCONFIGr, regval, ITU_MODE_SELf)) {
    990         meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
    991     }
    992     meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
    993 
    994     BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIG_64r(unit, port, cosq, &regval_64));
    995     granularity = soc_reg64_field32_get(unit, MAXBUCKETCONFIG_64r,
    996                                             regval_64, METER_GRANf);
    997     refresh_rate = soc_reg64_field32_get(unit, MAXBUCKETCONFIG_64r,
    998                                              regval_64, MAX_REFRESHf);
    999     bucketsize = soc_reg64_field32_get(unit, MAXBUCKETCONFIG_64r,
   1000                                              regval_64, MAX_THDf);
   1001 
   1002     BCM_IF_ERROR_RETURN
   1003         (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   1004                                            granularity, meter_flags,
   1005                                            max_quantum, kbits_burst_max));
   1006 
   1007     BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIG_64r(unit, port, cosq, &regval_64));
   1008 
   1009     granularity = soc_reg64_field32_get(unit, MINBUCKETCONFIG_64r,
   1010                                             regval_64, METER_GRANf);
   1011     refresh_rate = soc_reg64_field32_get(unit, MINBUCKETCONFIG_64r,
   1012                                              regval_64, MIN_REFRESHf);
   1013     bucketsize = soc_reg64_field32_get(unit, MINBUCKETCONFIG_64r,
   1014                                              regval_64, MIN_THDf);
   1015     BCM_IF_ERROR_RETURN
   1016         (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   1017                                            granularity, meter_flags,
   1018                                            min_quantum, kbits_burst_min));
   1019 
   1020     return BCM_E_NONE;
   1021 }
   1022 
   1023 int
   1024 bcm_tr2_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   1025                                 bcm_cos_queue_t cosq,
   1026                                 uint32 min_quantum, /* kbps or packet/second */
   1027                                 uint32 max_quantum, /* kbps or packet/second */
   1028                                 uint32 burst_quantum, /* kbps or packet/second */
   1029                                 uint32 flags)
   1030 {
   1031 
   1032     if (cosq < 0) {
   1033         return BCM_E_PARAM;
   1034     }
   1035 
   1036     /*keep place with original*/
   1037     return _bcm_tr2_cosq_bucket_set(unit, port, cosq, min_quantum, max_quantum,
   1038                                     min_quantum, burst_quantum, flags);    
   1039 }
   1040 
   1041 int
   1042 bcm_tr2_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   1043                                 bcm_cos_queue_t cosq,
   1044                                 uint32 *min_quantum, /* kbps or packet/second */
   1045                                 uint32 *max_quantum, /* kbps or packet/second */
   1046                                 uint32 *burst_quantum, /* kbps or packet/second */
   1047                                 uint32 *flags)
   1048 {
   1049     uint32 kbit_burst_min;
   1050 
   1051     if (cosq < -1) {
   1052         return BCM_E_PARAM;
   1053     }
   1054 
   1055     BCM_IF_ERROR_RETURN(_bcm_tr2_cosq_bucket_get(unit, port, cosq,
   1056                         min_quantum, max_quantum, &kbit_burst_min,
   1057                         burst_quantum, flags));
   1058     return BCM_E_NONE;
   1059 }
   1060 
   1061 int
   1062 bcm_tr2_cosq_port_pps_set(int unit, bcm_port_t port,
   1063                           bcm_cos_queue_t cosq, int pps)
   1064 {
   1065     uint32 min, max, burst, flags = _BCM_XGS_METER_FLAG_PACKET_MODE;
   1066     if (!IS_CPU_PORT(unit, port)) {
   1067         return BCM_E_PORT;
   1068     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   1069         return BCM_E_PARAM;
   1070     }
   1071 
   1072     /* Get the current PPS and BURST settings */
   1073     BCM_IF_ERROR_RETURN
   1074         (bcm_tr2_cosq_port_bandwidth_get(unit, port, cosq,
   1075                                          &min, &max, &burst, &flags));
   1076     /* Set the current PPS setting */
   1077     return bcm_tr2_cosq_port_bandwidth_set(unit, port, cosq,
   1078                                            min, pps, burst, flags);
   1079 }
   1080 
   1081 int
   1082 bcm_tr2_cosq_port_pps_get(int unit, bcm_port_t port,
   1083                           bcm_cos_queue_t cosq, int *pps)
   1084 {
   1085     uint32 min, max, burst, flags = _BCM_XGS_METER_FLAG_PACKET_MODE;
   1086 
   1087     if (!IS_CPU_PORT(unit, port)) {
   1088         return BCM_E_PORT;
   1089     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   1090         return BCM_E_PARAM;
   1091     }
   1092 
   1093     BCM_IF_ERROR_RETURN(bcm_tr2_cosq_port_bandwidth_get(unit, port, cosq,
   1094                                                &min, &max, &burst, &flags));
   1095     *pps = max;
   1096     return BCM_E_NONE;
   1097 }
   1098 
   1099 int
   1100 bcm_tr2_cosq_port_burst_set(int unit, bcm_port_t port,
   1101                             bcm_cos_queue_t cosq, int burst)
   1102 {
   1103     uint32 min, max, cur_burst, flags = _BCM_XGS_METER_FLAG_PACKET_MODE;
   1104 
   1105     if (!IS_CPU_PORT(unit, port)) {
   1106         return BCM_E_PORT;
   1107     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   1108         return BCM_E_PARAM;
   1109     }
   1110 
   1111     /* Get the current PPS and BURST settings */
   1112     BCM_IF_ERROR_RETURN(bcm_tr2_cosq_port_bandwidth_get(unit, port, cosq,
   1113                                           &min, &max, &cur_burst, &flags));
   1114     /* Replace the current BURST setting, keep PPS the same */
   1115     return bcm_tr2_cosq_port_bandwidth_set(unit, port, cosq, min, max,
   1116                                            burst, flags);
   1117 }
   1118 
   1119 int
   1120 bcm_tr2_cosq_port_burst_get(int unit, bcm_port_t port,
   1121                             bcm_cos_queue_t cosq, int *burst)
   1122 {
   1123     uint32 min, max, cur_burst, flags = _BCM_XGS_METER_FLAG_PACKET_MODE;
   1124 
   1125     if (!IS_CPU_PORT(unit, port)) {
   1126         return BCM_E_PORT;
   1127     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   1128         return BCM_E_PARAM;
   1129     }
   1130 
   1131     BCM_IF_ERROR_RETURN(bcm_tr2_cosq_port_bandwidth_get(unit, port, cosq,
   1132                                           &min, &max, &cur_burst, &flags));
   1133     *burst = cur_burst;
   1134     return BCM_E_NONE;
   1135 }
   1136 
   1137 int
   1138 _bcm_tr2_cosq_port_resolve(int unit, bcm_gport_t gport,
   1139                            bcm_module_t *modid, bcm_port_t *port,
   1140                            bcm_trunk_t *trunk_id, int *id)
   1141 {
   1142     bcm_module_t mod_in;
   1143     bcm_port_t port_in;
   1144 
   1145     if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1146         mod_in = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0xff;
   1147         port_in = BCM_GPORT_SCHEDULER_GET(gport) & 0xff;
   1148         *id = BCM_GPORT_SCHEDULER_GET(gport);
   1149         *trunk_id = -1;
   1150 
   1151         /* Since the modid/port in the scheduler GPORT is the
   1152          * applications modid/port space, convert to local space.
   1153          */
   1154         BCM_IF_ERROR_RETURN
   1155             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   1156                                     mod_in, port_in, modid, port));
   1157 
   1158         if (!_tr2_num_port_cosq[unit]) {
   1159             return BCM_E_INIT;
   1160         } else if (!SOC_PBMP_MEMBER(_tr2_cosq_24q_ports[unit], *port)) {
   1161             return BCM_E_BADID;
   1162         } else if (_tr2_num_port_cosq[unit][*port] == 0) {
   1163             return BCM_E_NOT_FOUND;
   1164         }
   1165     } else {
   1166         return BCM_E_BADID;
   1167     }
   1168     return BCM_E_NONE;
   1169 }
   1170 
   1171 STATIC int
   1172 _bcm_tr2_cosq_resolve_mod_port(int unit, bcm_gport_t gport,
   1173                                bcm_module_t *modid, bcm_port_t *port,
   1174                                bcm_trunk_t *trunk_id)
   1175 {
   1176     int gport_id, result;
   1177 
   1178     BCM_IF_ERROR_RETURN
   1179         (_bcm_esw_gport_resolve(unit, gport, modid,
   1180                                 port, trunk_id, &gport_id));
   1181     BCM_IF_ERROR_RETURN(
   1182         _bcm_esw_modid_is_local(unit, *modid, &result)); 
   1183 
   1184     if (TRUE != result) {
   1185         return BCM_E_PORT;
   1186     }
   1187     return BCM_E_NONE;
   1188 }
   1189 
   1190 STATIC int     
   1191 _bcm_tr2_cosq_discard_cap_enable_set(int unit, bcm_port_t port, 
   1192                                     bcm_cos_queue_t cosq, soc_reg_t config_reg, 
   1193                                     uint32 flags)
   1194 {
   1195     uint32 val, addr;
   1196 
   1197     addr = soc_reg_addr(unit, config_reg, port, cosq);
   1198     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1199 
   1200     if (flags & BCM_COSQ_DISCARD_CAP_AVERAGE) {
   1201         soc_reg_field_set(unit, config_reg, &val, CAP_AVERAGEf, 1);
   1202     } else {
   1203         soc_reg_field_set(unit, config_reg, &val, CAP_AVERAGEf, 0);
   1204     }
   1205     if (flags & BCM_COSQ_DISCARD_ENABLE) {
   1206         soc_reg_field_set(unit, config_reg, &val, ENABLEf, 1);
   1207     } else {
   1208         soc_reg_field_set(unit, config_reg, &val, ENABLEf, 0);
   1209     }
   1210     SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1211     return BCM_E_NONE;
   1212 }
   1213 
   1214 STATIC int
   1215 _bcm_tr2_cosq_discard_cap_enable_get(int unit, bcm_port_t port, 
   1216                                     bcm_cos_queue_t cosq, soc_reg_t config_reg, 
   1217                                     uint32 *flags)
   1218 {
   1219     uint32 val, addr;
   1220 
   1221     addr = soc_reg_addr(unit, config_reg, port, cosq);
   1222     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1223 
   1224     if (soc_reg_field_get(unit, config_reg, val, CAP_AVERAGEf)) {
   1225         *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   1226     }
   1227     if (soc_reg_field_get(unit, config_reg, val, ENABLEf)) {
   1228         *flags |= BCM_COSQ_DISCARD_ENABLE;
   1229     }
   1230     return BCM_E_NONE;
   1231 }
   1232 
   1233 int
   1234 bcm_tr2_cosq_discard_set(int unit, uint32 flags)
   1235 {
   1236     bcm_port_t port;
   1237     bcm_cos_queue_t cosq;
   1238     soc_reg_t config_reg = WREDCONFIG_PACKETr;
   1239 
   1240     if (flags & ~(BCM_COSQ_DISCARD_CAP_AVERAGE |
   1241                   BCM_COSQ_DISCARD_ENABLE)) {
   1242         return BCM_E_PARAM;
   1243     }
   1244 
   1245     PBMP_ALL_ITER(unit, port) {
   1246         if (IS_CPU_PORT(unit, port)) {
   1247             continue;
   1248         }
   1249         for (cosq = 0; cosq < 8; cosq++) {
   1250             BCM_IF_ERROR_RETURN
   1251                 (_bcm_tr2_cosq_discard_cap_enable_set(unit, port, cosq,
   1252                                                      config_reg, flags));
   1253         }
   1254         if (SOC_PBMP_MEMBER(_tr2_cosq_24q_ports[unit], port)) {
   1255             for (cosq = 8; cosq < 24; cosq++) {
   1256                 BCM_IF_ERROR_RETURN
   1257                     (_bcm_tr2_cosq_discard_cap_enable_set(unit, port, cosq,
   1258                                                          config_reg, flags));
   1259             }
   1260         }
   1261     }
   1262     return BCM_E_NONE;
   1263 }
   1264 
   1265 int
   1266 bcm_tr2_cosq_discard_get(int unit, uint32 *flags)
   1267 {
   1268     int rv = BCM_E_NONE;
   1269     bcm_port_t port;
   1270     soc_reg_t config_reg = WREDCONFIG_PACKETr;
   1271 
   1272     PBMP_ALL_ITER(unit, port) {
   1273         if (IS_CPU_PORT(unit, port)) {
   1274             continue;
   1275         }
   1276         *flags = 0;
   1277         rv = _bcm_tr2_cosq_discard_cap_enable_get(unit, port, 0,
   1278                                                  config_reg, flags);
   1279         break;
   1280     }
   1281     return rv;
   1282 }
   1283 
   1284 /*      
   1285  *  Convert HW drop probability to percent value
   1286  */     
   1287 STATIC int       
   1288 _bcm_tr2_hw_drop_prob_to_percent[] = {
   1289     0,     /* 0  */
   1290     1,     /* 1  */
   1291     2,     /* 2  */
   1292     3,     /* 3  */
   1293     4,     /* 4  */
   1294     5,     /* 5  */
   1295     6,     /* 6  */
   1296     7,     /* 7  */
   1297     8,     /* 8  */
   1298     9,     /* 9  */
   1299     10,    /* 10 */
   1300     25,    /* 11 */
   1301     50,    /* 12 */
   1302     75,    /* 13 */
   1303     100,   /* 14 */
   1304     -1     /* 15 */
   1305 };
   1306 
   1307 STATIC int
   1308 _bcm_tr2_percent_to_drop_prob(int percent) {
   1309    int i;
   1310 
   1311    for (i=14; i > 0 ; i--) {
   1312       if (percent >= _bcm_tr2_hw_drop_prob_to_percent[i]) {
   1313           break;
   1314       }
   1315    }
   1316    return i;
   1317 }
   1318 
   1319 STATIC int
   1320 _bcm_tr2_drop_prob_to_percent(int drop_prob) {
   1321    return (_bcm_tr2_hw_drop_prob_to_percent[drop_prob]);
   1322 }   
   1323 
   1324 STATIC int 
   1325 _bcm_tr2_angle_to_packets_table[] =
   1326 {
   1327     /*  0.. 5 */  16383, 5727, 2862, 1908, 1430, 1142,
   1328     /*  6..11 */    951,  814,  711,  631,  567,  514,
   1329     /* 12..17 */    470,  433,  401,  373,  348,  327,
   1330     /* 18..23 */    307,  290,  274,  260,  247,  235,
   1331     /* 24..29 */    224,  214,  205,  196,  188,  180,
   1332     /* 30..35 */    173,  166,  160,  153,  148,  142,
   1333     /* 36..41 */    137,  132,  127,  123,  119,  115,
   1334     /* 42..47 */    111,  107,  103,  100,   96,   93,
   1335     /* 48..53 */     90,   86,   83,   80,   78,   75,
   1336     /* 54..59 */     72,   70,   67,   64,   62,   60,
   1337     /* 60..65 */     57,   55,   53,   50,   48,   46,
   1338     /* 66..71 */     44,   42,   40,   38,   36,   34,
   1339     /* 72..77 */     32,   30,   28,   26,   24,   23,
   1340     /* 78..83 */     21,   19,   17,   15,   14,   12,
   1341     /* 84..89 */     10,    8,    6,    5,    3,    1,
   1342     /* 90     */      0
   1343 };
   1344 
   1345 /* 
   1346  * Given a slope (angle in degrees) from 0 to 90, return
   1347  * the number of packets in the range from 0% drop
   1348  * probability to 100% drop probability.
   1349  */
   1350 STATIC int
   1351 _bcm_tr2_angle_to_packets(int angle) {
   1352     return (_bcm_tr2_angle_to_packets_table[angle]);
   1353 }
   1354 
   1355 /*
   1356  * Given a number of packets in the range from 0% drop probability
   1357  * to 100% drop probability, return the slope (angle in degrees).
   1358  */
   1359 STATIC int
   1360 _bcm_tr2_packets_to_angle(int packets) {
   1361     int angle;
   1362 
   1363     for (angle = 90; angle >= 0 ; angle--) {
   1364         if (packets <= _bcm_tr2_angle_to_packets_table[angle]) {
   1365             break;
   1366         }
   1367     }
   1368     return angle;
   1369 }
   1370 
   1371 STATIC int     
   1372 _bcm_tr2_cosq_discard_set(int unit, bcm_port_t port, uint32 flags,
   1373                          bcm_cos_queue_t cosq, soc_reg_t config_reg,
   1374                          soc_reg_t thresh_reg_green,
   1375                          soc_reg_t thresh_reg_yellow,
   1376                          soc_reg_t thresh_reg_red,
   1377                          soc_reg_t thresh_reg_non_tcp,
   1378                          uint32 min_thresh, uint32 max_thresh,
   1379                          int drop_probability, int gain)
   1380 {
   1381     uint32 val, addr;
   1382 
   1383     if (flags & ~(BCM_COSQ_DISCARD_COLOR_GREEN  | 
   1384                   BCM_COSQ_DISCARD_COLOR_YELLOW |
   1385                   BCM_COSQ_DISCARD_COLOR_RED    |
   1386                   BCM_COSQ_DISCARD_COLOR_ALL    |
   1387                   BCM_COSQ_DISCARD_CAP_AVERAGE  |
   1388                   BCM_COSQ_DISCARD_PACKETS      |
   1389                   BCM_COSQ_DISCARD_BYTES        |
   1390                   BCM_COSQ_DISCARD_ENABLE       |
   1391                   BCM_COSQ_DISCARD_NONTCP)) {
   1392         return BCM_E_PARAM;
   1393     }
   1394 
   1395     addr = soc_reg_addr(unit, config_reg, port, cosq);
   1396     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1397 
   1398     /* Program the weight */
   1399     soc_reg_field_set(unit, config_reg, &val, WEIGHTf, gain);
   1400 
   1401     /* Program the drop probabilty */
   1402     if ((flags & BCM_COSQ_DISCARD_COLOR_GREEN) ||
   1403         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1404         soc_reg_field_set(unit, config_reg, &val, MAXDROPRATEf,
   1405             _bcm_tr2_percent_to_drop_prob(drop_probability));
   1406     }
   1407     if ((flags & BCM_COSQ_DISCARD_COLOR_YELLOW) ||
   1408         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1409         soc_reg_field_set(unit, config_reg, &val, YELLOW_MAXDROPRATEf,
   1410             _bcm_tr2_percent_to_drop_prob(drop_probability));
   1411     }
   1412     if ((flags & BCM_COSQ_DISCARD_COLOR_RED) ||
   1413         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1414         soc_reg_field_set(unit, config_reg, &val, RED_MAXDROPRATEf,
   1415             _bcm_tr2_percent_to_drop_prob(drop_probability));
   1416     }
   1417     if (flags & BCM_COSQ_DISCARD_NONTCP) {
   1418         soc_reg_field_set(unit, config_reg, &val, NONTCP_MAXDROPRATEf,
   1419             _bcm_tr2_percent_to_drop_prob(drop_probability));
   1420     }
   1421     SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1422 
   1423     /* Program the min and max thresholds */
   1424     if ((flags & BCM_COSQ_DISCARD_COLOR_GREEN) ||
   1425         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1426         addr = soc_reg_addr(unit, thresh_reg_green, port, cosq);
   1427         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1428         soc_reg_field_set(unit, thresh_reg_green, &val, DROPSTARTPOINTf,
   1429                           min_thresh);
   1430         soc_reg_field_set(unit, thresh_reg_green, &val, DROPENDPOINTf,
   1431                           max_thresh);
   1432         SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1433     }
   1434     if ((flags & BCM_COSQ_DISCARD_COLOR_YELLOW) ||
   1435         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1436         addr = soc_reg_addr(unit, thresh_reg_yellow, port, cosq);
   1437         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1438         soc_reg_field_set(unit, thresh_reg_yellow, &val,
   1439                           YELLOW_DROPSTARTPOINTf, min_thresh);
   1440         soc_reg_field_set(unit, thresh_reg_yellow, &val,
   1441                           YELLOW_DROPENDPOINTf, max_thresh);
   1442         SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1443     }
   1444     if ((flags & BCM_COSQ_DISCARD_COLOR_RED) ||
   1445         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1446         addr = soc_reg_addr(unit, thresh_reg_red, port, cosq);
   1447         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1448         soc_reg_field_set(unit, thresh_reg_red, &val,
   1449                           RED_DROPSTARTPOINTf, min_thresh);
   1450         soc_reg_field_set(unit, thresh_reg_red, &val,
   1451                           RED_DROPENDPOINTf, max_thresh);
   1452         SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1453     }
   1454     if (flags & BCM_COSQ_DISCARD_NONTCP) {
   1455         addr = soc_reg_addr(unit, thresh_reg_non_tcp, port, cosq);
   1456         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1457         soc_reg_field_set(unit, thresh_reg_non_tcp, &val,
   1458                           NONTCP_DROPSTARTPOINTf, min_thresh);
   1459         soc_reg_field_set(unit, thresh_reg_non_tcp, &val,
   1460                           NONTCP_DROPENDPOINTf, max_thresh);
   1461         SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1462     }
   1463 
   1464     return BCM_E_NONE;
   1465 }
   1466 
   1467 STATIC int     
   1468 _bcm_tr2_cosq_discard_get(int unit, bcm_port_t port, uint32 flags,
   1469                          bcm_cos_queue_t cosq, soc_reg_t config_reg,
   1470                          soc_reg_t thresh_reg_green,
   1471                          soc_reg_t thresh_reg_yellow,
   1472                          soc_reg_t thresh_reg_red,
   1473                          soc_reg_t thresh_reg_non_tcp,
   1474                          uint32 *min_thresh, uint32 *max_thresh,
   1475                          int *drop_probability, int *gain)
   1476 {
   1477     uint32 val, addr, drop_rate;
   1478 
   1479     addr = soc_reg_addr(unit, config_reg, port, cosq);
   1480     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1481 
   1482     /* Get the weight */
   1483     *gain = soc_reg_field_get(unit, config_reg, val, WEIGHTf);
   1484 
   1485     /* Get the drop probabilty */
   1486     if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   1487         drop_rate = soc_reg_field_get(unit, config_reg, val,
   1488                                       YELLOW_MAXDROPRATEf);
   1489     } else if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   1490         drop_rate = soc_reg_field_get(unit, config_reg, val,
   1491                                       RED_MAXDROPRATEf);
   1492     } else {
   1493         drop_rate = soc_reg_field_get(unit, config_reg, val,
   1494                                       MAXDROPRATEf);
   1495     }
   1496     *drop_probability = _bcm_tr2_drop_prob_to_percent(drop_rate);
   1497 
   1498     /* Get the min and max thresholds */
   1499     if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   1500         addr = soc_reg_addr(unit, thresh_reg_yellow, port, cosq);
   1501         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1502         *min_thresh = soc_reg_field_get(unit, thresh_reg_yellow, val,
   1503                                         YELLOW_DROPSTARTPOINTf);
   1504         *max_thresh = soc_reg_field_get(unit, thresh_reg_yellow, val,
   1505                                         YELLOW_DROPENDPOINTf);
   1506     } else if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   1507         addr = soc_reg_addr(unit, thresh_reg_red, port, cosq);
   1508         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1509         *min_thresh = soc_reg_field_get(unit, thresh_reg_red, val,
   1510                                         RED_DROPSTARTPOINTf);
   1511         *max_thresh = soc_reg_field_get(unit, thresh_reg_red, val,
   1512                                         RED_DROPENDPOINTf);
   1513     } else {
   1514         addr = soc_reg_addr(unit, thresh_reg_green, port, cosq);
   1515         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1516         *min_thresh = soc_reg_field_get(unit, thresh_reg_green, val, 
   1517                                         DROPSTARTPOINTf);
   1518         *max_thresh = soc_reg_field_get(unit, thresh_reg_green, val, 
   1519                                         DROPENDPOINTf);
   1520     }
   1521     return BCM_E_NONE;
   1522 }
   1523 
   1524 #define ABS(n) (((n) < 0) ? -(n) : (n))
   1525 
   1526 int
   1527 bcm_tr2_cosq_discard_port_set(int unit, bcm_port_t port,
   1528                              bcm_cos_queue_t cosq,
   1529                              uint32 color,
   1530                              int drop_start,
   1531                              int drop_slope,
   1532                              int average_time)
   1533 {
   1534     bcm_module_t modid;
   1535     bcm_port_t local_port;
   1536     bcm_trunk_t trunk_id;
   1537     bcm_pbmp_t pbmp;
   1538     int i, gain, cosq_start, num_cosq;
   1539     uint32 min_thresh, max_thresh, shared_limit;
   1540     uint32 rval, bits;
   1541 
   1542     if (!_tr2_num_port_cosq[unit]) {
   1543         return BCM_E_INIT;
   1544     }
   1545 
   1546     if (drop_start < 0 || drop_start > 100 ||
   1547         drop_slope < 0 || drop_slope > 90) {
   1548         return BCM_E_PARAM;
   1549     }
   1550 
   1551     if (BCM_GPORT_IS_SET(port)) {
   1552         if (BCM_GPORT_IS_SCHEDULER(port)) {
   1553             BCM_IF_ERROR_RETURN
   1554                 (_bcm_tr2_cosq_resolve_mod_port(unit, port, &modid,
   1555                                                 &local_port, &trunk_id));
   1556         } else {
   1557             BCM_IF_ERROR_RETURN
   1558                 (bcm_esw_port_local_get(unit, port, &local_port));
   1559         }
   1560         BCM_PBMP_PORT_SET(pbmp, local_port);
   1561     } else {
   1562         if (port == -1) {
   1563             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   1564         } else if (IS_CPU_PORT(unit, port) || !SOC_PORT_VALID(unit, port)) {
   1565             return BCM_E_PORT;
   1566         } else {
   1567             local_port = port;
   1568             BCM_PBMP_PORT_SET(pbmp, port);
   1569         }
   1570     }
   1571 
   1572     if (BCM_GPORT_IS_SCHEDULER(port)) {
   1573         if (_tr2_num_port_cosq[unit][local_port] == 0) {
   1574             return BCM_E_NOT_FOUND;
   1575         } else if (cosq < -1 || cosq >= _tr2_num_port_cosq[unit][local_port]) {
   1576             return BCM_E_PARAM;
   1577         } else if (cosq == -1) {
   1578             cosq_start = 8;
   1579             num_cosq = _tr2_num_port_cosq[unit][local_port];
   1580         } else {
   1581             cosq_start = cosq + 8;
   1582             num_cosq = 1;
   1583         }
   1584     } else {
   1585         if (cosq < -1 || cosq >= _tr2_num_cosq[unit]) {
   1586             return BCM_E_PARAM;
   1587         } else if (cosq == -1) {
   1588             cosq_start = 0;
   1589             num_cosq = 8;
   1590         } else {
   1591             cosq_start = cosq;
   1592             num_cosq = 1;
   1593         }
   1594     }
   1595 
   1596     /*
   1597      * average queue size is reculated every 4us, the formula is
   1598      * avg_qsize(t + 1) =
   1599      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   1600      * gain = log2(average_time / 4)
   1601      */
   1602     bits = (average_time / 4) & 0xffff;
   1603     bits |= bits >> 1;
   1604     bits |= bits >> 2;
   1605     bits |= bits >> 4;
   1606     bits |= bits >> 8;
   1607     gain = _shr_popcount(bits);
   1608     /* Don't allow negative value of gain */
   1609     if (gain) {
   1610         gain -= 1;
   1611     }
   1612 
   1613     /*
   1614      * per-port packet limit may be disabled.
   1615      * per-port per-cos packet limit may be set to use dynamic method.
   1616      * therefore drop_start percentage is based on per-device total shared
   1617      * packets.
   1618      */
   1619     SOC_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMIT_PACKETr(unit, &rval));
   1620     shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMIT_PACKETr,
   1621                                      rval, OP_BUFFER_SHARED_LIMIT_PACKETf);
   1622     min_thresh = drop_start * shared_limit / 100;
   1623 
   1624     /* Calculate the max threshold. For a given slope (angle in 
   1625      * degrees), determine how many packets are in the range from
   1626      * 0% drop probability to 100% drop probability. Add that
   1627      * number to the min_treshold to the the max_threshold.
   1628      */
   1629     max_thresh = min_thresh + _bcm_tr2_angle_to_packets(drop_slope);
   1630     if (max_thresh > TR2_PACKET_FIELD_MAX) {
   1631         max_thresh = TR2_PACKET_FIELD_MAX;
   1632     }
   1633 
   1634     BCM_PBMP_ITER(pbmp, local_port) {
   1635         for (i = cosq_start; i < (cosq_start + num_cosq); i++) { 
   1636             BCM_IF_ERROR_RETURN
   1637                 (_bcm_tr2_cosq_discard_set(unit, local_port, color, i,
   1638                                            WREDCONFIG_PACKETr,
   1639                                            WREDPARAM_PACKETr,
   1640                                            WREDPARAM_YELLOW_PACKETr,
   1641                                            WREDPARAM_RED_PACKETr,
   1642                                            WREDPARAM_NONTCP_PACKETr,
   1643                                            min_thresh, max_thresh, 100, gain));
   1644         }
   1645     }
   1646     return BCM_E_NONE;
   1647 }
   1648 
   1649 int
   1650 bcm_tr2_cosq_discard_port_get(int unit, bcm_port_t port,
   1651                              bcm_cos_queue_t cosq,
   1652                              uint32 color,
   1653                              int *drop_start,
   1654                              int *drop_slope,
   1655                              int *average_time)
   1656 {
   1657     bcm_module_t modid;
   1658     bcm_port_t local_port;
   1659     bcm_trunk_t trunk_id;
   1660     bcm_pbmp_t pbmp;
   1661     int gain, drop_prob;
   1662     uint32 min_thresh, max_thresh, shared_limit;
   1663     uint32 rval;
   1664 
   1665     if (!_tr2_num_port_cosq[unit]) {
   1666         return BCM_E_INIT;
   1667     }
   1668 
   1669     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   1670         return BCM_E_PARAM;
   1671     }
   1672 
   1673     if (BCM_GPORT_IS_SET(port)) {
   1674         if (BCM_GPORT_IS_SCHEDULER(port)) {
   1675             BCM_IF_ERROR_RETURN
   1676                 (_bcm_tr2_cosq_resolve_mod_port(unit, port, &modid,
   1677                                                 &local_port, &trunk_id));
   1678         } else {
   1679             BCM_IF_ERROR_RETURN
   1680                 (bcm_esw_port_local_get(unit, port, &local_port));
   1681         }
   1682         BCM_PBMP_PORT_SET(pbmp, local_port);
   1683     } else {
   1684         if (port == -1) {
   1685             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   1686         } else if (IS_CPU_PORT(unit, port) || !SOC_PORT_VALID(unit, port)) {
   1687             return BCM_E_PORT;
   1688         } else {
   1689             local_port = port;
   1690             BCM_PBMP_PORT_SET(pbmp, port);
   1691         }
   1692     }
   1693 
   1694     if (BCM_GPORT_IS_SCHEDULER(port)) {
   1695         if (_tr2_num_port_cosq[unit][local_port] == 0) {
   1696             return BCM_E_NOT_FOUND;
   1697         } else if (cosq < -1 || cosq >= _tr2_num_port_cosq[unit][local_port]) {
   1698             return BCM_E_PARAM;
   1699         } else if (cosq == -1) {
   1700             cosq = 8;
   1701         } else {
   1702             cosq = cosq + 8;
   1703         }
   1704     } else {
   1705         if (cosq < -1 || cosq >= _tr2_num_cosq[unit]) {
   1706             return BCM_E_PARAM;
   1707         } else if (cosq == -1) {
   1708             cosq = 0;
   1709         }
   1710     }
   1711 
   1712     BCM_PBMP_ITER(pbmp, local_port) {
   1713         BCM_IF_ERROR_RETURN
   1714             (_bcm_tr2_cosq_discard_get(unit, local_port, color, cosq,
   1715                                        WREDCONFIG_PACKETr,
   1716                                        WREDPARAM_PACKETr,
   1717                                        WREDPARAM_YELLOW_PACKETr,
   1718                                        WREDPARAM_RED_PACKETr,
   1719                                        WREDPARAM_NONTCP_PACKETr,
   1720                                        &min_thresh, &max_thresh, &drop_prob,
   1721                                        &gain));
   1722 
   1723         /*
   1724          * average queue size is reculated every 4us, the formula is
   1725          * avg_qsize(t + 1) =
   1726          *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   1727          */
   1728         *average_time = (1 << gain) * 4;
   1729 
   1730         /*
   1731          * per-port packet limit may be disabled.
   1732          * per-port per-cos packet limit may be set to use dynamic method.
   1733          * therefore drop_start percentage is based on per-device total shared
   1734          * packets.
   1735          */
   1736         SOC_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMIT_PACKETr(unit, &rval));
   1737         shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMIT_PACKETr,
   1738                                          rval, OP_BUFFER_SHARED_LIMIT_PACKETf);
   1739         if (min_thresh >= shared_limit) {
   1740             *drop_start = 100;
   1741         } else {
   1742             *drop_start = min_thresh * 100 / shared_limit;
   1743         }
   1744 
   1745         /* Calculate the slope using the min and max threshold.
   1746          * The angle is calculated knowing drop probability at min
   1747          * threshold is 0% and drop probability at max threshold is 100%.
   1748          */
   1749         *drop_slope = _bcm_tr2_packets_to_angle(max_thresh - min_thresh);
   1750         break;
   1751     }
   1752 
   1753     return BCM_E_NONE;
   1754 }
   1755 
   1756 STATIC int
   1757 _bcm_tr2_cosq_port_sched_set(int unit, soc_reg_t config_reg,
   1758                             soc_reg_t weight_reg, soc_reg_t minsp_reg,
   1759                             bcm_port_t port, bcm_cos_queue_t start_cosq,
   1760                             int num_weights, const int weights[],
   1761                             int mode)
   1762 {
   1763     int t, i;
   1764     uint32 cfg_addr, cosw_addr, minsp_addr, cfg, cosw, minsp;
   1765     int mbits = 0;
   1766     int weight_max, sel, quanta;
   1767 
   1768     cfg_addr = soc_reg_addr(unit, config_reg, port, 0);
   1769     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, cfg_addr, &cfg));
   1770 
   1771     switch (mode) {
   1772     case BCM_COSQ_STRICT:
   1773         mbits = 0;
   1774         break;
   1775     case BCM_COSQ_ROUND_ROBIN:
   1776         mbits = 1;
   1777         break;
   1778     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   1779         mbits = 2;
   1780         /*
   1781          * All weight values must fit within 7 bits.
   1782          * If weight is 0, this queue is run in strict mode,
   1783          * others run in WRR mode.
   1784          */
   1785         for(i = 0; i < num_weights; i++) {
   1786             if (weights[i] > TR2_WRR_WEIGHT_MAX) {
   1787                 return BCM_E_PARAM;
   1788             }
   1789         }
   1790         for (i = 0; i < num_weights; i++) {
   1791             cosw_addr = soc_reg_addr(unit, weight_reg, port, start_cosq + i);
   1792             SOC_IF_ERROR_RETURN(soc_reg32_read(unit, cosw_addr, &cosw));
   1793             soc_reg_field_set(unit, weight_reg, &cosw, COSWEIGHTSf,
   1794                               weights[i]);
   1795             SOC_IF_ERROR_RETURN(soc_reg32_write(unit, cosw_addr, cosw));
   1796         }
   1797         break;
   1798     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   1799         mbits = 3;
   1800 
   1801         weight_max = 0;
   1802         for (i = 0; i < num_weights; i++) {
   1803             if (weight_max < weights[i]) {
   1804                 weight_max = weights[i];
   1805             }
   1806         }
   1807 
   1808         for (sel = 0; sel <= 3; sel++) {
   1809             if (weight_max <= TR2_DRR_WEIGHT_MAX * (1 << (sel + 1))) {
   1810                 break;
   1811             }
   1812         }
   1813         if (sel > 3) {
   1814             return BCM_E_PARAM;
   1815         }
   1816         quanta = 1 << (sel + 1);
   1817         soc_reg_field_set(unit, config_reg, &cfg, MTU_QUANTA_SELECTf, sel);
   1818         for (i = 0; i < num_weights; i++) {
   1819             cosw_addr = soc_reg_addr(unit, weight_reg, port, start_cosq + i);
   1820             SOC_IF_ERROR_RETURN(soc_reg32_read(unit, cosw_addr, &cosw));
   1821             /* the unit of weight for WDRR is specified mtu quanta */
   1822             soc_reg_field_set(unit, weight_reg, &cosw, COSWEIGHTSf,
   1823                               (weights[i] + quanta - 1) / quanta);
   1824             SOC_IF_ERROR_RETURN(soc_reg32_write(unit, cosw_addr, cosw));
   1825         }
   1826         break;
   1827     case BCM_COSQ_BOUNDED_DELAY:        /* not supported in xgs */
   1828     default:
   1829         return BCM_E_PARAM;
   1830     }
   1831 
   1832     if ((mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) ||
   1833         (mode == BCM_COSQ_DEFICIT_ROUND_ROBIN)) {
   1834         /* Set strict priority bit if weight is zero */
   1835         minsp_addr = soc_reg_addr(unit, minsp_reg, port, 0);
   1836         SOC_IF_ERROR_RETURN
   1837             (soc_reg32_read(unit, minsp_addr, &minsp));
   1838         for(i = 0; i < num_weights; i++) {
   1839             t = start_cosq + i;
   1840             if (weights[i] == 0) {
   1841                 minsp |= (1 << t);
   1842             } else {
   1843                 minsp &= ~(1 << t);
   1844             }
   1845         }
   1846         SOC_IF_ERROR_RETURN
   1847             (soc_reg32_write(unit, minsp_addr, minsp));
   1848     }
   1849 
   1850     /* Program the scheduling mode */
   1851     soc_reg_field_set(unit, config_reg, &cfg, SCHEDULING_SELECTf, mbits);
   1852     SOC_IF_ERROR_RETURN(soc_reg32_write(unit, cfg_addr, cfg));
   1853 
   1854     return BCM_E_NONE;
   1855 }
   1856 
   1857 STATIC int
   1858 _bcm_tr2_cosq_port_sched_get(int unit, soc_reg_t config_reg,
   1859                             soc_reg_t weight_reg, bcm_port_t port,
   1860                             bcm_cos_queue_t start_cosq,
   1861                             int num_weights, int weights[], int *mode)
   1862 {
   1863     uint32 addr, cfg, cosw;
   1864     int mbits, i;
   1865     uint32 quanta;
   1866 
   1867     addr = soc_reg_addr(unit, config_reg, port, 0);
   1868     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &cfg));
   1869     mbits = soc_reg_field_get(unit, config_reg, cfg, SCHEDULING_SELECTf);
   1870 
   1871     switch (mbits) {
   1872     case 0:
   1873         *mode = BCM_COSQ_STRICT;
   1874         break;
   1875     case 1:
   1876         *mode = BCM_COSQ_ROUND_ROBIN;
   1877         break;
   1878     case 2:
   1879         *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   1880         for (i = 0; i < num_weights; i++) {
   1881             addr = soc_reg_addr(unit, weight_reg, port, start_cosq + i);
   1882             SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &cosw));
   1883             weights[i] = soc_reg_field_get(unit, weight_reg, cosw,
   1884                                            COSWEIGHTSf);
   1885         }
   1886         break;
   1887     case 3:
   1888         *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   1889         switch (soc_reg_field_get(unit, config_reg, cfg, MTU_QUANTA_SELECTf)) {
   1890         case 0: /* quanta is 2k bytes */
   1891             quanta = 2;
   1892             break;
   1893         case 1: /* quanta is 4k bytes */
   1894             quanta = 4;
   1895             break;
   1896         case 2: /* quanta is 8k bytes */
   1897             quanta = 8;
   1898             break;
   1899         case 3: /* quanta is 16k bytes */
   1900             quanta = 16;
   1901             break;
   1902         default:
   1903             return SOC_E_INTERNAL;
   1904         }
   1905         for (i = 0; i < num_weights; i++) {
   1906             addr = soc_reg_addr(unit, weight_reg, port, start_cosq + i);
   1907             SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &cosw));
   1908             /* the unit of weight for WDRR is specified mtu quanta */
   1909             weights[i] = soc_reg_field_get(unit, weight_reg, cosw,
   1910                                            COSWEIGHTSf) * quanta;
   1911         }
   1912         break;
   1913     default:
   1914         return BCM_E_INTERNAL;
   1915     }
   1916 
   1917     return BCM_E_NONE;
   1918 }
   1919 
   1920 /*
   1921  * Function:
   1922  *      bcm_cosq_port_sched_set
   1923  * Purpose:
   1924  *      Set up class-of-service policy and corresponding weights and delay
   1925  * Parameters:
   1926  *      unit - StrataSwitch unit number.
   1927  *      pbm - port bitmap
   1928  *      mode - Scheduling mode, one of BCM_COSQ_xxx
   1929  *      weights - Weights for each COS queue
   1930  *                Only for BCM_COSQ_WEIGHTED_FAIR_ROUND_ROBIN mode.
   1931  *                For DRR Weight is specified in Kbytes
   1932  *      delay - This parameter is not used 
   1933  * Returns:
   1934  *      BCM_E_XXX
   1935  */
   1936 
   1937 int
   1938 bcm_tr2_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
   1939                            int mode, const int weights[], int delay)
   1940 {
   1941     bcm_port_t port;
   1942     int        i, max_weight;
   1943 
   1944     mbcm_driver[unit]->mbcm_cosq_sched_weight_max_get(unit, mode, &max_weight);
   1945     if((mode != BCM_COSQ_STRICT) && (mode != BCM_COSQ_ROUND_ROBIN) &&
   1946              (max_weight != BCM_COSQ_WEIGHT_UNLIMITED)) {
   1947         for(i = 0; i < NUM_COS(unit); i++) {
   1948             if((weights[i] < 0) || (weights[i] > max_weight)) {
   1949                 return BCM_E_PARAM;
   1950             }
   1951         }
   1952     }
   1953 
   1954     PBMP_ITER(pbm, port) {
   1955         BCM_IF_ERROR_RETURN
   1956             (_bcm_tr2_cosq_port_sched_set(unit,
   1957                                          ESCONFIGr, COSWEIGHTSr, MINSPCONFIGr,
   1958                                          port, 0, 8, weights, mode));
   1959     }
   1960     return BCM_E_NONE;
   1961 }
   1962 
   1963 /*
   1964  * Function:
   1965  *      bcm_cosq_port_sched_get
   1966  * Purpose:
   1967  *      Retrieve class-of-service policy and corresponding weights and delay
   1968  * Parameters:
   1969  *      unit     - StrataSwitch unit number.
   1970  *      pbm      - port bitmap
   1971  *      mode     - (output) Scheduling mode, one of BCM_COSQ_xxx
   1972  *      weights  - (output) Weights for each COS queue
   1973  *                          Only for BCM_COSQ_WEIGHTED_ROUND_ROBIN and
   1974  *                          BCM_COSQ_DEFICIT_ROUND_ROBIN mode.
   1975  *                 For DRR Weight is specified in Kbytes
   1976  *      delay    - This parameter is not used
   1977  * Returns:
   1978  *      BCM_E_XXX
   1979  * Notes:
   1980  *      Actually just returns data for the first port in the bitmap
   1981  */
   1982 
   1983 int
   1984 bcm_tr2_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
   1985                            int *mode, int weights[], int *delay)
   1986 {
   1987     bcm_port_t port;
   1988 
   1989     PBMP_ITER(pbm, port) {
   1990         BCM_IF_ERROR_RETURN
   1991             (_bcm_tr2_cosq_port_sched_get(unit, ESCONFIGr, COSWEIGHTSr,
   1992                                          port, 0, 8, weights, mode));
   1993         break;
   1994     }
   1995     return BCM_E_NONE;
   1996 }
   1997 
   1998 /*
   1999  * Function:
   2000  *      bcm_cosq_gport_add
   2001  * Purpose:
   2002  *
   2003  * Parameters:
   2004  *      unit - (IN) Unit number.
   2005  *      port - (IN) Physical port.
   2006  *      numq - (IN) Number of COS queues.
   2007  *      flags - (IN) Flags.
   2008  *      gport - (IN/OUT) GPORT ID.
   2009  * Returns:
   2010  *      BCM_E_XXX
   2011  */     
   2012 int 
   2013 bcm_tr2_cosq_gport_add(int unit, bcm_gport_t port, int numq,
   2014                       uint32 flags, bcm_gport_t *gport)
   2015 {
   2016     bcm_module_t modid, mod_out;
   2017     bcm_port_t local_port, port_out;
   2018     bcm_trunk_t trunk_id;
   2019     int gport_id;
   2020 
   2021     if ((numq <= 0) || (numq > 16) ||
   2022         (!BCM_GPORT_IS_LOCAL(port) && !BCM_GPORT_IS_MODPORT(port))) {
   2023         return BCM_E_PARAM;
   2024     }
   2025     if (flags & (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_OVERLAY | 
   2026         BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE |
   2027         BCM_COSQ_GPORT_MCAST_QUEUE_GROUP | BCM_COSQ_GPORT_SUBSCRIBER |
   2028         BCM_COSQ_GPORT_EGRESS_GROUP | BCM_COSQ_GPORT_DISABLE |
   2029         BCM_COSQ_GPORT_CALENDAR)) {
   2030         return BCM_E_UNAVAIL;
   2031     }
   2032 
   2033     BCM_IF_ERROR_RETURN
   2034         (_bcm_tr2_cosq_resolve_mod_port(unit, port, &modid,
   2035                                        &local_port, &trunk_id));
   2036 
   2037     /* Verify that the specified port is for my modid and that 
   2038      * it is capable of hierarchical queueing.
   2039      */
   2040         if (!_tr2_num_port_cosq[unit]) {
   2041             return BCM_E_INIT;
   2042         } else if (!SOC_PBMP_MEMBER(_tr2_cosq_24q_ports[unit], local_port)) {
   2043             return BCM_E_PORT;
   2044         } else if (_tr2_num_port_cosq[unit][local_port]) {
   2045             return BCM_E_EXISTS;
   2046         }
   2047         /* Call delete routine to init HW settings */
   2048         BCM_IF_ERROR_RETURN (_bcm_tr2_cosq_gport_delete(unit, local_port));
   2049 
   2050         _tr2_num_port_cosq[unit][local_port] = numq;
   2051 
   2052         /* The GPORT ID for SCHEDULER is the modid/port from application
   2053          * space. This allows the GPORT ID to be used on remote module
   2054          * API calls. Convert from local space to application space.
   2055          */
   2056         BCM_IF_ERROR_RETURN
   2057             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   2058                                     modid, local_port, &mod_out, &port_out));
   2059         gport_id = (mod_out << 8) | port_out;
   2060         BCM_GPORT_SCHEDULER_SET(*gport, gport_id);
   2061     return BCM_E_NONE;
   2062 }
   2063  
   2064 STATIC int
   2065 _bcm_tr2_cosq_gport_delete(int unit, bcm_port_t port)
   2066 {
   2067     int cosq, weights[16];
   2068     uint32 val;
   2069 
   2070     /* Detach from physical port */
   2071     BCM_IF_ERROR_RETURN
   2072         (soc_reg_field32_modify(unit, COS_MODEr, port, SELECTf, 0x0));
   2073     BCM_IF_ERROR_RETURN
   2074         (soc_reg_field32_modify(unit, ING_COS_MODEr, port, SELECTf, 0x0));
   2075 
   2076     /* Clear bandwidth of all Stage1 COSQs */
   2077     for (cosq = 8; cosq < 24; cosq++) {
   2078         BCM_IF_ERROR_RETURN
   2079             (bcm_tr2_cosq_port_bandwidth_set(unit, port, cosq, 0, 0, 0, 0));
   2080     }
   2081 
   2082     /* Clear bandwidth of S1 output queue */
   2083     cosq = 24;
   2084     BCM_IF_ERROR_RETURN
   2085         (bcm_tr2_cosq_port_bandwidth_set(unit, port, cosq, 0, 0, 0, 0));
   2086 
   2087     /* Clear weights of all Stage1 COSQs */
   2088     for (cosq = 0; cosq < 16; cosq++) {
   2089         weights[cosq] = 0;
   2090     }
   2091     BCM_IF_ERROR_RETURN
   2092         (_bcm_tr2_cosq_port_sched_set(unit, S1V_CONFIGr, S1V_COSWEIGHTSr,
   2093                                      S1V_MINSPCONFIGr, port, 0, 16,
   2094                                      weights, BCM_COSQ_WEIGHTED_ROUND_ROBIN));
   2095 
   2096     /* Clear weight for S1 output queue */
   2097     cosq = 8;
   2098     BCM_IF_ERROR_RETURN(READ_COSWEIGHTSr(unit, port, cosq, &val));
   2099     soc_reg_field_set(unit, COSWEIGHTSr, &val, COSWEIGHTSf, 0);
   2100     BCM_IF_ERROR_RETURN(WRITE_COSWEIGHTSr(unit, port, cosq, val));
   2101 
   2102     /* Clear discard settings for all Stage1 COSQs */
   2103     for (cosq = 8; cosq < 24; cosq++) {
   2104         BCM_IF_ERROR_RETURN
   2105             (_bcm_tr2_cosq_discard_set(unit, port, 
   2106                                       BCM_COSQ_DISCARD_COLOR_ALL | 
   2107                                       BCM_COSQ_DISCARD_NONTCP, cosq,
   2108                                       WREDCONFIG_PACKETr,
   2109                                       WREDPARAM_PACKETr,
   2110                                       WREDPARAM_YELLOW_PACKETr,
   2111                                       WREDPARAM_RED_PACKETr,
   2112                                       WREDPARAM_NONTCP_PACKETr,
   2113                                       TR2_PACKET_FIELD_MAX, 
   2114                                       TR2_PACKET_FIELD_MAX, 100, 0));
   2115     }
   2116 
   2117     _tr2_num_port_cosq[unit][port] = 0;
   2118 
   2119     return BCM_E_NONE;
   2120 }
   2121 
   2122 /*      
   2123  * Function:
   2124  *      bcm_cosq_gport_delete
   2125  * Purpose:
   2126  *      
   2127  * Parameters:
   2128  *      unit - (IN) Unit number.
   2129  *      gport - (IN) GPORT ID.
   2130  * Returns:
   2131  *      BCM_E_XXX
   2132  */
   2133 int
   2134 bcm_tr2_cosq_gport_delete(int unit, bcm_gport_t gport)
   2135 {
   2136     bcm_module_t modid;
   2137     bcm_port_t local_port;
   2138     bcm_trunk_t trunk_id;
   2139 
   2140     BCM_IF_ERROR_RETURN
   2141         (_bcm_tr2_cosq_resolve_mod_port(unit, gport, &modid,
   2142                                        &local_port, &trunk_id));
   2143     if (BCM_GPORT_IS_SCHEDULER(gport)) {
   2144         if (!_tr2_num_port_cosq[unit]) {
   2145             return BCM_E_INIT;
   2146         } else if (_tr2_num_port_cosq[unit][local_port] == 0) {
   2147             return BCM_E_NOT_FOUND;
   2148         }
   2149     } else if(BCM_GPORT_IS_LOCAL(gport) ||
   2150                 BCM_GPORT_IS_MODPORT(gport)) {
   2151         if (!_tr2_num_port_cosq[unit]) {
   2152             return BCM_E_INIT;
   2153         }    
   2154     } else {
   2155         return BCM_E_PARAM;
   2156     }
   2157 
   2158     BCM_IF_ERROR_RETURN (_bcm_tr2_cosq_gport_delete(unit, local_port));
   2159     return BCM_E_NONE;
   2160 }
   2161     
   2162 /*
   2163  * Function:
   2164  *      bcm_cosq_gport_traverse
   2165  * Purpose:
   2166  *      Walks through the valid COSQ GPORTs and calls
   2167  *      the user supplied callback function for each entry.
   2168  * Parameters:
   2169  *      unit       - (IN) bcm device.
   2170  *      trav_fn    - (IN) Callback function.
   2171  *      user_data  - (IN) User data to be passed to callback function.
   2172  * Returns:
   2173  *      BCM_E_NONE - Success.
   2174  *      BCM_E_XXX
   2175  */
   2176 int     
   2177 bcm_tr2_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb,
   2178                             void *user_data)
   2179 {
   2180     bcm_module_t my_modid, mod_out;
   2181     bcm_port_t port, port_out;
   2182     bcm_gport_t gport, sched_gport;
   2183     int gport_id;
   2184     uint32 flags = BCM_COSQ_GPORT_SCHEDULER;
   2185     int rv = SOC_E_NONE;
   2186 
   2187     if (_tr2_num_port_cosq[unit]) {
   2188         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   2189         BCM_PBMP_ITER(_tr2_cosq_24q_ports[unit], port) {
   2190             if (_tr2_num_port_cosq[unit][port]) {
   2191 
   2192                 /* Construct physical port GPORT ID */
   2193                 BCM_IF_ERROR_RETURN
   2194                     (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   2195                                             my_modid, port, &mod_out, &port_out));
   2196                 BCM_GPORT_MODPORT_SET(gport, mod_out, port_out);
   2197 
   2198                 /* Construct scheduler GPORT ID */
   2199                 gport_id = (mod_out << 8) | port_out;
   2200                 BCM_GPORT_SCHEDULER_SET(sched_gport, gport_id);
   2201 
   2202                 /* Call application call-back */
   2203                 rv = cb(unit, gport, _tr2_num_port_cosq[unit][port],
   2204                         flags, sched_gport, user_data);
   2205                 if (BCM_FAILURE(rv)) {
   2206 #ifdef BCM_CB_ABORT_ON_ERR
   2207                     if (SOC_CB_ABORT_ON_ERR(unit)) {
   2208                         return rv;
   2209                     }
   2210 #endif
   2211                 }
   2212             }
   2213         } 
   2214     } else {
   2215         return BCM_E_INIT;
   2216     }
   2217     return BCM_E_NONE;
   2218 }
   2219 
   2220 STATIC int
   2221 _bcm_tr2_cosq_gport_bandwidth_port_resolve(int unit, bcm_gport_t gport,
   2222                                            bcm_cos_queue_t cosq,
   2223                                            bcm_port_t *local_port,
   2224                                            bcm_cos_queue_t *cosq_start,
   2225                                            bcm_cos_queue_t *cosq_end)
   2226 {
   2227     bcm_module_t modid;
   2228     bcm_trunk_t trunk_id;
   2229 
   2230     if (BCM_GPORT_IS_SET(gport)) {
   2231         BCM_IF_ERROR_RETURN
   2232             (_bcm_tr2_cosq_resolve_mod_port(unit, gport, &modid,
   2233                                             local_port, &trunk_id));
   2234     } else {
   2235         if (!SOC_PORT_VALID(unit, gport)) {
   2236             return BCM_E_PORT;
   2237         }
   2238         *local_port = gport;
   2239     }
   2240 
   2241     if (!_tr2_num_port_cosq[unit]) {
   2242         return BCM_E_INIT;
   2243     }
   2244 
   2245     if (BCM_GPORT_IS_SCHEDULER(gport)) {
   2246         if (_tr2_num_port_cosq[unit][*local_port] == 0) {
   2247             return BCM_E_NOT_FOUND;
   2248         } else if (cosq < 0) {
   2249             *cosq_start = 8;
   2250             *cosq_end = 23;
   2251         } else if (cosq >= _tr2_num_port_cosq[unit][*local_port]) {
   2252             return BCM_E_PARAM;
   2253         } else {
   2254             *cosq_start = *cosq_end = (cosq + 8);
   2255         }
   2256     } else if (cosq == TR2_SCHEDULER_COSQ) {
   2257         if (!SOC_PBMP_MEMBER(_tr2_cosq_24q_ports[unit], *local_port)) {
   2258             return BCM_E_PORT;
   2259         }
   2260         /* Output of S1 scheduler is configured using register offset 24 */
   2261         *cosq_start = *cosq_end = 24;
   2262     } else {
   2263         if (IS_CPU_PORT(unit, *local_port)) {
   2264             if (cosq >=  NUM_CPU_COSQ(unit)) {
   2265                 return BCM_E_PARAM;
   2266             } else if (cosq < 0) {
   2267                 *cosq_start = 0;
   2268                 *cosq_end =  NUM_CPU_COSQ(unit) - 1 ; 
   2269             } else {
   2270                 *cosq_start = *cosq_end = cosq;
   2271             }
   2272         } else {
   2273             if (cosq >= _tr2_num_cosq[unit]) {
   2274                 return BCM_E_PARAM;
   2275             } else if (cosq < 0) {
   2276                 *cosq_start = 0;
   2277                 *cosq_end = 7;
   2278             } else {
   2279                 *cosq_start = *cosq_end = cosq;
   2280             }
   2281         }
   2282     }
   2283     return BCM_E_NONE;
   2284 }
   2285 
   2286 /*  
   2287  * Function:
   2288  *      bcm_cosq_gport_bandwidth_set
   2289  * Purpose:
   2290  *       
   2291  * Parameters:
   2292  *      unit - (IN) Unit number.
   2293  *      gport - (IN) GPORT ID.
   2294  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   2295  *      kbits_sec_min - (IN) minimum bandwidth, kbits/sec.
   2296  *      kbits_sec_max - (IN) maximum bandwidth, kbits/sec.
   2297  *      flags - (IN) BCM_COSQ_BW_*
   2298  * Returns:
   2299  *      BCM_E_XXX 
   2300  */ 
   2301 int
   2302 bcm_tr2_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
   2303                                 bcm_cos_queue_t cosq, uint32 kbits_sec_min,
   2304                                 uint32 kbits_sec_max, uint32 flags)
   2305 {
   2306     bcm_port_t local_port;
   2307     int i;
   2308     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
   2309 
   2310     BCM_IF_ERROR_RETURN
   2311         (_bcm_tr2_cosq_gport_bandwidth_port_resolve(unit, gport, cosq,
   2312                                                     &local_port,
   2313                                                     &cosq_start, &cosq_end));
   2314 
   2315     flags &= ~_BCM_XGS_METER_FLAG_PACKET_MODE;
   2316     for (i = cosq_start; i <= cosq_end; i++) {
   2317         BCM_IF_ERROR_RETURN
   2318             (bcm_tr2_cosq_port_bandwidth_set(unit, local_port, i,
   2319                                              kbits_sec_min,
   2320                                              kbits_sec_max,
   2321                                              kbits_sec_max,
   2322                                              flags));
   2323     }
   2324     return BCM_E_NONE;
   2325 }
   2326 
   2327 /*
   2328  * Function:
   2329  *      bcm_cosq_gport_bandwidth_get
   2330  * Purpose:
   2331  *
   2332  * Parameters:
   2333  *      unit - (IN) Unit number.
   2334  *      gport - (IN) GPORT ID.
   2335  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   2336  *      kbits_sec_min - (OUT) minimum bandwidth, kbits/sec.
   2337  *      kbits_sec_max - (OUT) maximum bandwidth, kbits/sec.
   2338  *      flags - (OUT) BCM_COSQ_BW_*
   2339  * Returns:
   2340  *      BCM_E_XXX
   2341  */
   2342 int
   2343 bcm_tr2_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
   2344                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
   2345                                 uint32 *kbits_sec_max, uint32 *flags)
   2346 {
   2347     bcm_port_t local_port;
   2348     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
   2349     uint32 kbits_sec_burst;    /* Dummy variable */
   2350 
   2351     BCM_IF_ERROR_RETURN
   2352         (_bcm_tr2_cosq_gport_bandwidth_port_resolve(unit, gport, cosq,
   2353                                                     &local_port,
   2354                                                     &cosq_start, &cosq_end));
   2355     *kbits_sec_min = *kbits_sec_max = *flags = 0;
   2356 
   2357     BCM_IF_ERROR_RETURN
   2358         (bcm_tr2_cosq_port_bandwidth_get(unit, local_port, cosq_start,
   2359                                          kbits_sec_min, kbits_sec_max,
   2360                                          &kbits_sec_burst, flags));
   2361     return BCM_E_NONE;
   2362 }
   2363 
   2364 /*  
   2365  * Function:
   2366  *      bcm_tr2_cosq_gport_bandwidth_burst_set
   2367  * Purpose:
   2368  *       
   2369  * Parameters:
   2370  *      unit - (IN) Unit number.
   2371  *      gport - (IN) GPORT ID.
   2372  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   2373  *      kbits_burst_min - (IN) minimum burst, kbits.
   2374  *      kbits_burst_max - (IN) maximum burst, kbits.
   2375  * Returns:
   2376  *      BCM_E_XXX 
   2377  */ 
   2378 int
   2379 bcm_tr2_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport,
   2380                                        bcm_cos_queue_t cosq,
   2381                                        uint32 kbits_burst_min,
   2382                                        uint32 kbits_burst_max)
   2383 {
   2384     bcm_port_t local_port, port;
   2385     int i;
   2386     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
   2387     uint32 kbits_sec_min, kbits_sec_max, flags = 0;
   2388     uint32 kbits_sec_burst; /* Dummy variable */
   2389 
   2390     if (gport < 0) {
   2391         PBMP_ALL_ITER(unit, port) {
   2392             BCM_IF_ERROR_RETURN
   2393                 (_bcm_tr2_cosq_gport_bandwidth_port_resolve(unit, port, cosq,
   2394                                                            &local_port,
   2395                                                            &cosq_start, &cosq_end));
   2396             for (i = cosq_start; i <= cosq_end; i++) {
   2397                 BCM_IF_ERROR_RETURN
   2398                     (_bcm_tr2_cosq_bucket_get(unit, local_port, i,
   2399                                               &kbits_sec_min, &kbits_sec_max,
   2400                                               &kbits_sec_burst, &kbits_sec_burst,
   2401                                               &flags));
   2402                 BCM_IF_ERROR_RETURN
   2403                     (_bcm_tr2_cosq_bucket_set(unit, local_port, i,
   2404                                                     kbits_sec_min,
   2405                                                     kbits_sec_max,
   2406                                                     kbits_burst_min,
   2407                                                     kbits_burst_max,
   2408                                                     flags));
   2409             }
   2410         }
   2411         return BCM_E_NONE;
   2412     }
   2413 
   2414     BCM_IF_ERROR_RETURN
   2415         (_bcm_tr2_cosq_gport_bandwidth_port_resolve(unit, gport, cosq,
   2416                                                     &local_port,
   2417                                                    &cosq_start, &cosq_end));
   2418 
   2419     for (i = cosq_start; i <= cosq_end; i++) {
   2420         BCM_IF_ERROR_RETURN
   2421             (_bcm_tr2_cosq_bucket_get(unit, local_port, i,
   2422                                       &kbits_sec_min, &kbits_sec_max,
   2423                                       &kbits_sec_burst, &kbits_sec_burst, &flags));
   2424         BCM_IF_ERROR_RETURN
   2425             (_bcm_tr2_cosq_bucket_set(unit, local_port, i,
   2426                                       kbits_sec_min,
   2427                                       kbits_sec_max,
   2428                                       kbits_burst_min,
   2429                                       kbits_burst_max,
   2430                                       flags));
   2431     }
   2432     return BCM_E_NONE;
   2433 }
   2434 
   2435 /*
   2436  * Function:
   2437  *      bcm_tr2_cosq_gport_bandwidth_burst_get
   2438  * Purpose:
   2439  *
   2440  * Parameters:
   2441  *      unit - (IN) Unit number.
   2442  *      gport - (IN) GPORT ID.
   2443  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   2444  *      kbits_burst_min - (OUT) minimum burst, kbits.
   2445  *      kbits_burst_max - (OUT) maximum burst, kbits.
   2446  * Returns:
   2447  *      BCM_E_XXX
   2448  */
   2449 int
   2450 bcm_tr2_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport,
   2451                                        bcm_cos_queue_t cosq,
   2452                                        uint32 *kbits_burst_min,
   2453                                        uint32 *kbits_burst_max)
   2454 {
   2455     bcm_port_t local_port, port;
   2456     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
   2457     uint32 kbits_sec_min, kbits_sec_max, flags;    /* Dummy variables */
   2458 
   2459     if (gport < 0) {
   2460         port = SOC_PORT_MIN(unit,all);
   2461 
   2462         BCM_IF_ERROR_RETURN
   2463             (_bcm_tr2_cosq_gport_bandwidth_port_resolve(unit, port, cosq,
   2464                                                        &local_port,
   2465                                                        &cosq_start, &cosq_end));
   2466     } else {
   2467         BCM_IF_ERROR_RETURN
   2468             (_bcm_tr2_cosq_gport_bandwidth_port_resolve(unit, gport, cosq,
   2469                                                        &local_port,
   2470                                                        &cosq_start, &cosq_end));
   2471     }
   2472 
   2473     kbits_sec_min = kbits_sec_max = flags = 0;
   2474 
   2475     BCM_IF_ERROR_RETURN
   2476         (_bcm_tr2_cosq_bucket_get(unit, local_port, cosq_start,
   2477                                   &kbits_sec_min, &kbits_sec_max,
   2478                                   kbits_burst_min, kbits_burst_max, &flags));
   2479     return BCM_E_NONE;
   2480 }
   2481 
   2482 /*
   2483  * Function:
   2484  *      bcm_cosq_gport_sched_set
   2485  * Purpose:
   2486  *
   2487  * Parameters:
   2488  *      unit - (IN) Unit number.
   2489  *      gport - (IN) GPORT ID.
   2490  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   2491  *      mode - (IN) Scheduling mode, one of BCM_COSQ_xxx
   2492  *      weight - (IN) Weight for the specified COS queue(s)
   2493  *               Unused if mode is BCM_COSQ_STRICT.
   2494  * Returns:
   2495  *      BCM_E_XXX
   2496  */
   2497 int
   2498 bcm_tr2_cosq_gport_sched_set(int unit, bcm_gport_t gport,
   2499                             bcm_cos_queue_t cosq, int mode, int weight)
   2500 {
   2501     bcm_module_t modid;
   2502     bcm_port_t local_port;
   2503     bcm_trunk_t trunk_id;
   2504     int i;
   2505     bcm_cos_queue_t cosq_start = 0;
   2506     int num_weights = 1, weights[16];
   2507     soc_reg_t config_reg = ESCONFIGr;
   2508     soc_reg_t weight_reg = COSWEIGHTSr;
   2509     soc_reg_t minsp_reg = MINSPCONFIGr;
   2510 
   2511     BCM_IF_ERROR_RETURN
   2512         (_bcm_tr2_cosq_resolve_mod_port(unit, gport, &modid,
   2513                                        &local_port, &trunk_id));
   2514 
   2515         if (!_tr2_num_port_cosq[unit]) {
   2516             return BCM_E_INIT;
   2517         }
   2518         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   2519             if (_tr2_num_port_cosq[unit][local_port] == 0) {
   2520                 return BCM_E_NOT_FOUND;
   2521             } else if (cosq >= _tr2_num_port_cosq[unit][local_port]) {
   2522                 return BCM_E_PARAM;
   2523             } else if (cosq < 0) {
   2524                 cosq_start = 0;
   2525                 num_weights = 16;
   2526                 for (i = 0; i < num_weights; i++) {
   2527                     if (i < _tr2_num_port_cosq[unit][local_port]) {
   2528                         weights[i] = weight;
   2529                     } else {
   2530                         weights[i] = 0;
   2531                     }
   2532                 }
   2533             } else {
   2534                 cosq_start = cosq;
   2535                 num_weights = 1;
   2536                 weights[0] = weight;
   2537             }
   2538             config_reg = S1V_CONFIGr;
   2539             weight_reg = S1V_COSWEIGHTSr;
   2540             minsp_reg = S1V_MINSPCONFIGr;
   2541         } else if (cosq == TR2_SCHEDULER_COSQ) {
   2542             if (!SOC_PBMP_MEMBER(_tr2_cosq_24q_ports[unit], local_port)) {
   2543                 return BCM_E_PORT;
   2544             }
   2545             /* Weight for output of S1 scheduler is configured using offset 8 
   2546              * of COSWEIGHTS register.
   2547              */
   2548             cosq_start = 8;
   2549             num_weights = 1;
   2550             weights[0] = weight;
   2551         } else {
   2552             if (cosq >= _tr2_num_cosq[unit]) {
   2553                 return BCM_E_PARAM;
   2554             } else if (cosq < 0) {
   2555                 cosq_start = 0;
   2556                 num_weights = 8;
   2557                 for (i = 0; i < num_weights; i++) {
   2558                     if (i < _tr2_num_cosq[unit]) {
   2559                         weights[i] = weight;
   2560                     } else {
   2561                         weights[i] = 0;
   2562                     }
   2563                 }
   2564             } else {
   2565                 cosq_start = cosq;
   2566                 num_weights = 1;
   2567                 weights[0] = weight;
   2568             }
   2569         }
   2570 
   2571         BCM_IF_ERROR_RETURN
   2572             (_bcm_tr2_cosq_port_sched_set(unit, config_reg, weight_reg, minsp_reg,
   2573                                          local_port, cosq_start, num_weights,
   2574                                          weights, mode));
   2575     return BCM_E_NONE;
   2576 }
   2577 
   2578 /*
   2579  * Function:
   2580  *      bcm_cosq_gport_sched_get
   2581  * Purpose:
   2582  *
   2583  * Parameters:
   2584  *      unit - (IN) Unit number.
   2585  *      gport - (IN) GPORT ID.
   2586  *      cosq - (IN) COS queue
   2587  *      mode - (OUT) Scheduling mode, one of BCM_COSQ_xxx
   2588  *      weight - (OUT) Weight for the specified COS queue(s)
   2589  *               Unused if mode is BCM_COSQ_STRICT.
   2590  * Returns:
   2591  *      BCM_E_XXX
   2592  */
   2593 int
   2594 bcm_tr2_cosq_gport_sched_get(int unit, bcm_gport_t gport, 
   2595                             bcm_cos_queue_t cosq, int *mode, int *weight)
   2596 {   
   2597     bcm_module_t modid;
   2598     bcm_port_t local_port;
   2599     bcm_trunk_t trunk_id;
   2600     soc_reg_t config_reg = ESCONFIGr;
   2601     soc_reg_t weight_reg = COSWEIGHTSr;
   2602 
   2603     *mode = *weight = 0;
   2604 
   2605     BCM_IF_ERROR_RETURN
   2606         (_bcm_tr2_cosq_resolve_mod_port(unit, gport, &modid,
   2607                                        &local_port, &trunk_id));
   2608         if (!_tr2_num_port_cosq[unit]) {
   2609             return BCM_E_INIT;
   2610         }
   2611         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   2612             if (_tr2_num_port_cosq[unit][local_port] == 0) {
   2613                 return BCM_E_NOT_FOUND;
   2614             } else if (cosq >= _tr2_num_port_cosq[unit][local_port]) {
   2615                 return BCM_E_PARAM;
   2616             } else if (cosq < 0) {
   2617                 cosq = 0;
   2618             }
   2619             config_reg = S1V_CONFIGr;
   2620             weight_reg = S1V_COSWEIGHTSr;
   2621         } else if (cosq == TR2_SCHEDULER_COSQ) {
   2622             if (!SOC_PBMP_MEMBER(_tr2_cosq_24q_ports[unit], local_port)) {
   2623                 return BCM_E_PORT;
   2624             }
   2625             /* Weight for output of S1 scheduler is configured using offset 8 
   2626              * of COSWEIGHTS register.
   2627              */
   2628             cosq = 8;
   2629         } else {
   2630             if (cosq >= _tr2_num_cosq[unit]) {
   2631                 return BCM_E_PARAM;
   2632             } else if (cosq < 0) {
   2633                 cosq = 0;
   2634             }
   2635         }
   2636         BCM_IF_ERROR_RETURN
   2637             (_bcm_tr2_cosq_port_sched_get(unit, config_reg, weight_reg, 
   2638                                          local_port, cosq, 1,
   2639                                          weight, mode));
   2640     return BCM_E_NONE;
   2641 }
   2642 
   2643 /*
   2644  * Function:
   2645  *      bcm_cosq_gport_discard_set
   2646  * Purpose:
   2647  *
   2648  * Parameters:
   2649  *      unit    - (IN) Unit number.
   2650  *      port    - (IN) GPORT ID.
   2651  *      cosq    - (IN) COS queue to configure
   2652  *      discard - (IN) Discard settings
   2653  * Returns:
   2654  *      BCM_E_XXX
   2655  */
   2656 int
   2657 bcm_tr2_cosq_gport_discard_set(int unit, bcm_gport_t port,
   2658                                bcm_cos_queue_t cosq,
   2659                                bcm_cosq_gport_discard_t *discard)
   2660 {
   2661     bcm_module_t modid;
   2662     bcm_port_t local_port;
   2663     bcm_trunk_t trunk_id;
   2664     uint32 min_thresh, max_thresh;
   2665     int cell_size, cell_field_max;
   2666 
   2667     if ((discard == NULL) || 
   2668         (discard->gain < 0) || (discard->gain > 15) ||
   2669         (discard->drop_probability < 0) || (discard->drop_probability > 100)) {
   2670         return BCM_E_PARAM;
   2671     }
   2672 
   2673     cell_size      = _BCM_TR2_COSQ_CELLSIZE;
   2674     cell_field_max = TR2_CELL_FIELD_MAX;
   2675 
   2676     min_thresh = discard->min_thresh;
   2677     max_thresh = discard->max_thresh;
   2678     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   2679         /* Convert bytes to cells */
   2680         min_thresh += (cell_size - 1);
   2681         min_thresh /= cell_size;
   2682 
   2683         max_thresh += (cell_size - 1);
   2684         max_thresh /= cell_size;
   2685 
   2686         if ((min_thresh > cell_field_max) || 
   2687             (max_thresh > cell_field_max)) {
   2688             return BCM_E_PARAM;
   2689         }
   2690     } else { /* BCM_COSQ_DISCARD_PACKETS */
   2691         if ((min_thresh > TR2_PACKET_FIELD_MAX) || 
   2692             (max_thresh > TR2_PACKET_FIELD_MAX)) {
   2693             return BCM_E_PARAM;
   2694         }
   2695     }
   2696 
   2697     if (port != BCM_GPORT_INVALID) {
   2698         BCM_IF_ERROR_RETURN
   2699             (_bcm_tr2_cosq_resolve_mod_port(unit, port, &modid,
   2700                                            &local_port, &trunk_id));
   2701         if (cosq < 0) {
   2702             /* per-port discard settings */
   2703             if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   2704                 BCM_IF_ERROR_RETURN
   2705                     (_bcm_tr2_cosq_discard_set(unit, local_port,
   2706                                               discard->flags, 0,
   2707                                               PORT_WREDCONFIG_CELLr,
   2708                                               PORT_WREDPARAM_CELLr,
   2709                                               PORT_WREDPARAM_YELLOW_CELLr,
   2710                                               PORT_WREDPARAM_RED_CELLr,
   2711                                               PORT_WREDPARAM_NONTCP_CELLr,
   2712                                               min_thresh, max_thresh, 
   2713                                               discard->drop_probability,
   2714                                               discard->gain));
   2715                 BCM_IF_ERROR_RETURN
   2716                     (_bcm_tr2_cosq_discard_cap_enable_set(unit, local_port, 0,
   2717                                                          PORT_WREDCONFIG_CELLr, 
   2718                                                          discard->flags));
   2719 
   2720             } else { /* BCM_COSQ_DISCARD_PACKETS */
   2721                 BCM_IF_ERROR_RETURN
   2722                     (_bcm_tr2_cosq_discard_set(unit, local_port,
   2723                                               discard->flags, 0,
   2724                                               PORT_WREDCONFIG_PACKETr,
   2725                                               PORT_WREDPARAM_PACKETr,
   2726                                               PORT_WREDPARAM_YELLOW_PACKETr,
   2727                                               PORT_WREDPARAM_RED_PACKETr,
   2728                                               PORT_WREDPARAM_NONTCP_PACKETr,
   2729                                               min_thresh, max_thresh, 
   2730                                               discard->drop_probability,
   2731                                               discard->gain));
   2732                 BCM_IF_ERROR_RETURN
   2733                     (_bcm_tr2_cosq_discard_cap_enable_set(unit, local_port, 0,
   2734                                                          PORT_WREDCONFIG_PACKETr, 
   2735                                                          discard->flags));
   2736             }
   2737         } else {
   2738             /* per-port/per-cos discard settings */
   2739             if (BCM_GPORT_IS_SCHEDULER(port)) {
   2740                 if (_tr2_num_port_cosq[unit][local_port] == 0) {
   2741                     return BCM_E_NOT_FOUND;
   2742                 } else if (cosq >= _tr2_num_port_cosq[unit][local_port]) {
   2743                     return BCM_E_PARAM;
   2744                 } else {
   2745                     cosq = cosq + 8;
   2746                 }
   2747             } else if (cosq >= _tr2_num_cosq[unit]) {
   2748                 return BCM_E_PARAM;
   2749             }
   2750 
   2751             if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   2752                 BCM_IF_ERROR_RETURN
   2753                     (_bcm_tr2_cosq_discard_set(unit, local_port,
   2754                                               discard->flags, cosq,
   2755                                               WREDCONFIG_CELLr,
   2756                                               WREDPARAM_CELLr,
   2757                                               WREDPARAM_YELLOW_CELLr,
   2758                                               WREDPARAM_RED_CELLr,
   2759                                               WREDPARAM_NONTCP_CELLr,
   2760                                               min_thresh, max_thresh, 
   2761                                               discard->drop_probability,
   2762                                               discard->gain));
   2763                 BCM_IF_ERROR_RETURN
   2764                     (_bcm_tr2_cosq_discard_cap_enable_set(unit, local_port, cosq,
   2765                                                          WREDCONFIG_CELLr, 
   2766                                                          discard->flags));
   2767             } else { /* BCM_COSQ_DISCARD_PACKETS */
   2768                 BCM_IF_ERROR_RETURN
   2769                     (_bcm_tr2_cosq_discard_set(unit, local_port,
   2770                                               discard->flags, cosq,
   2771                                               WREDCONFIG_PACKETr,
   2772                                               WREDPARAM_PACKETr,
   2773                                               WREDPARAM_YELLOW_PACKETr,
   2774                                               WREDPARAM_RED_PACKETr,
   2775                                               WREDPARAM_NONTCP_PACKETr,
   2776                                               min_thresh, max_thresh, 
   2777                                               discard->drop_probability,
   2778                                               discard->gain));
   2779                 BCM_IF_ERROR_RETURN
   2780                     (_bcm_tr2_cosq_discard_cap_enable_set(unit, local_port, cosq,
   2781                                                          WREDCONFIG_PACKETr, 
   2782                                                          discard->flags));
   2783             }
   2784         }
   2785     } else {
   2786         /* chip-wide discard settings */
   2787         if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   2788             BCM_IF_ERROR_RETURN
   2789                 (_bcm_tr2_cosq_discard_set(unit, REG_PORT_ANY, discard->flags,
   2790                                           0, GLOBAL_WREDCONFIG_CELLr,
   2791                                           GLOBAL_WREDPARAM_CELLr,
   2792                                           GLOBAL_WREDPARAM_YELLOW_CELLr,
   2793                                           GLOBAL_WREDPARAM_RED_CELLr,
   2794                                           GLOBAL_WREDPARAM_NONTCP_CELLr,
   2795                                           min_thresh, max_thresh, 
   2796                                           discard->drop_probability,
   2797                                           discard->gain));
   2798             BCM_IF_ERROR_RETURN
   2799                 (_bcm_tr2_cosq_discard_cap_enable_set(unit, REG_PORT_ANY, 0,
   2800                                                      GLOBAL_WREDCONFIG_CELLr, 
   2801                                                      discard->flags));
   2802         } else { /* BCM_COSQ_DISCARD_PACKETS */
   2803             BCM_IF_ERROR_RETURN
   2804                 (_bcm_tr2_cosq_discard_set(unit, REG_PORT_ANY, discard->flags,
   2805                                           0, GLOBAL_WREDCONFIG_PACKETr,
   2806                                           GLOBAL_WREDPARAM_PACKETr,
   2807                                           GLOBAL_WREDPARAM_YELLOW_PACKETr,
   2808                                           GLOBAL_WREDPARAM_RED_PACKETr,
   2809                                           GLOBAL_WREDPARAM_NONTCP_PACKETr,
   2810                                           min_thresh, max_thresh, 
   2811                                           discard->drop_probability,
   2812                                           discard->gain));
   2813             BCM_IF_ERROR_RETURN
   2814                 (_bcm_tr2_cosq_discard_cap_enable_set(unit, REG_PORT_ANY, 0,
   2815                                                      GLOBAL_WREDCONFIG_PACKETr, 
   2816                                                      discard->flags));
   2817         }
   2818     }
   2819     return BCM_E_NONE;
   2820 }
   2821 
   2822 /*
   2823  * Function:
   2824  *      bcm_cosq_gport_discard_get
   2825  * Purpose:
   2826  *
   2827  * Parameters:
   2828  *      unit    - (IN) Unit number.
   2829  *      port    - (IN) GPORT ID.
   2830  *      cosq    - (IN) COS queue to get
   2831  *      discard - (IN/OUT) Discard settings
   2832  * Returns:
   2833  *      BCM_E_XXX
   2834  */
   2835 int
   2836 bcm_tr2_cosq_gport_discard_get(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   2837                               bcm_cosq_gport_discard_t *discard)
   2838 {
   2839     bcm_module_t modid;
   2840     bcm_port_t local_port;
   2841     bcm_trunk_t trunk_id;
   2842     uint32 min_thresh, max_thresh;
   2843 
   2844     if (discard == NULL) {
   2845         return BCM_E_PARAM;
   2846     }
   2847 
   2848     if (port != BCM_GPORT_INVALID) {
   2849         BCM_IF_ERROR_RETURN
   2850             (_bcm_tr2_cosq_resolve_mod_port(unit, port, &modid,
   2851                                            &local_port, &trunk_id));
   2852         if (cosq < 0) {
   2853             /* per-port discard settings */
   2854             if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   2855                 BCM_IF_ERROR_RETURN
   2856                     (_bcm_tr2_cosq_discard_get(unit, local_port,
   2857                                               discard->flags, 0,
   2858                                               PORT_WREDCONFIG_CELLr,
   2859                                               PORT_WREDPARAM_CELLr,
   2860                                               PORT_WREDPARAM_YELLOW_CELLr,
   2861                                               PORT_WREDPARAM_RED_CELLr,
   2862                                               PORT_WREDPARAM_NONTCP_CELLr,
   2863                                               &min_thresh, &max_thresh, 
   2864                                               &discard->drop_probability,
   2865                                               &discard->gain));
   2866                 BCM_IF_ERROR_RETURN
   2867                     (_bcm_tr2_cosq_discard_cap_enable_get(unit, local_port, 0,
   2868                                                          PORT_WREDCONFIG_CELLr, 
   2869                                                          &discard->flags));
   2870             } else { /* BCM_COSQ_DISCARD_PACKETS */
   2871                 BCM_IF_ERROR_RETURN
   2872                     (_bcm_tr2_cosq_discard_get(unit, local_port,
   2873                                               discard->flags, 0,
   2874                                               PORT_WREDCONFIG_PACKETr,
   2875                                               PORT_WREDPARAM_PACKETr,
   2876                                               PORT_WREDPARAM_YELLOW_PACKETr,
   2877                                               PORT_WREDPARAM_RED_PACKETr,
   2878                                               PORT_WREDPARAM_NONTCP_PACKETr,
   2879                                               &min_thresh, &max_thresh, 
   2880                                               &discard->drop_probability,
   2881                                               &discard->gain));
   2882                 BCM_IF_ERROR_RETURN
   2883                     (_bcm_tr2_cosq_discard_cap_enable_get(unit, local_port, 0,
   2884                                                          PORT_WREDCONFIG_PACKETr, 
   2885                                                          &discard->flags));
   2886             }
   2887         } else {
   2888             /* per-port/per-cos discard settings */
   2889             if (BCM_GPORT_IS_SCHEDULER(port)) {
   2890                 if (_tr2_num_port_cosq[unit][local_port] == 0) {
   2891                     return BCM_E_NOT_FOUND;
   2892                 } else if (cosq >= _tr2_num_port_cosq[unit][local_port]) {
   2893                     return BCM_E_PARAM;
   2894                 } else {
   2895                     cosq = cosq + 8;
   2896                 }
   2897             } else if (cosq >= _tr2_num_cosq[unit]) {
   2898                 return BCM_E_PARAM;
   2899             }
   2900 
   2901             if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   2902                 BCM_IF_ERROR_RETURN
   2903                     (_bcm_tr2_cosq_discard_get(unit, local_port,
   2904                                               discard->flags, cosq,
   2905                                               WREDCONFIG_CELLr,
   2906                                               WREDPARAM_CELLr,
   2907                                               WREDPARAM_YELLOW_CELLr,
   2908                                               WREDPARAM_RED_CELLr,
   2909                                               WREDPARAM_NONTCP_CELLr,
   2910                                               &min_thresh, &max_thresh, 
   2911                                               &discard->drop_probability,
   2912                                               &discard->gain));
   2913                 BCM_IF_ERROR_RETURN
   2914                     (_bcm_tr2_cosq_discard_cap_enable_get(unit, local_port, cosq,
   2915                                                          WREDCONFIG_CELLr, 
   2916                                                          &discard->flags));
   2917             } else { /* BCM_COSQ_DISCARD_PACKETS */
   2918                 BCM_IF_ERROR_RETURN
   2919                     (_bcm_tr2_cosq_discard_get(unit, local_port,
   2920                                               discard->flags, cosq,
   2921                                               WREDCONFIG_PACKETr,
   2922                                               WREDPARAM_PACKETr,
   2923                                               WREDPARAM_YELLOW_PACKETr,
   2924                                               WREDPARAM_RED_PACKETr,
   2925                                               WREDPARAM_NONTCP_PACKETr,
   2926                                               &min_thresh, &max_thresh, 
   2927                                               &discard->drop_probability,
   2928                                               &discard->gain));
   2929                 BCM_IF_ERROR_RETURN
   2930                     (_bcm_tr2_cosq_discard_cap_enable_get(unit, local_port, cosq,
   2931                                                          WREDCONFIG_PACKETr, 
   2932                                                          &discard->flags));
   2933             }
   2934         }
   2935     } else {
   2936         /* chip-wide discard settings */
   2937         if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   2938             BCM_IF_ERROR_RETURN
   2939                 (_bcm_tr2_cosq_discard_get(unit, REG_PORT_ANY, discard->flags,
   2940                                           0, GLOBAL_WREDCONFIG_CELLr,
   2941                                           GLOBAL_WREDPARAM_CELLr,
   2942                                           GLOBAL_WREDPARAM_YELLOW_CELLr,
   2943                                           GLOBAL_WREDPARAM_RED_CELLr,
   2944                                           GLOBAL_WREDPARAM_NONTCP_CELLr,
   2945                                           &min_thresh, &max_thresh, 
   2946                                           &discard->drop_probability,
   2947                                           &discard->gain));
   2948             BCM_IF_ERROR_RETURN
   2949                 (_bcm_tr2_cosq_discard_cap_enable_get(unit, REG_PORT_ANY, 0,
   2950                                                      GLOBAL_WREDCONFIG_CELLr, 
   2951                                                      &discard->flags));
   2952         } else { /* BCM_COSQ_DISCARD_PACKETS */
   2953             BCM_IF_ERROR_RETURN
   2954                 (_bcm_tr2_cosq_discard_get(unit, REG_PORT_ANY, discard->flags,
   2955                                           0, GLOBAL_WREDCONFIG_PACKETr,
   2956                                           GLOBAL_WREDPARAM_PACKETr,
   2957                                           GLOBAL_WREDPARAM_YELLOW_PACKETr,
   2958                                           GLOBAL_WREDPARAM_RED_PACKETr,
   2959                                           GLOBAL_WREDPARAM_NONTCP_PACKETr,
   2960                                           &min_thresh, &max_thresh, 
   2961                                           &discard->drop_probability,
   2962                                           &discard->gain));
   2963             BCM_IF_ERROR_RETURN
   2964                 (_bcm_tr2_cosq_discard_cap_enable_get(unit, REG_PORT_ANY, 0,
   2965                                                      GLOBAL_WREDCONFIG_PACKETr, 
   2966                                                      &discard->flags));
   2967         }
   2968     }
   2969 
   2970     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   2971         /* Convert cells to bytes */
   2972         min_thresh *= _BCM_TR2_COSQ_CELLSIZE;
   2973         max_thresh *= _BCM_TR2_COSQ_CELLSIZE;
   2974     }
   2975     discard->min_thresh = min_thresh;
   2976     discard->max_thresh = max_thresh;
   2977 
   2978     return BCM_E_NONE;
   2979 }
   2980 
   2981 /* 
   2982  * Function:
   2983  *      bcm_cosq_gport_attach
   2984  * Purpose:
   2985  *      
   2986  * Parameters: 
   2987  *      unit       - (IN) Unit number.
   2988  *      sched_port - (IN) Scheduler GPORT ID.
   2989  *      input_port - (IN) GPORT to attach to.
   2990  *      cosq       - (IN) COS queue to attach to.
   2991  * Returns:
   2992  *      BCM_E_XXX
   2993  */
   2994 int
   2995 bcm_tr2_cosq_gport_attach(int unit, bcm_gport_t sched_gport, 
   2996                          bcm_gport_t input_gport, bcm_cos_queue_t cosq)
   2997 {
   2998     bcm_module_t sched_modid, input_modid;
   2999     bcm_port_t sched_port, input_port;
   3000     bcm_trunk_t trunk_id;
   3001 
   3002     if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) {
   3003         return BCM_E_PARAM;
   3004     } else if (!_tr2_num_port_cosq[unit]) {
   3005         return BCM_E_INIT;
   3006     } else if (cosq < 0) {
   3007         cosq = TR2_SCHEDULER_COSQ;
   3008     } else if (cosq != TR2_SCHEDULER_COSQ) {
   3009         return BCM_E_PARAM;
   3010     }
   3011 
   3012     BCM_IF_ERROR_RETURN
   3013         (_bcm_tr2_cosq_resolve_mod_port(unit, sched_gport, &sched_modid,
   3014                                        &sched_port, &trunk_id));
   3015 
   3016         BCM_IF_ERROR_RETURN
   3017             (_bcm_tr2_cosq_resolve_mod_port(unit, input_gport, &input_modid,
   3018                                            &input_port, &trunk_id));
   3019 
   3020         if (_tr2_num_port_cosq[unit][sched_port] == 0) {
   3021             /* GPORT has not been added. */
   3022             return BCM_E_NOT_FOUND;
   3023         } else if ((sched_modid != input_modid) || (sched_port != input_port)) {
   3024             /* Be sure the GPORT matches to the physical port */
   3025             return BCM_E_PARAM;
   3026         }
   3027 
   3028         BCM_IF_ERROR_RETURN
   3029             (soc_reg_field32_modify(unit, ING_COS_MODEr, input_port, 
   3030                                     SELECTf, 0x3)); /* VLAN_COS */
   3031         BCM_IF_ERROR_RETURN
   3032             (soc_reg_field32_modify(unit, COS_MODEr, input_port, 
   3033                                     SELECTf, 0x3)); /* VLAN_COS */
   3034     return BCM_E_NONE;
   3035 }   
   3036 
   3037 /*
   3038  * Function:
   3039  *      bcm_cosq_gport_detach
   3040  * Purpose:
   3041  * 
   3042  * Parameters:
   3043  *      unit       - (IN) Unit number.
   3044  *      sched_port - (IN) Scheduler GPORT ID.
   3045  *      input_port - (IN) GPORT to detach from.
   3046  *      cosq       - (IN) COS queue to detach from.
   3047  * Returns:
   3048  *      BCM_E_XXX
   3049  * Notes:
   3050  */
   3051 int     
   3052 bcm_tr2_cosq_gport_detach(int unit, bcm_gport_t sched_gport,
   3053                          bcm_gport_t input_gport, bcm_cos_queue_t cosq)
   3054 {
   3055     bcm_module_t sched_modid, input_modid;
   3056     bcm_port_t sched_port, input_port;
   3057     bcm_trunk_t trunk_id;
   3058 
   3059     if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) {
   3060         return BCM_E_PORT;
   3061     } else if (!_tr2_num_port_cosq[unit]) {
   3062         return BCM_E_INIT;
   3063     } else if ((cosq > 0) && (cosq != TR2_SCHEDULER_COSQ)) {
   3064         return BCM_E_NOT_FOUND;
   3065     }
   3066 
   3067     BCM_IF_ERROR_RETURN
   3068         (_bcm_tr2_cosq_resolve_mod_port(unit, sched_gport, &sched_modid,
   3069                                        &sched_port, &trunk_id));
   3070        BCM_IF_ERROR_RETURN
   3071            (_bcm_tr2_cosq_resolve_mod_port(unit, input_gport, &input_modid,
   3072                                           &input_port, &trunk_id));
   3073         if (_tr2_num_port_cosq[unit][sched_port] == 0) {
   3074             /* GPORT has not been added. */
   3075             return BCM_E_NOT_FOUND;
   3076         } else if ((sched_modid != input_modid) || (sched_port != input_port)) {
   3077             /* Be sure the GPORT matches to the physical port */
   3078             return BCM_E_PORT;
   3079         }
   3080     
   3081         BCM_IF_ERROR_RETURN
   3082             (soc_reg_field32_modify(unit, COS_MODEr, input_port, SELECTf, 0x0));
   3083         BCM_IF_ERROR_RETURN
   3084             (soc_reg_field32_modify(unit, ING_COS_MODEr, input_port, SELECTf, 0x0));
   3085     return BCM_E_NONE;
   3086 }
   3087 
   3088 /*
   3089  * Function:
   3090  *      bcm_cosq_gport_attach_get
   3091  * Purpose:
   3092  *
   3093  * Parameters:
   3094  *      unit       - (IN) Unit number.
   3095  *      sched_port - (IN) Scheduler GPORT ID.
   3096  *      input_port - (OUT) GPORT attached to.
   3097  *      cosq       - (OUT) COS queue attached to.
   3098  * Returns:
   3099  *      BCM_E_XXX
   3100  * Notes:
   3101  */
   3102 int
   3103 bcm_tr2_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport,
   3104                              bcm_gport_t *input_gport, bcm_cos_queue_t *cosq)
   3105 {
   3106     bcm_module_t sched_modid, input_modid;
   3107     bcm_port_t sched_port, input_port;
   3108     bcm_trunk_t trunk_id;
   3109     uint32 val;
   3110 
   3111     if (!BCM_GPORT_IS_SCHEDULER(sched_gport) ||
   3112         !cosq || !input_gport) {
   3113         return BCM_E_PARAM;
   3114     } else if (!_tr2_num_port_cosq[unit]) {
   3115         return BCM_E_INIT;
   3116     }
   3117 
   3118     BCM_IF_ERROR_RETURN
   3119         (_bcm_tr2_cosq_resolve_mod_port(unit, sched_gport, &sched_modid,
   3120                                        &sched_port, &trunk_id));
   3121         if (_tr2_num_port_cosq[unit][sched_port] == 0) {
   3122             /* GPORT has not been added. */
   3123             return BCM_E_NOT_FOUND;
   3124         }
   3125 
   3126         BCM_IF_ERROR_RETURN(READ_COS_MODEr(unit, sched_port, &val));
   3127         if (soc_reg_field_get(unit, COS_MODEr, val, SELECTf) == 3) {
   3128             /* GPORT has been attached */
   3129             *cosq = TR2_SCHEDULER_COSQ;
   3130 
   3131             BCM_IF_ERROR_RETURN
   3132                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   3133                                         sched_modid, sched_port,
   3134                                         &input_modid, &input_port));
   3135             BCM_GPORT_MODPORT_SET(*input_gport, input_modid, input_port);
   3136         } else {
   3137             /* GPORT has not been attached */
   3138             return BCM_E_NOT_FOUND;
   3139         }
   3140     return BCM_E_NONE;
   3141 }
   3142 
   3143 #ifndef BCM_SW_STATE_DUMP_DISABLE
   3144 /*
   3145  * Function:
   3146  *     bcm_tr2_cosq_sw_dump
   3147  * Purpose:
   3148  *     Displays COS Queue information maintained by software.
   3149  * Parameters:
   3150  *     unit - Device unit number
   3151  * Returns:
   3152  *     None
   3153  */
   3154 void
   3155 bcm_tr2_cosq_sw_dump(int unit)
   3156 {
   3157     int  i;
   3158 
   3159     LOG_CLI((BSL_META_U(unit,
   3160                         "\nSW Information COSQ - Unit %d\n"), unit));
   3161 
   3162     /* Number COSQ */
   3163     LOG_CLI((BSL_META_U(unit,
   3164                         "    Number: %d\n"), _tr2_num_cosq[unit]));
   3165 
   3166     /* Number of COSQs per port */
   3167     LOG_CLI((BSL_META_U(unit,
   3168                         "    Number COSQ per port:\n")));
   3169     if (_tr2_num_port_cosq[unit]) {
   3170         for (i = 0; i < TR2_PORT_COUNT; i++) {
   3171             LOG_CLI((BSL_META_U(unit,
   3172                                 "        Port %2d: %d\n"), i,
   3173                      _tr2_num_port_cosq[unit][i]));
   3174         }
   3175     }
   3176     
   3177     /* COSQ Map profile */
   3178     /* Display those entries with reference count > 0 */
   3179     LOG_CLI((BSL_META_U(unit,
   3180                         "    COSQ Map Profile:\n")));
   3181     if (_tr2_cos_map_profile[unit] != NULL) {
   3182         int     num_entries;
   3183         int     ref_count;
   3184         int     entries_per_set;
   3185         uint32  index;
   3186         uint32  cosq, hg_cosq;
   3187         port_cos_map_entry_t *entry_p;
   3188 
   3189         num_entries = soc_mem_index_count
   3190             (unit, _tr2_cos_map_profile[unit]->tables[0].mem);
   3191         LOG_CLI((BSL_META_U(unit,
   3192                             "        Number of entries: %d\n"), num_entries));
   3193         LOG_CLI((BSL_META_U(unit,
   3194                             "        Index RefCount EntriesPerSet - "
   3195                  "COS HG_COS\n")));
   3196 
   3197         for (index = 0; index < num_entries;
   3198              index += TR2_COS_MAP_ENTRIES_PER_SET) {
   3199             if (SOC_FAILURE
   3200                 (soc_profile_mem_ref_count_get(unit,
   3201                                                _tr2_cos_map_profile[unit],
   3202                                                index, &ref_count))) {
   3203                 break;
   3204             }
   3205 
   3206             if (ref_count <= 0) {
   3207                 continue;
   3208             }
   3209 
   3210             for (i = 0; i < TR2_COS_MAP_ENTRIES_PER_SET; i++) {
   3211                 entries_per_set =
   3212                     _tr2_cos_map_profile[unit]->tables[0].entries[index+i].entries_per_set;
   3213                 LOG_CLI((BSL_META_U(unit,
   3214                                     "       %5d %8d %13d    "),
   3215                          index + i, ref_count, entries_per_set));
   3216 
   3217                 entry_p = SOC_PROFILE_MEM_ENTRY(unit,
   3218                                                 _tr2_cos_map_profile[unit],
   3219                                                 port_cos_map_entry_t *,
   3220                                                 index + i);
   3221                 cosq = soc_mem_field32_get(unit,
   3222                                            PORT_COS_MAPm,
   3223                                            entry_p,
   3224                                            COSf);
   3225                 LOG_CLI((BSL_META_U(unit,
   3226                                     "%2d "), cosq));
   3227                 if (soc_mem_field_valid(unit, PORT_COS_MAPm, HG_COSf)) {
   3228                     hg_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm,
   3229                                                   entry_p,
   3230                                                   HG_COSf);
   3231                     LOG_CLI((BSL_META_U(unit,
   3232                                         "    %2d"), hg_cosq));
   3233                 }
   3234                 LOG_CLI((BSL_META_U(unit,
   3235                                     "\n")));
   3236             }
   3237         }
   3238     }
   3239 
   3240     /* Egress COSQ Map profile */
   3241     /* Display those entries with reference count > 0 */
   3242     LOG_CLI((BSL_META_U(unit,
   3243                         "    Egress COSQ Map Profile:\n")));
   3244     if (_tr2_cos_egr_map_profile[unit] != NULL) {
   3245         int     num_entries;
   3246         int     ref_count;
   3247         int     entries_per_set;
   3248         uint32  index;
   3249         uint32  cosq;
   3250         egr_cos_map_entry_t *entry_p;
   3251 
   3252         num_entries = soc_mem_index_count
   3253             (unit, _tr2_cos_egr_map_profile[unit]->tables[0].mem);
   3254         LOG_CLI((BSL_META_U(unit,
   3255                             "        Number of entries: %d\n"), num_entries));
   3256         LOG_CLI((BSL_META_U(unit,
   3257                             "        Index RefCount EntriesPerSet - "
   3258                  "Entry: REDIRECT_COS\n")));
   3259 
   3260         for (index = 0; index < num_entries;
   3261              index += TR2_COS_MAP_ENTRIES_PER_SET) {
   3262             if (SOC_FAILURE
   3263                 (soc_profile_mem_ref_count_get(unit,
   3264                                                _tr2_cos_egr_map_profile[unit],
   3265                                                index, &ref_count))) {
   3266                 break;
   3267             }
   3268 
   3269             if (ref_count <= 0) {
   3270                 continue;
   3271             }
   3272 
   3273             for (i = 0; i < TR2_COS_MAP_ENTRIES_PER_SET; i++) {
   3274                 entries_per_set =
   3275                     _tr2_cos_egr_map_profile[unit]->tables[0].entries[index+i].entries_per_set;
   3276                 LOG_CLI((BSL_META_U(unit,
   3277                                     "       %5d %8d %13d     "),
   3278                          index + i, ref_count, entries_per_set));
   3279 
   3280                 entry_p = SOC_PROFILE_MEM_ENTRY(unit,
   3281                                                 _tr2_cos_egr_map_profile[unit],
   3282                                                 egr_cos_map_entry_t *,
   3283                                                 index + i);
   3284                 cosq = soc_mem_field32_get(unit,
   3285                                            EGR_COS_MAPm,
   3286                                            entry_p,
   3287                                            REDIRECT_COSf);
   3288                 LOG_CLI((BSL_META_U(unit,
   3289                                     "              %3d "), cosq));
   3290 
   3291                 LOG_CLI((BSL_META_U(unit,
   3292                                     "\n")));
   3293             }
   3294         }
   3295     }
   3296 
   3297     return;
   3298 }
   3299 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   3300 
   3301 #else /* BCM_TRIUMPH2_SUPPORT */
   3302 int _tr2_cosq_not_empty;
   3303 #endif  /* BCM_TRIUMPH2_SUPPORT */
   3304