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


      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_TRX_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/stack.h>
     26 #ifdef BCM_SCORPION_SUPPORT
     27 #include <bcm_int/esw/scorpion.h>
     28 #endif 
     29 #include <bcm_int/esw/triumph.h>
     30 
     31 #include <bcm_int/esw_dispatch.h>
     32 
     33 #ifdef BCM_WARM_BOOT_SUPPORT
     34 #include <bcm_int/esw/switch.h>
     35 #endif /* BCM_WARM_BOOT_SUPPORT */
     36 
     37 #define TR_DRR_WEIGHT_MAX       0x7f
     38 #define TR_WRR_WEIGHT_MAX       0x7f
     39 
     40 #define TR_PACKET_FIELD_MAX(_u_)   (SOC_IS_ENDURO(_u_) ? (0x1fff) : (0x3fff))
     41 #define TR_CELL_FIELD_MAX(_u_)   (SOC_IS_ENDURO(_u_) ? (0x3fff) : (0x7fff))
     42 
     43 #define TR_PKT_REFRESH_MAX(_u_)   (SOC_IS_ENDURO(_u_) ? (0x3ffff) : (0xfffff))
     44 #define TR_PKT_THD_MAX(_u_)   (SOC_IS_ENDURO(_u_) ? (0xfff) : (0x7ff))
     45 
     46 /* COSQ where output of hierarchical COSQs scheduler is attached */
     47 #define TR_SCHEDULER_COSQ       8
     48 
     49 /* MMU cell size in bytes */
     50 #define _BCM_TR_COSQ_CELLSIZE   128
     51 
     52 #ifdef BCM_SCORPION_SUPPORT
     53 #define SC_CELL_FIELD_MAX       0x3fff
     54 #define _BCM_SC_COSQ_CELLSIZE   128
     55 STATIC int _bcm_sc_cosq_discard_all_disable (int unit);
     56 #endif
     57 
     58 
     59 /* Cache of COS_MAP Profile Table */
     60 #define TR_COS_MAP_ENTRIES_PER_SET    16 /* COS Map profile entries per set */
     61 STATIC soc_profile_mem_t *_tr_cos_map_profile[BCM_MAX_NUM_UNITS] = {NULL};
     62 
     63 /* Number of COSQs configured for this device */
     64 STATIC int _tr_num_cosq[SOC_MAX_NUM_DEVICES];
     65 
     66 /* Port Bitmap which includes ports capable of hierarchical queueing */
     67 STATIC soc_pbmp_t _tr_cosq_24q_ports[SOC_MAX_NUM_DEVICES];
     68 
     69 /* Array to keep track of the number of hierarchical COSQs added per port */
     70 STATIC uint8 *_tr_num_port_cosq[SOC_MAX_NUM_DEVICES] = {NULL};
     71 
     72 /* Forward declarations */
     73 STATIC int _bcm_tr_cosq_gport_delete(int unit, bcm_port_t port);
     74 STATIC int _bcm_tr_cosq_port_sched_set(int unit, soc_reg_t config_reg,
     75                                        soc_reg_t weight_reg, soc_reg_t minsp_reg,
     76                                        bcm_port_t port, bcm_cos_queue_t start_cosq,
     77                                        int num_weights, const int weights[], 
     78                                        int mode);
     79 STATIC int _bcm_tr_cosq_discard_set(int unit, bcm_port_t port, uint32 flags,
     80                                     bcm_cos_queue_t cosq, soc_reg_t config_reg,
     81                                     soc_reg_t thresh_reg_green,
     82                                     soc_reg_t thresh_reg_yellow,
     83                                     soc_reg_t thresh_reg_red,
     84                                     soc_reg_t thresh_reg_non_tcp,
     85                                     uint32 min_thresh, uint32 max_thresh,
     86                                     int drop_probability, int gain);
     87 
     88 /*
     89  * Function:
     90  *      _bcm_tr_cosw_port_count_get
     91  * Purpose:
     92  *      Returns number of ports in device.
     93  * Parameters:
     94  *      unit - Unit number.
     95  * Returns:
     96  *      BCM_E_XXX
     97  */
     98 STATIC int
     99 _bcm_tr_cosq_port_count_get(int unit)
    100 {
    101     int port_count = 44;
    102 
    103 #ifdef BCM_ENDURO_SUPPORT
    104     if(SOC_IS_ENDURO (unit)) {
    105         port_count = 30;
    106     }
    107 #endif /* BCM_ENDURO_SUPPORT */
    108 
    109     return port_count;
    110 }
    111 
    112 #ifdef BCM_WARM_BOOT_SUPPORT
    113 
    114 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    115 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
    116 
    117 /*
    118  * Function:
    119  *      bcm_tr_cosq_sync
    120  * Purpose:
    121  *      Record COSQ module persistent info for Level 2 Warm Boot.
    122  * Parameters:
    123  *      unit - Unit number.
    124  * Returns:
    125  *      BCM_E_XXX
    126  */
    127 int
    128 bcm_tr_cosq_sync(int unit)
    129 {
    130     soc_scache_handle_t scache_handle;
    131     uint8               *cosq_scache_ptr;
    132     uint32              num_cosq;
    133 
    134     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    135     BCM_IF_ERROR_RETURN
    136         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    137                                  0, &cosq_scache_ptr, 
    138                                  BCM_WB_DEFAULT_VERSION, NULL));
    139     
    140     /* Number COSQ */
    141     num_cosq = _tr_num_cosq[unit];
    142     sal_memcpy(cosq_scache_ptr, &num_cosq, sizeof(num_cosq));
    143     cosq_scache_ptr += sizeof(num_cosq);
    144         
    145     /* Number of hierarchical COSQs added per port */
    146     if (_tr_num_port_cosq[unit] != NULL) {
    147         sal_memcpy(cosq_scache_ptr, _tr_num_port_cosq[unit],
    148                    sizeof(uint8) * _bcm_tr_cosq_port_count_get(unit));
    149     }
    150 
    151     return BCM_E_NONE;
    152 }
    153 
    154 /*
    155  * Function:
    156  *      _bcm_tr_cosq_reinit
    157  * Purpose:
    158  *      Recover COSQ software state.
    159  * Parameters:
    160  *      unit - Unit number.
    161  * Returns:
    162  *      BCM_E_XXX
    163  */
    164 STATIC int
    165 _bcm_tr_cosq_reinit(int unit)
    166 {
    167     int                 rv;
    168     soc_scache_handle_t scache_handle;
    169     uint8               *cosq_scache_ptr;
    170     uint32              num_cosq;
    171  	 
    172     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    173     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    174                                  0, &cosq_scache_ptr, 
    175                                  BCM_WB_DEFAULT_VERSION, NULL);
    176 
    177     if (rv == BCM_E_NOT_FOUND) {
    178         cosq_scache_ptr = NULL;
    179     } else if (BCM_FAILURE(rv)) {
    180         return rv;
    181     }
    182 
    183     if (cosq_scache_ptr != NULL) {
    184         /* Number COSQ */
    185         sal_memcpy(&num_cosq, cosq_scache_ptr, sizeof(num_cosq));
    186         _tr_num_cosq[unit] = num_cosq;
    187         cosq_scache_ptr += sizeof(num_cosq);
    188 
    189         /* Number of hierarchical COSQs added per port */
    190         if (_tr_num_port_cosq[unit] != NULL) {
    191             sal_memcpy(_tr_num_port_cosq[unit], cosq_scache_ptr,
    192                        sizeof(uint8) * _bcm_tr_cosq_port_count_get(unit));
    193         }
    194 
    195     } else {
    196         _tr_num_cosq[unit] = _bcm_esw_cosq_config_property_get(unit);
    197     }
    198     
    199     return BCM_E_NONE;
    200 }
    201 #endif /* BCM_WARM_BOOT_SUPPORT */
    202 
    203 /*
    204  * Function:
    205  *      bcm_cosq_init
    206  * Purpose:
    207  *      Initialize (clear) all COS schedule/mapping state.
    208  * Parameters:
    209  *      unit - StrataSwitch unit number.
    210  * Returns:
    211  *      BCM_E_XXX
    212  */
    213 
    214 int
    215 bcm_tr_cosq_init(int unit)
    216 {
    217     STATIC int _tr_max_cosq = -1;
    218     int num_cos;
    219     int port_count;
    220 #ifdef BCM_WARM_BOOT_SUPPORT
    221     int                 rv;
    222     soc_scache_handle_t scache_handle;
    223     uint32              cosq_scache_size;
    224     uint8               *cosq_scache_ptr;
    225 #endif /* BCM_WARM_BOOT_SUPPORT */
    226 
    227 #ifdef BCM_SCORPION_SUPPORT
    228     STATIC int _sc_max_cosq = -1;
    229     if (SOC_IS_SC_CQ(unit)) {
    230         if (_sc_max_cosq < 0) {
    231             _sc_max_cosq = NUM_COS(unit);
    232             NUM_COS(unit) = 8;
    233         }
    234     } else 
    235 #endif
    236     if (_tr_max_cosq < 0) {
    237         _tr_max_cosq = NUM_COS(unit);
    238         NUM_COS(unit) = 8;
    239     }
    240 
    241     if (!SOC_WARM_BOOT(unit)) {    /* Cold Boot */
    242         BCM_IF_ERROR_RETURN (bcm_tr_cosq_detach(unit, 0));
    243     }
    244 
    245     num_cos = _bcm_esw_cosq_config_property_get(unit);
    246 
    247     port_count = _bcm_tr_cosq_port_count_get(unit);
    248     if (SOC_IS_TR_VL(unit)) {
    249         SOC_PBMP_CLEAR(_tr_cosq_24q_ports[unit]);
    250         /* Keep track of ports that support 24 (16 + 8) queues */
    251 #ifdef BCM_ENDURO_SUPPORT
    252         if(SOC_IS_ENDURO (unit)) {
    253             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 26);
    254             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 27);
    255             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 28);
    256             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 29);            
    257         } else
    258 #endif /* BCM_ENDURO_SUPPORT */
    259         {
    260             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 2);
    261             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 3);
    262             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 14);
    263             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 15);
    264             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 26);
    265             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 27);
    266             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 28);
    267             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 29);
    268             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 30);
    269             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 31);
    270             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 32);
    271             SOC_PBMP_PORT_ADD(_tr_cosq_24q_ports[unit], 43);
    272         }
    273 
    274         if (_tr_num_port_cosq[unit] == NULL) {
    275             _tr_num_port_cosq[unit] = sal_alloc(sizeof(uint8) * port_count,
    276                                          "_tr_num_port_cosq");
    277         }
    278         sal_memset(_tr_num_port_cosq[unit], 0, sizeof(uint8) * port_count);
    279     }
    280 
    281 #ifdef BCM_WARM_BOOT_SUPPORT
    282     /* Warm boot level 2 cache size */
    283     cosq_scache_size = sizeof(uint32); /* Number COSQ */
    284     if (_tr_num_port_cosq[unit] != NULL) {  /* Number of COSQs per port */
    285         cosq_scache_size += (sizeof(uint8) * port_count);
    286     }
    287 
    288     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    289     rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
    290                                  (0 == SOC_WARM_BOOT(unit)),
    291                                  cosq_scache_size, &cosq_scache_ptr, 
    292                                  BCM_WB_DEFAULT_VERSION, NULL);
    293     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    294         return rv;
    295     }
    296 
    297     if (SOC_WARM_BOOT(unit)) {
    298         BCM_IF_ERROR_RETURN(_bcm_tr_cosq_reinit(unit));
    299         num_cos = _tr_num_cosq[unit];
    300     }
    301 #endif /* BCM_WARM_BOOT_SUPPORT */
    302 
    303     return bcm_tr_cosq_config_set(unit, num_cos);
    304 }
    305 
    306 /*
    307  * Function:
    308  *      bcm_cosq_detach
    309  * Purpose:
    310  *      Discard all COS schedule/mapping state.
    311  * Parameters:
    312  *      unit - StrataSwitch unit number.
    313  * Returns:
    314  *      BCM_E_XXX
    315  */
    316 
    317 int
    318 bcm_tr_cosq_detach(int unit, int software_state_only)
    319 {
    320     bcm_port_t port;
    321     int weights[8];
    322     int cosq;
    323 
    324     if (SOC_IS_TR_VL(unit))
    325     {
    326         /* Delete any gports that were added */
    327 
    328         if (_tr_num_port_cosq[unit])
    329         {
    330             if (!software_state_only)
    331             {
    332                 BCM_PBMP_ITER(_tr_cosq_24q_ports[unit], port)
    333                 {
    334                     if (_tr_num_port_cosq[unit][port])
    335                     {
    336                         BCM_IF_ERROR_RETURN
    337                             (_bcm_tr_cosq_gport_delete(unit, port));
    338                     }
    339                 }
    340             }
    341 
    342             BCM_IF_ERROR_RETURN
    343                 (soc_profile_mem_destroy(unit, _tr_cos_map_profile[unit]));
    344             sal_free(_tr_cos_map_profile[unit]);
    345             _tr_cos_map_profile[unit] = NULL;
    346 
    347             sal_free(_tr_num_port_cosq[unit]);
    348             _tr_num_port_cosq[unit] = NULL;
    349         }
    350     }
    351 
    352     for (cosq = 0; cosq < 8; cosq++) {
    353         weights[cosq] = 0;
    354     }
    355 
    356     if (!software_state_only)
    357     {
    358         PBMP_ALL_ITER(unit, port) {
    359             if (IS_CPU_PORT(unit, port)) {
    360                 continue;
    361             }
    362 
    363     #ifdef BCM_SCORPION_SUPPORT
    364             if (SOC_IS_SC_CQ(unit)) {
    365                 /* Clear bandwidth settings on port */
    366                 for (cosq = 0; cosq < 8; cosq++) {
    367                      BCM_IF_ERROR_RETURN
    368                         (bcm_sc_cosq_port_bandwidth_set(unit, port, cosq, 0, 0, 0, 0));
    369                 }
    370             } else 
    371     #endif
    372             {
    373                 /* Clear bandwidth settings on port */
    374                 for (cosq = 0; cosq < 8; cosq++) {
    375                      BCM_IF_ERROR_RETURN
    376                         (bcm_tr_cosq_port_bandwidth_set(unit, port, cosq, 0, 0, 0, 0));
    377                 }
    378             }
    379             /* Clear scheduling settings on port */
    380             BCM_IF_ERROR_RETURN
    381                 (_bcm_tr_cosq_port_sched_set(unit, 
    382                                              ESCONFIGr, COSWEIGHTSr, MINSPCONFIGr,
    383                                              port, 0, 8, weights, 
    384                                              BCM_COSQ_WEIGHTED_ROUND_ROBIN));
    385             /* Clear discard settings on port */
    386      
    387             if (SOC_IS_TR_VL(unit)) {
    388                 for (cosq = 0; cosq < 8; cosq++) {
    389                      BCM_IF_ERROR_RETURN
    390                         (_bcm_tr_cosq_discard_set(unit, port, 
    391                                               BCM_COSQ_DISCARD_COLOR_ALL | 
    392                                               BCM_COSQ_DISCARD_NONTCP, cosq,
    393                                               WREDCONFIG_PACKETr,
    394                                               WREDPARAM_PACKETr,
    395                                               WREDPARAM_YELLOW_PACKETr,
    396                                               WREDPARAM_RED_PACKETr,
    397                                               WREDPARAM_NONTCP_PACKETr,
    398                                               TR_PACKET_FIELD_MAX(unit), 
    399                                               TR_PACKET_FIELD_MAX(unit), 100, 0));
    400                 }
    401             }
    402         }
    403     }
    404 
    405 #ifdef BCM_SCORPION_SUPPORT
    406     if (SOC_IS_SC_CQ(unit)) {
    407         BCM_IF_ERROR_RETURN (_bcm_sc_cosq_discard_all_disable(unit));
    408     } else
    409 #endif
    410     {
    411         /* Disable WRED on all cosq level */
    412         BCM_IF_ERROR_RETURN (bcm_tr_cosq_discard_set(unit, 0));
    413     }
    414 
    415     return BCM_E_NONE;
    416 }
    417 
    418 /*
    419  * Function:
    420  *      bcm_cosq_config_set
    421  * Purpose:
    422  *      Set the number of COS queues
    423  * Parameters:
    424  *      unit - Unit number.
    425  *      numq - number of COS queues (1-8).
    426  * Returns:
    427  *      BCM_E_XXX
    428  */
    429 
    430 int
    431 bcm_tr_cosq_config_set(int unit, int numq)
    432 {
    433     int cos, prio, ratio, remain;
    434     uint32 index, minsp;
    435     soc_mem_t mem = PORT_COS_MAPm; 
    436     int entry_words = sizeof(port_cos_map_entry_t) / sizeof(uint32);
    437     bcm_pbmp_t ports;
    438     bcm_port_t port;
    439     port_cos_map_entry_t cos_map_array[TR_COS_MAP_ENTRIES_PER_SET];
    440     void *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     if (SOC_IS_SHADOW(unit)) {
    453         return BCM_E_NONE; 
    454     }
    455 
    456     sal_memset(cos_map_array, 0,
    457                TR_COS_MAP_ENTRIES_PER_SET * sizeof(port_cos_map_entry_t));
    458 
    459     if (_tr_cos_map_profile[unit] == NULL) {
    460         _tr_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
    461                                           "COS_MAP Profile Mem");
    462         if (_tr_cos_map_profile[unit] == NULL) {
    463             return BCM_E_MEMORY;
    464         }
    465         soc_profile_mem_t_init(_tr_cos_map_profile[unit]);
    466     }
    467 
    468     /* Create profile table cache (or re-init if it already exists) */
    469     SOC_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, &entry_words, 1,
    470                                                _tr_cos_map_profile[unit]));
    471 
    472     if (SOC_WARM_BOOT(unit)) {    /* Warm Boot */
    473         int     i;
    474         uint32  val;
    475 
    476         /* Gather reference count for cosq map profile table */
    477         BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
    478         PBMP_ITER(ports, port) {
    479             SOC_IF_ERROR_RETURN(READ_COS_MAP_SELr(unit, port, &val));
    480             index = soc_reg_field_get(unit, COS_MAP_SELr, val, SELECTf);
    481             index *= TR_COS_MAP_ENTRIES_PER_SET;
    482             for (i = 0; i < TR_COS_MAP_ENTRIES_PER_SET; i++) {
    483                 SOC_PROFILE_MEM_REFERENCE(unit, _tr_cos_map_profile[unit],
    484                                           index + i, 1);
    485                 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit,
    486                                                 _tr_cos_map_profile[unit],
    487                                                 index + i,
    488                                                 TR_COS_MAP_ENTRIES_PER_SET);
    489             }
    490 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
    491             if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
    492                 SOC_IF_ERROR_RETURN(READ_ICOS_MAP_SELr(unit, port, &val));
    493                 index = soc_reg_field_get(unit, ICOS_MAP_SELr, val, SELECTf);
    494                 index *= TR_COS_MAP_ENTRIES_PER_SET;
    495                 for (i = 0; i < TR_COS_MAP_ENTRIES_PER_SET; i++) {
    496                     SOC_PROFILE_MEM_REFERENCE(unit, _tr_cos_map_profile[unit],
    497                                               index + i, 1);
    498                     SOC_PROFILE_MEM_ENTRIES_PER_SET(unit,
    499                                                     _tr_cos_map_profile[unit],
    500                                                     index + i,
    501                                                     TR_COS_MAP_ENTRIES_PER_SET);
    502                 }
    503             }
    504 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
    505         }
    506     } else {    /* Cold Boot */
    507 
    508         entries[0] = &cos_map_array;
    509 
    510         ratio = 8 / numq;
    511         remain = 8 % numq;
    512         cos = 0;
    513         for (prio = 0; prio < 8; prio++) {
    514             soc_mem_field32_set(unit, PORT_COS_MAPm,
    515                                 &cos_map_array[prio], COSf, cos);
    516             if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
    517                 soc_mem_field32_set(unit, PORT_COS_MAPm,
    518                                     &cos_map_array[prio], HG_COSf, 0);
    519             }
    520 
    521             if ((prio + 1) == (((cos + 1) * ratio) +
    522                                ((remain < (numq - cos)) ? 0 :
    523                                 (remain - (numq - cos) + 1)))) {
    524                 cos++;
    525             }
    526         }
    527 
    528         /* Map remaining internal priority levels to highest priority cosq */
    529         cos = numq - 1;
    530         for (prio = 8; prio < 16; prio++) {
    531             soc_mem_field32_set(unit, PORT_COS_MAPm,
    532                                 &cos_map_array[prio], COSf, cos);
    533             if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
    534                 soc_mem_field32_set(unit, PORT_COS_MAPm,
    535                                     &cos_map_array[prio], HG_COSf, 0);
    536             }
    537         }
    538 
    539         /* Map internal priority levels to CPU CoS queues */
    540         BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq));
    541 
    542         /* Add a profile mem entry for each port */
    543         BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
    544         PBMP_ITER(ports, port) {
    545             SOC_IF_ERROR_RETURN
    546                 (soc_profile_mem_add(unit, _tr_cos_map_profile[unit],
    547                                      (void *) &entries,
    548                                      TR_COS_MAP_ENTRIES_PER_SET,
    549                                      &index));
    550             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, COS_MAP_SELr, port, 
    551                                                        SELECTf,
    552                                                        (index / TR_COS_MAP_ENTRIES_PER_SET)));
    553 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
    554             if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
    555                 SOC_IF_ERROR_RETURN
    556                     (soc_profile_mem_add(unit, _tr_cos_map_profile[unit],
    557                                          (void *) &entries,
    558                                          TR_COS_MAP_ENTRIES_PER_SET,
    559                                          &index));
    560                 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ICOS_MAP_SELr, port, 
    561                                                            SELECTf,
    562                                                            (index / TR_COS_MAP_ENTRIES_PER_SET)));
    563             }
    564 #endif
    565         }
    566 
    567 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
    568         /* identity mapping for higig ports */
    569 
    570         /* map prio0->cos0, prio1->cos1, ... , prio7->cos7 */
    571         for (prio = 0; prio < 8; prio++) {
    572             soc_mem_field32_set(unit, PORT_COS_MAPm,
    573                                 &cos_map_array[prio], COSf, prio);
    574             if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
    575                 soc_mem_field32_set(unit, PORT_COS_MAPm,
    576                                     &cos_map_array[prio], HG_COSf, 0);
    577             }
    578         }
    579         /* Map remaining internal priority levels to highest priority cosq */
    580         for (prio = 8; prio < 16; prio++) {
    581             soc_mem_field32_set(unit, PORT_COS_MAPm,
    582                                 &cos_map_array[prio], COSf, 7);
    583             if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
    584                 soc_mem_field32_set(unit, PORT_COS_MAPm,
    585                                     &cos_map_array[prio], HG_COSf, 0);
    586             }
    587         }
    588 
    589         PBMP_ITER(ports, port) {
    590             if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
    591                 SOC_IF_ERROR_RETURN
    592                     (soc_profile_mem_add(unit, _tr_cos_map_profile[unit],
    593                                          (void *) &entries,
    594                                          TR_COS_MAP_ENTRIES_PER_SET, &index));
    595                 soc_reg_field32_modify(unit, ICOS_MAP_SELr, port, 
    596                                        SELECTf,
    597                                        (index / TR_COS_MAP_ENTRIES_PER_SET));
    598             }
    599         }
    600 #endif
    601 
    602         /* Always strict priority for SC and QM COS queues */
    603         PBMP_ITER(ports, port) {
    604 #ifdef BCM_SCORPION_SUPPORT
    605             if (SOC_IS_SC_CQ(unit)) {
    606                 /* COS8 and COS9 not configurable on Scorpion */
    607                 continue;
    608             }
    609 #endif
    610             SOC_IF_ERROR_RETURN
    611                 (READ_MINSPCONFIGr(unit, port, &minsp));
    612             soc_reg_field_set(unit, MINSPCONFIGr, &minsp, COS8_IS_SPf, 1);
    613             soc_reg_field_set(unit, MINSPCONFIGr, &minsp, COS9_IS_SPf, 1);
    614             SOC_IF_ERROR_RETURN
    615                 (WRITE_MINSPCONFIGr(unit, port, minsp));
    616         }
    617     }
    618 
    619     _tr_num_cosq[unit] = numq;
    620 
    621 #ifdef BCM_WARM_BOOT_SUPPORT
    622     SOC_CONTROL_LOCK(unit);
    623     SOC_CONTROL(unit)->scache_dirty = 1;
    624     SOC_CONTROL_UNLOCK(unit);
    625 #endif
    626 
    627     return BCM_E_NONE;
    628 }
    629 
    630 /*
    631  * Function:
    632  *      bcm_cosq_config_get
    633  * Purpose:
    634  *      Get the number of cos queues
    635  * Parameters:
    636  *      unit - StrataSwitch unit number.
    637  *      numq - (Output) number of cosq
    638  * Returns:
    639  *      BCM_E_XXX
    640  */
    641 
    642 int
    643 bcm_tr_cosq_config_get(int unit, int *numq)
    644 {
    645     if (_tr_num_cosq[unit] == 0) {
    646         return BCM_E_INIT;
    647     }
    648 
    649     if (numq != NULL) {
    650         *numq = _tr_num_cosq[unit];
    651     }
    652 
    653     return BCM_E_NONE;
    654 }
    655 
    656 /*
    657  * Function:
    658  *      bcm_cosq_mapping_set
    659  * Purpose:
    660  *      Set which cosq a given priority should fall into
    661  * Parameters:
    662  *      unit - StrataSwitch unit number.
    663  *      priority - Priority value to map
    664  *      cosq - COS queue to map to
    665  * Returns:
    666  *      BCM_E_XXX
    667  */
    668 
    669 int
    670 bcm_tr_cosq_mapping_set(int unit, bcm_port_t port,
    671                         bcm_cos_t priority, bcm_cos_queue_t cosq)
    672 {
    673     uint32 val, old_index, new_index;
    674     int i;
    675     port_cos_map_entry_t cos_map_array[TR_COS_MAP_ENTRIES_PER_SET], *entry_p;
    676     void *entries[1];
    677     bcm_pbmp_t ports;
    678     bcm_port_t local_port;
    679 
    680     if (priority < 0 || priority >= 16) {
    681         return (BCM_E_PARAM);
    682     }
    683 
    684     if (cosq < 0 || cosq >= 8) {
    685         return (BCM_E_PARAM);
    686     }
    687 
    688     if (port == -1) {	/* all ports */
    689         BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
    690     } else {
    691         if (BCM_GPORT_IS_SET(port)) {
    692             BCM_IF_ERROR_RETURN(
    693                 bcm_esw_port_local_get(unit, port, &local_port)); 
    694         } else {
    695             local_port = port;
    696         }
    697 
    698         if (!SOC_PORT_VALID(unit, local_port) || !IS_ALL_PORT(unit, local_port)) {
    699             return BCM_E_PORT;
    700         }
    701         BCM_PBMP_CLEAR(ports);
    702         BCM_PBMP_PORT_ADD(ports, local_port);
    703     }
    704 
    705     entries[0] = &cos_map_array;
    706 
    707     PBMP_ITER(ports, local_port) {
    708         SOC_IF_ERROR_RETURN(READ_COS_MAP_SELr(unit, local_port, &val));
    709         old_index = soc_reg_field_get(unit, COS_MAP_SELr, val, SELECTf);
    710         old_index *= TR_COS_MAP_ENTRIES_PER_SET;
    711 
    712         /* get current mapping profile values */
    713         for (i = 0; i < TR_COS_MAP_ENTRIES_PER_SET; i++) {
    714             entry_p = SOC_PROFILE_MEM_ENTRY(unit, _tr_cos_map_profile[unit],
    715                                             port_cos_map_entry_t *, (old_index + i));
    716             memcpy(&cos_map_array[i], entry_p, sizeof(*entry_p));
    717         }
    718         soc_mem_field32_set(unit, PORT_COS_MAPm,
    719                             &cos_map_array[priority], COSf, cosq);
    720         SOC_IF_ERROR_RETURN
    721             (soc_profile_mem_add(unit, _tr_cos_map_profile[unit],
    722                                  (void *) &entries,
    723                                  TR_COS_MAP_ENTRIES_PER_SET,
    724                                  &new_index));
    725         SOC_IF_ERROR_RETURN
    726             (soc_reg_field32_modify(unit, COS_MAP_SELr, local_port, 
    727                                     SELECTf,
    728                                     new_index / TR_COS_MAP_ENTRIES_PER_SET));
    729         SOC_IF_ERROR_RETURN
    730             (soc_profile_mem_delete(unit, _tr_cos_map_profile[unit], old_index));
    731 
    732 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
    733         if (IS_HG_PORT(unit, local_port) || local_port == CMIC_PORT(unit)) {
    734             SOC_IF_ERROR_RETURN
    735                 (soc_profile_mem_add(unit, _tr_cos_map_profile[unit],
    736                                      (void *) &entries,
    737                                      TR_COS_MAP_ENTRIES_PER_SET,
    738                                      &new_index));
    739             SOC_IF_ERROR_RETURN
    740                 (soc_reg_field32_modify(unit, ICOS_MAP_SELr, local_port, 
    741                                         SELECTf,
    742                                         new_index / TR_COS_MAP_ENTRIES_PER_SET));
    743             SOC_IF_ERROR_RETURN
    744                 (soc_profile_mem_delete(unit, _tr_cos_map_profile[unit], old_index));
    745         }
    746 #endif
    747     }
    748     return BCM_E_NONE;
    749 }
    750 
    751 /*
    752  * Function:
    753  *      bcm_cosq_mapping_get
    754  * Purpose:
    755  *      Determine which COS queue a given priority currently maps to.
    756  * Parameters:
    757  *      unit - StrataSwitch unit number.
    758  *      priority - Priority value
    759  *      cosq - (Output) COS queue number
    760  * Returns:
    761  *      BCM_E_XXX
    762  */
    763 
    764 int
    765 bcm_tr_cosq_mapping_get(int unit, bcm_port_t port,
    766                         bcm_cos_t priority, bcm_cos_queue_t *cosq)
    767 {
    768     uint32 val;
    769     int index;
    770     port_cos_map_entry_t *entry_p;
    771     bcm_port_t local_port;
    772 
    773     if (priority < 0 || priority >= 16) {
    774         return (BCM_E_PARAM);
    775     }
    776 
    777     if (port == -1) {
    778         local_port = REG_PORT_ANY;
    779     } else {
    780         if (BCM_GPORT_IS_SET(port)) {
    781             BCM_IF_ERROR_RETURN(
    782                 bcm_esw_port_local_get(unit, port, &local_port)); 
    783         } else {
    784             local_port = port;
    785         }
    786 
    787         if (!SOC_PORT_VALID(unit, local_port) || !IS_ALL_PORT(unit, local_port)) {
    788             return BCM_E_PORT;
    789         }
    790     }
    791 
    792     SOC_IF_ERROR_RETURN(READ_COS_MAP_SELr(unit, local_port, &val));
    793     index = soc_reg_field_get(unit, COS_MAP_SELr, val, SELECTf);
    794     index *= TR_COS_MAP_ENTRIES_PER_SET;
    795 
    796     entry_p = SOC_PROFILE_MEM_ENTRY(unit, _tr_cos_map_profile[unit],
    797                                     port_cos_map_entry_t *, 
    798                                     (index + priority));
    799     *cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, COSf);
    800     return BCM_E_NONE;
    801 }
    802 
    803 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
    804 STATIC int
    805 _bcm_tr_cpu_cosq_port_bandwidth_set(int unit, bcm_port_t port,
    806                                bcm_cos_queue_t cosq,
    807                                uint32 kbits_sec_min,
    808                                uint32 kbits_sec_max,
    809                                uint32 kbits_sec_burst,
    810                                uint32 flags)
    811 {
    812     uint32 regval;
    813     uint32 bucket_val = 0;
    814     uint64 regval_64;
    815     uint32 refresh_rate, bucketsize, granularity = 3, meter_flags = 0;
    816     int    refresh_bitsize, bucket_bitsize;
    817 
    818     if(SOC_IS_RCPU_ONLY(unit)) {
    819         return 0; 
    820     }   
    821 
    822     /*
    823      * To set the new Bandwidth settings, the procedure adopted is
    824      * a. reset MAXBUCKETCONFIG, MINBUCKETCONFIG, MAXBUCKET,MINBUCKET
    825      * b. update MAXBUCKETCONFIG and MINBUCKETCONFIG with new values passed
    826      * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it.
    827      */
    828     if (SOC_IS_ENDURO(unit)) {
    829         meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ?
    830                             _BCM_XGS_METER_FLAG_PACKET_MODE : 0;
    831     }
    832      
    833     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
    834     if (soc_reg_field_get(unit, MISCCONFIGr, regval, ITU_MODE_SELf)) {
    835         meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
    836     }
    837     meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
    838 
    839     /* Disable egress metering for this port */
    840     if (SOC_REG_IS_VALID(unit, CPUMAXBUCKETCONFIG_64r)) {
    841         BCM_IF_ERROR_RETURN(READ_CPUMAXBUCKETCONFIG_64r(unit, cosq, &regval_64));
    842         soc_reg64_field32_set(unit, CPUMAXBUCKETCONFIG_64r, &regval_64, MAX_REFRESHf, 0);
    843         soc_reg64_field32_set(unit, CPUMAXBUCKETCONFIG_64r, &regval_64, MAX_THDf, 0);
    844         BCM_IF_ERROR_RETURN(WRITE_CPUMAXBUCKETCONFIG_64r(unit, cosq, regval_64));
    845     }
    846 
    847     /*reset the MAXBUCKET register*/
    848     if (SOC_REG_IS_VALID(unit, CPUMAXBUCKETr)) {
    849         soc_reg_field_set(unit, CPUMAXBUCKETr, &bucket_val, PKT_MAX_BUCKETf, 0);
    850         soc_reg_field_set(unit, CPUMAXBUCKETr, &bucket_val, OUT_PROFILE_FLAGf, 0);
    851         BCM_IF_ERROR_RETURN(WRITE_CPUMAXBUCKETr(unit, cosq, bucket_val));
    852     }
    853 
    854     refresh_bitsize =
    855         soc_reg_field_length(unit, MINBUCKETCONFIG_64r, MIN_REFRESHf);
    856     bucket_bitsize =
    857         soc_reg_field_length(unit, MINBUCKETCONFIG_64r, MIN_THDf);
    858 
    859     BCM_IF_ERROR_RETURN
    860         (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_min, kbits_sec_min,
    861                           meter_flags, refresh_bitsize, bucket_bitsize,
    862                           &refresh_rate, &bucketsize, &granularity));
    863 
    864     if (SOC_REG_IS_VALID(unit, CPUMAXBUCKETCONFIG_64r)) {
    865         refresh_bitsize =
    866             soc_reg_field_length(unit, CPUMAXBUCKETCONFIG_64r, MAX_REFRESHf);
    867         bucket_bitsize =
    868             soc_reg_field_length(unit, CPUMAXBUCKETCONFIG_64r, MAX_THDf);
    869     }
    870 
    871     BCM_IF_ERROR_RETURN
    872         (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_max, kbits_sec_burst,
    873                           meter_flags, refresh_bitsize, bucket_bitsize,
    874                           &refresh_rate, &bucketsize, &granularity));
    875 
    876     COMPILER_64_ZERO(regval_64);
    877     if (SOC_REG_IS_VALID(unit, CPUMAXBUCKETCONFIG_64r)) {
    878         soc_reg64_field32_set(unit, CPUMAXBUCKETCONFIG_64r, &regval_64,
    879                               METER_GRANf, granularity);
    880         soc_reg64_field32_set(unit, CPUMAXBUCKETCONFIG_64r, &regval_64,
    881                               MAX_REFRESHf, refresh_rate);
    882         soc_reg64_field32_set(unit, CPUMAXBUCKETCONFIG_64r, &regval_64, MAX_THDf,
    883                               bucketsize);
    884         if (SOC_IS_ENDURO(unit)) {                          
    885             soc_reg64_field32_set(unit, CPUMAXBUCKETCONFIG_64r, &regval_64, MODEf,
    886                               (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0);
    887         }
    888         BCM_IF_ERROR_RETURN(WRITE_CPUMAXBUCKETCONFIG_64r(unit, cosq, regval_64));
    889     }
    890     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
    891 
    892     return BCM_E_NONE;
    893 }
    894 #endif
    895 
    896 
    897 STATIC int
    898 _bcm_tr_cosq_bucket_set(int unit, bcm_port_t port, 
    899                                 bcm_cos_queue_t cosq,
    900                                 uint32 kbits_sec_min, /* kbps or packet/second */
    901                                 uint32 kbits_sec_max, /* kbps or packet/second */
    902                                 uint32 kbits_burst_min, 
    903                                 uint32 kbits_burst_max, 
    904                                 uint32 flags)
    905 {
    906     uint32 regval;
    907     uint32 bucket_val = 0;
    908     uint64 regval_64;
    909     uint32 refresh_rate, bucketsize, granularity = 3, meter_flags = 0;
    910     int    refresh_bitsize, bucket_bitsize;
    911 
    912     if(SOC_IS_RCPU_ONLY(unit)) {
    913         return 0; 
    914     }   
    915 
    916 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) 
    917     if (IS_CPU_PORT(unit, port)) {
    918         return _bcm_tr_cpu_cosq_port_bandwidth_set(unit, port, cosq, 
    919                 kbits_sec_min, kbits_sec_max, kbits_burst_max, flags);
    920     }    
    921 #endif /* BCM_ENDURO_SUPPORT */ 
    922 
    923     /*
    924      * To set the new Bandwidth settings, the procedure adopted is
    925      * a. reset MAXBUCKETCONFIG, MINBUCKETCONFIG, MAXBUCKET,MINBUCKET
    926      * b. update MAXBUCKETCONFIG and MINBUCKETCONFIG with new values passed
    927      * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it.
    928      */
    929 
    930     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
    931     if (soc_reg_field_get(unit, MISCCONFIGr, regval, ITU_MODE_SELf)) {
    932         meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
    933     }
    934     meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
    935 
    936     /* Disable egress metering for this port */
    937     BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIG_64r(unit, port, cosq, &regval_64));
    938     soc_reg64_field32_set(unit, MAXBUCKETCONFIG_64r, &regval_64, MAX_REFRESHf, 0);
    939     soc_reg64_field32_set(unit, MAXBUCKETCONFIG_64r, &regval_64, MAX_THDf, 0);
    940     BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIG_64r(unit, port, cosq, regval_64));
    941 
    942     BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIG_64r(unit, port, cosq, &regval_64));
    943     soc_reg64_field32_set(unit, MINBUCKETCONFIG_64r, &regval_64, MIN_REFRESHf, 0);
    944     soc_reg64_field32_set(unit, MINBUCKETCONFIG_64r, &regval_64, MIN_THDf, 0);
    945     BCM_IF_ERROR_RETURN(WRITE_MINBUCKETCONFIG_64r(unit, port, cosq, regval_64));
    946 
    947     /*reset the MAXBUCKET register*/
    948     soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, MAX_BUCKETf, 0);
    949     soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, OUT_PROFILE_FLAGf, 0);
    950     BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETr(unit, port, cosq, bucket_val));
    951 
    952     /*reset the MINBUCKET register value*/
    953     soc_reg_field_set(unit, MINBUCKETr, &bucket_val, MIN_BUCKETf, 0);
    954     soc_reg_field_set(unit, MINBUCKETr, &bucket_val, OUT_PROFILE_FLAGf, 0);
    955     BCM_IF_ERROR_RETURN(WRITE_MINBUCKETr(unit, port, cosq, bucket_val));
    956 
    957     refresh_bitsize =
    958         soc_reg_field_length(unit, MINBUCKETCONFIG_64r, MIN_REFRESHf);
    959     bucket_bitsize =
    960         soc_reg_field_length(unit, MINBUCKETCONFIG_64r, MIN_THDf);
    961 
    962     BCM_IF_ERROR_RETURN
    963         (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_min, kbits_burst_min,
    964                           meter_flags, refresh_bitsize, bucket_bitsize,
    965                           &refresh_rate, &bucketsize, &granularity));
    966 
    967     COMPILER_64_ZERO(regval_64);
    968     soc_reg64_field32_set(unit, MINBUCKETCONFIG_64r, &regval_64,
    969                           METER_GRANf, granularity);
    970     soc_reg64_field32_set(unit, MINBUCKETCONFIG_64r, &regval_64,
    971                           MIN_REFRESHf, refresh_rate);
    972     soc_reg64_field32_set(unit, MINBUCKETCONFIG_64r,
    973                           &regval_64, MIN_THDf, bucketsize);
    974     BCM_IF_ERROR_RETURN
    975         (WRITE_MINBUCKETCONFIG_64r(unit, port, cosq, regval_64));
    976 
    977     refresh_bitsize =
    978         soc_reg_field_length(unit, MAXBUCKETCONFIG_64r, MAX_REFRESHf);
    979     bucket_bitsize =
    980         soc_reg_field_length(unit, MAXBUCKETCONFIG_64r, MAX_THDf);
    981 
    982     BCM_IF_ERROR_RETURN
    983         (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_max, kbits_burst_max,
    984                           meter_flags, refresh_bitsize, bucket_bitsize,
    985                           &refresh_rate, &bucketsize, &granularity));
    986 
    987     COMPILER_64_ZERO(regval_64);
    988     soc_reg64_field32_set(unit, MAXBUCKETCONFIG_64r, &regval_64,
    989                           METER_GRANf, granularity);
    990     soc_reg64_field32_set(unit, MAXBUCKETCONFIG_64r, &regval_64,
    991                           MAX_REFRESHf, refresh_rate);
    992     soc_reg64_field32_set(unit, MAXBUCKETCONFIG_64r, &regval_64, MAX_THDf,
    993                           bucketsize);
    994     BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIG_64r(unit, port, cosq, regval_64));
    995 
    996     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
    997 
    998     return BCM_E_NONE;
    999 }
   1000 
   1001 STATIC int
   1002 _bcm_tr_cosq_bucket_get(int unit, bcm_port_t port,
   1003                                bcm_cos_queue_t cosq,
   1004                                uint32 *kbits_sec_min,
   1005                                uint32 *kbits_sec_max,
   1006                                uint32 *kbits_min_burst,
   1007                                uint32 *kbits_max_burst,
   1008                                uint32 *flags)
   1009 {
   1010     uint32 regval;
   1011     uint64 regval_64;
   1012     uint32 refresh_rate = 0, bucketsize = 0,
   1013         granularity = 3, meter_flags = 0;
   1014 
   1015     if (!kbits_sec_min || !kbits_sec_max || !kbits_min_burst
   1016         || !kbits_max_burst || !flags) {
   1017         return (BCM_E_PARAM);
   1018     }
   1019 
   1020     *flags = 0;
   1021     BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIG_64r(unit, port, cosq, &regval_64));
   1022     granularity = soc_reg64_field32_get(unit, MAXBUCKETCONFIG_64r,
   1023                                             regval_64, METER_GRANf);
   1024     refresh_rate = soc_reg64_field32_get(unit, MAXBUCKETCONFIG_64r,
   1025                                              regval_64, MAX_REFRESHf);
   1026     bucketsize = soc_reg64_field32_get(unit, MAXBUCKETCONFIG_64r,
   1027                                              regval_64, MAX_THDf);
   1028 
   1029     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
   1030     if (soc_reg_field_get(unit, MISCCONFIGr, regval, ITU_MODE_SELf)) {
   1031         meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1032     }
   1033 
   1034     meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1035 
   1036 
   1037 
   1038     BCM_IF_ERROR_RETURN
   1039         (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   1040                                            granularity, meter_flags,
   1041                                            kbits_sec_max, kbits_max_burst));
   1042 
   1043     BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIG_64r(unit, port, cosq, &regval_64));
   1044 
   1045     granularity = soc_reg64_field32_get(unit, MINBUCKETCONFIG_64r,
   1046                                             regval_64, METER_GRANf);
   1047     refresh_rate = soc_reg64_field32_get(unit, MINBUCKETCONFIG_64r,
   1048                                              regval_64, MIN_REFRESHf);
   1049     bucketsize = soc_reg64_field32_get(unit, MINBUCKETCONFIG_64r,
   1050                                              regval_64, MIN_THDf);
   1051     BCM_IF_ERROR_RETURN
   1052         (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   1053                                            granularity, meter_flags,
   1054                                            kbits_sec_min, kbits_min_burst));
   1055 
   1056     return BCM_E_NONE;
   1057 }
   1058 
   1059 
   1060 int
   1061 bcm_tr_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   1062                                bcm_cos_queue_t cosq,
   1063                                uint32 kbits_sec_min,
   1064                                uint32 kbits_sec_max,
   1065                                uint32 kbits_sec_burst,
   1066                                uint32 flags)
   1067 {
   1068     
   1069     /*keep place with original*/
   1070     return _bcm_tr_cosq_bucket_set(unit, port, cosq, kbits_sec_min, kbits_sec_max,
   1071                                     kbits_sec_min, kbits_sec_burst, flags); 
   1072 }
   1073 
   1074 int
   1075 bcm_tr_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   1076                                bcm_cos_queue_t cosq,
   1077                                uint32 *kbits_sec_min,
   1078                                uint32 *kbits_sec_max,
   1079                                uint32 *kbits_sec_burst,
   1080                                uint32 *flags)
   1081 {
   1082 
   1083     uint32 kbits_min_burst; /* Placeholder, since burst is unused for min */
   1084 
   1085     BCM_IF_ERROR_RETURN(_bcm_tr_cosq_bucket_get(unit, port, cosq,
   1086                         kbits_sec_min, kbits_sec_max, &kbits_min_burst,
   1087                         kbits_sec_burst, flags));
   1088     return BCM_E_NONE;
   1089 
   1090 }
   1091 
   1092 STATIC int
   1093 _bcm_tr_cosq_port_packet_bandwidth_set(int unit, bcm_port_t port,
   1094                                        bcm_cos_queue_t cosq,
   1095                                        int pps, int burst)
   1096 
   1097 {
   1098     uint32 regval, max_config_addr, max_addr;
   1099     soc_reg_t maxbucket_config_reg, maxbucket_reg;
   1100     soc_field_t refresh_f, thd_sel_f, bucket_f;
   1101 
   1102     if (cosq < 0) {
   1103         maxbucket_config_reg = CPUPKTPORTMAXBUCKETCONFIGr;
   1104         maxbucket_reg = CPUPKTPORTMAXBUCKETr;
   1105         refresh_f = PKT_PORT_MAX_REFRESHf;
   1106         thd_sel_f = PKT_PORT_MAX_THD_SELf;
   1107         bucket_f = PKT_PORT_MAX_BUCKETf;
   1108         cosq = 0;
   1109     } else {
   1110         maxbucket_config_reg = CPUPKTMAXBUCKETCONFIGr;
   1111         maxbucket_reg = CPUPKTMAXBUCKETr;
   1112         refresh_f = PKT_MAX_REFRESHf;
   1113         thd_sel_f = PKT_MAX_THD_SELf;
   1114         bucket_f = PKT_MAX_BUCKETf;
   1115     }
   1116 
   1117     /*
   1118      * To set the new Bandwidth settings, the procedure adopted is
   1119      * a. reset MAXBUCKETCONFIG and MAXBUCKET
   1120      * b. update MAXBUCKETCONFIG with new values passed
   1121      * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it.
   1122      */
   1123 
   1124     /* Disable egress metering */
   1125     max_config_addr = soc_reg_addr(unit, maxbucket_config_reg, port, cosq);
   1126     BCM_IF_ERROR_RETURN(soc_reg32_read(unit, max_config_addr, &regval));
   1127     soc_reg_field_set(unit, maxbucket_config_reg, &regval, refresh_f, 0);
   1128     soc_reg_field_set(unit, maxbucket_config_reg, &regval, thd_sel_f, 0);
   1129     BCM_IF_ERROR_RETURN(soc_reg32_write(unit, max_config_addr, regval));
   1130 
   1131     /* reset the MAXBUCKET register*/
   1132     max_addr = soc_reg_addr(unit, maxbucket_reg, port, cosq);
   1133     BCM_IF_ERROR_RETURN(soc_reg32_read(unit, max_addr, &regval));
   1134     soc_reg_field_set(unit, maxbucket_reg, &regval, bucket_f, 0);
   1135     soc_reg_field_set(unit, maxbucket_reg, &regval, OUT_PROFILE_FLAGf, 0);
   1136     BCM_IF_ERROR_RETURN(soc_reg32_write(unit, max_addr, regval));
   1137 
   1138     /* Check packets-per second upper limit */
   1139     if (pps > TR_PKT_REFRESH_MAX(unit)) {
   1140         pps = TR_PKT_REFRESH_MAX(unit);
   1141     }
   1142 
   1143     /* Check burst upper limit */
   1144     if (burst > TR_PKT_THD_MAX(unit)) {
   1145         burst = TR_PKT_THD_MAX(unit);
   1146     }
   1147 
   1148     BCM_IF_ERROR_RETURN(soc_reg32_read(unit, max_config_addr, &regval));
   1149     soc_reg_field_set(unit, maxbucket_config_reg, &regval, refresh_f, pps);
   1150     soc_reg_field_set(unit, maxbucket_config_reg, 
   1151                                 &regval, thd_sel_f, burst);
   1152     BCM_IF_ERROR_RETURN(soc_reg32_write(unit, max_config_addr, regval));
   1153 
   1154     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
   1155 
   1156     return BCM_E_NONE;
   1157 }
   1158 
   1159 #ifdef BCM_ENDURO_SUPPORT
   1160 
   1161 STATIC int
   1162 _bcm_en_cosq_port_packet_bandwidth_set(int unit, bcm_port_t port,
   1163                                        bcm_cos_queue_t cosq,
   1164                                        int pps, int burst, uint32 flags)
   1165 {
   1166     uint64 regval_64;
   1167     uint32 refresh_rate, bucketsize, granularity = 3, meter_flags = 0;
   1168     int    refresh_bitsize, bucket_bitsize;
   1169     uint32 regval, max_config_addr, max_addr;
   1170     soc_reg_t maxbucket_config_reg, maxbucket_reg;
   1171     soc_field_t refresh_f, thd_sel_f, bucket_f;
   1172 
   1173     if (cosq < 0) {
   1174         maxbucket_config_reg = CPUPORTMAXBUCKETCONFIG_64r;
   1175         maxbucket_reg = CPUPORTMAXBUCKETr;
   1176         refresh_f = MAX_REFRESHf;
   1177         thd_sel_f = MAX_THD_SELf;
   1178         bucket_f = MAX_BUCKETf;            
   1179         cosq = 0;
   1180     } else {
   1181         maxbucket_config_reg = CPUMAXBUCKETCONFIG_64r;
   1182         maxbucket_reg = CPUMAXBUCKETr;
   1183         refresh_f = MAX_REFRESHf;
   1184         thd_sel_f = MAX_THDf;
   1185         bucket_f = PKT_MAX_BUCKETf;
   1186     }
   1187 
   1188     /*
   1189      * To set the new Bandwidth settings, the procedure adopted is
   1190      * a. reset MAXBUCKETCONFIG and MAXBUCKET
   1191      * b. update MAXBUCKETCONFIG with new values passed
   1192      * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it.
   1193      */
   1194 
   1195     /* Disable egress metering */
   1196     max_config_addr = soc_reg_addr(unit, maxbucket_config_reg, port, cosq);
   1197     BCM_IF_ERROR_RETURN(soc_reg64_read(unit, max_config_addr, &regval_64));
   1198     soc_reg64_field32_set(unit, maxbucket_config_reg, 
   1199                                 &regval_64, refresh_f, 0);
   1200     soc_reg64_field32_set(unit, maxbucket_config_reg, 
   1201                                 &regval_64, thd_sel_f, 0);
   1202     BCM_IF_ERROR_RETURN(soc_reg64_write(unit, max_config_addr, regval_64));       
   1203 
   1204     /* reset the MAXBUCKET register*/
   1205     max_addr = soc_reg_addr(unit, maxbucket_reg, port, cosq);
   1206     BCM_IF_ERROR_RETURN(soc_reg32_read(unit, max_addr, &regval));
   1207     soc_reg_field_set(unit, maxbucket_reg, &regval, bucket_f, 0);
   1208     soc_reg_field_set(unit, maxbucket_reg, &regval, OUT_PROFILE_FLAGf, 0);
   1209     BCM_IF_ERROR_RETURN(soc_reg32_write(unit, max_addr, regval));
   1210 
   1211     meter_flags = flags & BCM_COSQ_BW_PACKET_MODE ?
   1212                             _BCM_XGS_METER_FLAG_PACKET_MODE : 0;
   1213         
   1214     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
   1215     if (soc_reg_field_get(unit, MISCCONFIGr, regval, ITU_MODE_SELf)) {
   1216         meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1217     }
   1218     meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1219 
   1220     refresh_bitsize =
   1221             soc_reg_field_length(unit, maxbucket_config_reg, refresh_f);
   1222     bucket_bitsize =
   1223             soc_reg_field_length(unit, maxbucket_config_reg, thd_sel_f);
   1224 
   1225     BCM_IF_ERROR_RETURN
   1226             (_bcm_xgs_kbits_to_bucket_encoding(pps, burst,
   1227                               meter_flags, refresh_bitsize, bucket_bitsize,
   1228                               &refresh_rate, &bucketsize, &granularity));
   1229 
   1230     BCM_IF_ERROR_RETURN(soc_reg64_read(unit, max_config_addr, &regval_64));
   1231     soc_reg64_field32_set(unit, maxbucket_config_reg, 
   1232                                     &regval_64, METER_GRANf, granularity);
   1233     soc_reg64_field32_set(unit, maxbucket_config_reg, 
   1234                                     &regval_64, refresh_f, refresh_rate);
   1235     soc_reg64_field32_set(unit, maxbucket_config_reg, 
   1236                                     &regval_64, thd_sel_f, bucketsize);
   1237     soc_reg64_field32_set(unit, maxbucket_config_reg, &regval_64, MODEf, 
   1238                                     (flags & BCM_COSQ_BW_PACKET_MODE) ? 1 : 0);
   1239     BCM_IF_ERROR_RETURN(soc_reg64_write(unit, max_config_addr, regval_64));      
   1240 
   1241     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
   1242 
   1243     return BCM_E_NONE;
   1244 }
   1245 
   1246 #endif /* BCM_ENDURO_SUPPORT */
   1247 
   1248 
   1249 STATIC int
   1250 _bcm_tr_cosq_port_packet_bandwidth_get(int unit, bcm_port_t port,
   1251                                        bcm_cos_queue_t cosq,
   1252                                        int *pps, int *burst)
   1253 
   1254 
   1255 {
   1256     uint32 regval, max_config_addr;
   1257     soc_reg_t maxbucket_config_reg;
   1258     soc_field_t refresh_f, thd_sel_f;
   1259 
   1260     if (cosq < 0) {
   1261         maxbucket_config_reg = CPUPKTPORTMAXBUCKETCONFIGr;
   1262         refresh_f = PKT_PORT_MAX_REFRESHf;
   1263         thd_sel_f = PKT_PORT_MAX_THD_SELf;
   1264         cosq = 0;
   1265     } else {
   1266         maxbucket_config_reg = CPUPKTMAXBUCKETCONFIGr;
   1267         refresh_f = PKT_MAX_REFRESHf;
   1268         thd_sel_f = PKT_MAX_THD_SELf;
   1269     }
   1270 
   1271     /* Disable egress metering */
   1272     max_config_addr = soc_reg_addr(unit, maxbucket_config_reg, port, cosq);
   1273     BCM_IF_ERROR_RETURN(soc_reg32_read(unit, max_config_addr, &regval));
   1274     *pps = soc_reg_field_get(unit, maxbucket_config_reg, regval, refresh_f);
   1275     *burst = soc_reg_field_get(unit, maxbucket_config_reg, 
   1276                                          regval, thd_sel_f);
   1277 
   1278     return BCM_E_NONE;
   1279 }
   1280 
   1281 #ifdef BCM_ENDURO_SUPPORT
   1282 
   1283 STATIC int
   1284 _bcm_en_cosq_port_packet_bandwidth_get(int unit, bcm_port_t port,
   1285                                        bcm_cos_queue_t cosq,
   1286                                        int *pps, int *burst,
   1287                                        uint32 *flags)
   1288 {
   1289     uint64 regval_64;
   1290     uint32 refresh_rate = 0, bucketsize = 0,
   1291         granularity = 3, meter_flags = 0;
   1292     uint32 regval;
   1293     uint32 max_config_addr;
   1294     
   1295     soc_reg_t maxbucket_config_reg;
   1296     soc_field_t refresh_f, thd_sel_f;
   1297 
   1298     if (cosq < 0) {
   1299         maxbucket_config_reg = CPUPORTMAXBUCKETCONFIG_64r;
   1300         refresh_f = MAX_REFRESHf;
   1301         thd_sel_f = MAX_THD_SELf;
   1302         cosq = 0;
   1303     } else {
   1304         maxbucket_config_reg = CPUMAXBUCKETCONFIG_64r;
   1305         refresh_f = MAX_REFRESHf;
   1306         thd_sel_f = MAX_THDf;
   1307     }
   1308 
   1309     /* Disable egress metering */
   1310     max_config_addr = soc_reg_addr(unit, maxbucket_config_reg, port, cosq);
   1311     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
   1312         if (soc_reg_field_get(unit, MISCCONFIGr, regval, ITU_MODE_SELf)) {
   1313             meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1314         }
   1315 
   1316         *flags = 0;
   1317 
   1318         BCM_IF_ERROR_RETURN(soc_reg64_read(unit, max_config_addr, &regval_64));       
   1319         if (soc_reg64_field32_get(unit, maxbucket_config_reg, 
   1320                                                   regval_64, MODEf)) {
   1321             meter_flags |= _BCM_XGS_METER_FLAG_PACKET_MODE;
   1322             *flags |= BCM_COSQ_BW_PACKET_MODE;
   1323         }
   1324         meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1325 
   1326         granularity = soc_reg64_field32_get(unit, maxbucket_config_reg, 
   1327                                                   regval_64, METER_GRANf);
   1328         refresh_rate = soc_reg64_field32_get(unit, maxbucket_config_reg, 
   1329                                                    regval_64, refresh_f);
   1330         bucketsize = soc_reg64_field32_get(unit, maxbucket_config_reg, 
   1331                                                  regval_64, thd_sel_f);
   1332 
   1333         BCM_IF_ERROR_RETURN
   1334             (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   1335                                                granularity, meter_flags,
   1336                                                (uint32 *)pps, (uint32 *)burst));
   1337 
   1338     return BCM_E_NONE;
   1339 }
   1340 
   1341 #endif /* BCM_ENDURO_SUPPORT */
   1342 
   1343 int
   1344 bcm_tr_cosq_port_pps_set(int unit, bcm_port_t port,
   1345                          bcm_cos_queue_t cosq, int pps)
   1346 {
   1347     int temp_pps, burst;
   1348 
   1349     if (!IS_CPU_PORT(unit, port)) {
   1350         return BCM_E_PORT;
   1351     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   1352         return BCM_E_PARAM;
   1353     } else if (pps < 0) {
   1354         return BCM_E_PARAM;
   1355     }
   1356 
   1357     /* Get the current PPS and BURST settings */
   1358 #ifdef BCM_ENDURO_SUPPORT    
   1359     if (SOC_IS_ENDURO(unit)) {
   1360         uint32 flags;
   1361 
   1362         BCM_IF_ERROR_RETURN
   1363             (_bcm_en_cosq_port_packet_bandwidth_get(unit, port, cosq,
   1364                                                 &temp_pps, &burst,
   1365                                                 &flags));
   1366 
   1367         /* Replace the current PPS setting, keep BURST the same */
   1368         return _bcm_en_cosq_port_packet_bandwidth_set(unit, port, cosq,
   1369                              pps, burst, flags | BCM_COSQ_BW_PACKET_MODE);
   1370                                                 
   1371     } else 
   1372 #endif /* BCM_ENDURO_SUPPORT */    
   1373     {
   1374         BCM_IF_ERROR_RETURN
   1375             (_bcm_tr_cosq_port_packet_bandwidth_get(unit, port, cosq,
   1376                                                 &temp_pps, &burst));
   1377 
   1378         /* Replace the current PPS setting, keep BURST the same */
   1379         return _bcm_tr_cosq_port_packet_bandwidth_set(unit, port, cosq,
   1380                                                   pps, burst);
   1381 
   1382     }
   1383 }
   1384 
   1385 int
   1386 bcm_tr_cosq_port_pps_get(int unit, bcm_port_t port,
   1387                          bcm_cos_queue_t cosq, int *pps)
   1388 {
   1389     int burst;
   1390 
   1391     if (!IS_CPU_PORT(unit, port)) {
   1392         return BCM_E_PORT;
   1393     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   1394         return BCM_E_PARAM;
   1395     }
   1396     
   1397 #ifdef BCM_ENDURO_SUPPORT    
   1398     if (SOC_IS_ENDURO(unit)) {
   1399         uint32 flags;
   1400     
   1401         return _bcm_en_cosq_port_packet_bandwidth_get(unit, port, cosq,
   1402                                                   pps, &burst, &flags);
   1403     } else 
   1404 #endif /* BCM_ENDURO_SUPPORT */        
   1405     {
   1406         return _bcm_tr_cosq_port_packet_bandwidth_get(unit, port, cosq,
   1407                                                   pps, &burst);
   1408     }
   1409 }
   1410 
   1411 int
   1412 bcm_tr_cosq_port_burst_set(int unit, bcm_port_t port,
   1413                            bcm_cos_queue_t cosq, int burst)
   1414 {
   1415     int pps, temp_burst;
   1416 
   1417     if (!IS_CPU_PORT(unit, port)) {
   1418         return BCM_E_PORT;
   1419     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   1420         return BCM_E_PARAM;
   1421     } else if (burst < 0) {
   1422         return BCM_E_PARAM;
   1423     }
   1424 #ifdef BCM_ENDURO_SUPPORT    
   1425     if (SOC_IS_ENDURO(unit)) {
   1426         uint32 flags;
   1427 
   1428         /* Get the current PPS and BURST settings */
   1429         BCM_IF_ERROR_RETURN
   1430             (_bcm_en_cosq_port_packet_bandwidth_get(unit, port, cosq,
   1431                                                 &pps, &temp_burst,
   1432                                                 &flags));
   1433 
   1434         /* Replace the current BURST setting, keep PPS the same */
   1435         return _bcm_en_cosq_port_packet_bandwidth_set(unit, port, cosq,
   1436                                 pps, burst, flags | BCM_COSQ_BW_PACKET_MODE);
   1437     } else 
   1438 #endif /* BCM_ENDURO_SUPPORT */            
   1439     {
   1440         /* Get the current PPS and BURST settings */
   1441         BCM_IF_ERROR_RETURN
   1442             (_bcm_tr_cosq_port_packet_bandwidth_get(unit, port, cosq,
   1443                                                 &pps, &temp_burst));
   1444 
   1445         /* Replace the current BURST setting, keep PPS the same */
   1446         return _bcm_tr_cosq_port_packet_bandwidth_set(unit, port, cosq,
   1447                                                   pps, burst);
   1448     }    
   1449 }
   1450 
   1451 int
   1452 bcm_tr_cosq_port_burst_get(int unit, bcm_port_t port,
   1453                            bcm_cos_queue_t cosq, int *burst)
   1454 {
   1455     int pps;
   1456 
   1457     if (!IS_CPU_PORT(unit, port)) {
   1458         return BCM_E_PORT;
   1459     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   1460         return BCM_E_PARAM;
   1461     }
   1462 
   1463 #ifdef BCM_ENDURO_SUPPORT        
   1464     if (SOC_IS_ENDURO(unit)) {
   1465         uint32 flags;
   1466 
   1467         return _bcm_en_cosq_port_packet_bandwidth_get(unit, port, cosq,
   1468                                                   &pps, burst, &flags);
   1469     } else 
   1470 #endif /* BCM_ENDURO_SUPPORT */                
   1471     {
   1472         return _bcm_tr_cosq_port_packet_bandwidth_get(unit, port, cosq,
   1473                                                   &pps, burst);
   1474     }
   1475 }
   1476 
   1477 int
   1478 _bcm_tr_cosq_port_resolve(int unit, bcm_gport_t gport,
   1479                        bcm_module_t *modid, bcm_port_t *port,
   1480                        bcm_trunk_t *trunk_id, int *id)
   1481 {
   1482     bcm_module_t mod_in;
   1483     bcm_port_t port_in;
   1484 
   1485     if (BCM_GPORT_IS_SCHEDULER(gport)) {
   1486         mod_in = (BCM_GPORT_SCHEDULER_GET(gport) >> 8) & 0xff;
   1487         port_in = BCM_GPORT_SCHEDULER_GET(gport) & 0xff;
   1488         *id = BCM_GPORT_SCHEDULER_GET(gport);
   1489         *trunk_id = -1;
   1490 
   1491         /* Since the modid/port in the scheduler GPORT is the
   1492          * applications modid/port space, convert to local space.
   1493          */
   1494         BCM_IF_ERROR_RETURN
   1495             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   1496                                     mod_in, port_in, modid, port));
   1497 
   1498         if (!_tr_num_port_cosq[unit]) {
   1499             return BCM_E_INIT;
   1500         } else if (!SOC_PBMP_MEMBER(_tr_cosq_24q_ports[unit], *port)) {
   1501             return BCM_E_BADID;
   1502         } else if (_tr_num_port_cosq[unit][*port] == 0) {
   1503             return BCM_E_NOT_FOUND;
   1504         }
   1505     } else {
   1506         return BCM_E_BADID;
   1507     }
   1508     return BCM_E_NONE;
   1509 }
   1510 
   1511 STATIC int
   1512 _bcm_tr_cosq_resolve_mod_port(int unit, bcm_gport_t gport,
   1513                               bcm_module_t *modid, bcm_port_t *port,
   1514                               bcm_trunk_t *trunk_id)
   1515 {
   1516     int gport_id, result;
   1517 
   1518     BCM_IF_ERROR_RETURN
   1519         (_bcm_esw_gport_resolve(unit, gport, modid,
   1520                                 port, trunk_id, &gport_id));
   1521     BCM_IF_ERROR_RETURN(
   1522         _bcm_esw_modid_is_local(unit, *modid, &result)); 
   1523 
   1524     if (TRUE != result) {
   1525         return BCM_E_PORT;
   1526     }
   1527     return BCM_E_NONE;
   1528 }
   1529 
   1530 STATIC int     
   1531 _bcm_tr_cosq_discard_cap_enable_set(int unit, bcm_port_t port, 
   1532                                     bcm_cos_queue_t cosq, soc_reg_t config_reg, 
   1533                                     uint32 flags)
   1534 {
   1535     uint32 val, addr;
   1536 
   1537     addr = soc_reg_addr(unit, config_reg, port, cosq);
   1538     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1539 
   1540     if (flags & BCM_COSQ_DISCARD_CAP_AVERAGE) {
   1541         soc_reg_field_set(unit, config_reg, &val, CAP_AVERAGEf, 1);
   1542     } else {
   1543         soc_reg_field_set(unit, config_reg, &val, CAP_AVERAGEf, 0);
   1544     }
   1545     if (flags & BCM_COSQ_DISCARD_ENABLE) {
   1546         soc_reg_field_set(unit, config_reg, &val, ENABLEf, 1);
   1547     } else {
   1548         soc_reg_field_set(unit, config_reg, &val, ENABLEf, 0);
   1549     }
   1550     SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1551     return BCM_E_NONE;
   1552 }
   1553 
   1554 STATIC int
   1555 _bcm_tr_cosq_discard_cap_enable_get(int unit, bcm_port_t port, 
   1556                                     bcm_cos_queue_t cosq, soc_reg_t config_reg, 
   1557                                     uint32 *flags)
   1558 {
   1559     uint32 val, addr;
   1560 
   1561     addr = soc_reg_addr(unit, config_reg, port, cosq);
   1562     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1563 
   1564     if (soc_reg_field_get(unit, config_reg, val, CAP_AVERAGEf)) {
   1565         *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   1566     }
   1567     if (soc_reg_field_get(unit, config_reg, val, ENABLEf)) {
   1568         *flags |= BCM_COSQ_DISCARD_ENABLE;
   1569     }
   1570     return BCM_E_NONE;
   1571 }
   1572 
   1573 int
   1574 bcm_tr_cosq_discard_set(int unit, uint32 flags)
   1575 {
   1576     bcm_port_t port;
   1577     bcm_cos_queue_t cosq;
   1578     soc_reg_t config_reg = WREDCONFIG_PACKETr;
   1579 
   1580     if (flags & ~(BCM_COSQ_DISCARD_CAP_AVERAGE |
   1581                   BCM_COSQ_DISCARD_ENABLE)) {
   1582         return BCM_E_PARAM;
   1583     }
   1584 
   1585     PBMP_ALL_ITER(unit, port) {
   1586         if (IS_CPU_PORT(unit, port)) {
   1587             continue;
   1588         }
   1589         for (cosq = 0; cosq < 8; cosq++) {
   1590             BCM_IF_ERROR_RETURN
   1591                 (_bcm_tr_cosq_discard_cap_enable_set(unit, port, cosq,
   1592                                                      config_reg, flags));
   1593         }
   1594         if (SOC_PBMP_MEMBER(_tr_cosq_24q_ports[unit], port)) {
   1595             for (cosq = 8; cosq < 24; cosq++) {
   1596                 BCM_IF_ERROR_RETURN
   1597                     (_bcm_tr_cosq_discard_cap_enable_set(unit, port, cosq,
   1598                                                          config_reg, flags));
   1599             }
   1600         }
   1601     }
   1602     return BCM_E_NONE;
   1603 }
   1604 
   1605 int
   1606 bcm_tr_cosq_discard_get(int unit, uint32 *flags)
   1607 {
   1608     int rv = BCM_E_NONE;
   1609     bcm_port_t port;
   1610     soc_reg_t config_reg = WREDCONFIG_PACKETr;
   1611 
   1612     PBMP_ALL_ITER(unit, port) {
   1613         if (IS_CPU_PORT(unit, port)) {
   1614             continue;
   1615         }
   1616         *flags = 0;
   1617         rv = _bcm_tr_cosq_discard_cap_enable_get(unit, port, 0,
   1618                                                  config_reg, flags);
   1619         break;
   1620     }
   1621     return rv;
   1622 }
   1623 
   1624 /*      
   1625  *  Convert HW drop probability to percent value
   1626  */     
   1627 STATIC int       
   1628 _bcm_tr_hw_drop_prob_to_percent[] = {
   1629     0,     /* 0  */
   1630     1,     /* 1  */
   1631     2,     /* 2  */
   1632     3,     /* 3  */
   1633     4,     /* 4  */
   1634     5,     /* 5  */
   1635     6,     /* 6  */
   1636     7,     /* 7  */
   1637     8,     /* 8  */
   1638     9,     /* 9  */
   1639     10,    /* 10 */
   1640     25,    /* 11 */
   1641     50,    /* 12 */
   1642     75,    /* 13 */
   1643     100,   /* 14 */
   1644     -1     /* 15 */
   1645 };
   1646 
   1647 STATIC int
   1648 _bcm_tr_percent_to_drop_prob(int percent) {
   1649    int i;
   1650 
   1651    for (i=14; i > 0 ; i--) {
   1652       if (percent >= _bcm_tr_hw_drop_prob_to_percent[i]) {
   1653           break;
   1654       }
   1655    }
   1656    return i;
   1657 }
   1658 
   1659 STATIC int
   1660 _bcm_tr_drop_prob_to_percent(int drop_prob) {
   1661    return (_bcm_tr_hw_drop_prob_to_percent[drop_prob]);
   1662 }   
   1663 
   1664 STATIC int 
   1665 _bcm_tr_angle_to_packets_table[] =
   1666 {
   1667     /*  0.. 5 */  16383, 5727, 2862, 1908, 1430, 1142,
   1668     /*  6..11 */    951,  814,  711,  631,  567,  514,
   1669     /* 12..17 */    470,  433,  401,  373,  348,  327,
   1670     /* 18..23 */    307,  290,  274,  260,  247,  235,
   1671     /* 24..29 */    224,  214,  205,  196,  188,  180,
   1672     /* 30..35 */    173,  166,  160,  153,  148,  142,
   1673     /* 36..41 */    137,  132,  127,  123,  119,  115,
   1674     /* 42..47 */    111,  107,  103,  100,   96,   93,
   1675     /* 48..53 */     90,   86,   83,   80,   78,   75,
   1676     /* 54..59 */     72,   70,   67,   64,   62,   60,
   1677     /* 60..65 */     57,   55,   53,   50,   48,   46,
   1678     /* 66..71 */     44,   42,   40,   38,   36,   34,
   1679     /* 72..77 */     32,   30,   28,   26,   24,   23,
   1680     /* 78..83 */     21,   19,   17,   15,   14,   12,
   1681     /* 84..89 */     10,    8,    6,    5,    3,    1,
   1682     /* 90     */      0
   1683 };
   1684 
   1685 /* 
   1686  * Given a slope (angle in degrees) from 0 to 90, return
   1687  * the number of packets in the range from 0% drop
   1688  * probability to 100% drop probability.
   1689  */
   1690 STATIC int
   1691 _bcm_tr_angle_to_packets(int angle) {
   1692     return (_bcm_tr_angle_to_packets_table[angle]);
   1693 }
   1694 
   1695 /*
   1696  * Given a number of packets in the range from 0% drop probability
   1697  * to 100% drop probability, return the slope (angle in degrees).
   1698  */
   1699 STATIC int
   1700 _bcm_tr_packets_to_angle(int packets) {
   1701     int angle;
   1702 
   1703     for (angle = 90; angle >= 0 ; angle--) {
   1704         if (packets <= _bcm_tr_angle_to_packets_table[angle]) {
   1705             break;
   1706         }
   1707     }
   1708     return angle;
   1709 }
   1710 
   1711 STATIC int     
   1712 _bcm_tr_cosq_discard_set(int unit, bcm_port_t port, uint32 flags,
   1713                          bcm_cos_queue_t cosq, soc_reg_t config_reg,
   1714                          soc_reg_t thresh_reg_green,
   1715                          soc_reg_t thresh_reg_yellow,
   1716                          soc_reg_t thresh_reg_red,
   1717                          soc_reg_t thresh_reg_non_tcp,
   1718                          uint32 min_thresh, uint32 max_thresh,
   1719                          int drop_probability, int gain)
   1720 {
   1721     uint32 val, addr;
   1722 
   1723     if (flags & ~(BCM_COSQ_DISCARD_COLOR_GREEN  | 
   1724                   BCM_COSQ_DISCARD_COLOR_YELLOW |
   1725                   BCM_COSQ_DISCARD_COLOR_RED    |
   1726                   BCM_COSQ_DISCARD_COLOR_ALL    |
   1727                   BCM_COSQ_DISCARD_CAP_AVERAGE  |
   1728                   BCM_COSQ_DISCARD_PACKETS      |
   1729                   BCM_COSQ_DISCARD_BYTES        |
   1730                   BCM_COSQ_DISCARD_ENABLE       |
   1731                   BCM_COSQ_DISCARD_NONTCP)) {
   1732         return BCM_E_PARAM;
   1733     }
   1734 
   1735     addr = soc_reg_addr(unit, config_reg, port, cosq);
   1736     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1737 
   1738     /* Program the weight */
   1739     soc_reg_field_set(unit, config_reg, &val, WEIGHTf, gain);
   1740 
   1741     /* Program the drop probabilty */
   1742     if ((flags & BCM_COSQ_DISCARD_COLOR_GREEN) ||
   1743         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1744         soc_reg_field_set(unit, config_reg, &val, MAXDROPRATEf,
   1745             _bcm_tr_percent_to_drop_prob(drop_probability));
   1746     }
   1747     if ((flags & BCM_COSQ_DISCARD_COLOR_YELLOW) ||
   1748         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1749         soc_reg_field_set(unit, config_reg, &val, YELLOW_MAXDROPRATEf,
   1750             _bcm_tr_percent_to_drop_prob(drop_probability));
   1751     }
   1752     if ((flags & BCM_COSQ_DISCARD_COLOR_RED) ||
   1753         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1754         soc_reg_field_set(unit, config_reg, &val, RED_MAXDROPRATEf,
   1755             _bcm_tr_percent_to_drop_prob(drop_probability));
   1756     }
   1757     if (flags & BCM_COSQ_DISCARD_NONTCP)  {
   1758         soc_reg_field_set(unit, config_reg, &val, NONTCP_MAXDROPRATEf,
   1759             _bcm_tr_percent_to_drop_prob(drop_probability));
   1760     }
   1761     SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1762 
   1763     /* Program the min and max thresholds */
   1764     if ((flags & BCM_COSQ_DISCARD_COLOR_GREEN) ||
   1765         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1766         addr = soc_reg_addr(unit, thresh_reg_green, port, cosq);
   1767         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1768         soc_reg_field_set(unit, thresh_reg_green, &val, DROPSTARTPOINTf,
   1769                           min_thresh);
   1770         soc_reg_field_set(unit, thresh_reg_green, &val, DROPENDPOINTf,
   1771                           max_thresh);
   1772         SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1773     }
   1774     if ((flags & BCM_COSQ_DISCARD_COLOR_YELLOW) ||
   1775         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1776         addr = soc_reg_addr(unit, thresh_reg_yellow, port, cosq);
   1777         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1778         soc_reg_field_set(unit, thresh_reg_yellow, &val,
   1779                           YELLOW_DROPSTARTPOINTf, min_thresh);
   1780         soc_reg_field_set(unit, thresh_reg_yellow, &val,
   1781                           YELLOW_DROPENDPOINTf, max_thresh);
   1782         SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1783     }
   1784     if ((flags & BCM_COSQ_DISCARD_COLOR_RED) ||
   1785         ((flags & BCM_COSQ_DISCARD_COLOR_ALL) == BCM_COSQ_DISCARD_COLOR_ALL)) {
   1786         addr = soc_reg_addr(unit, thresh_reg_red, port, cosq);
   1787         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1788         soc_reg_field_set(unit, thresh_reg_red, &val,
   1789                           RED_DROPSTARTPOINTf, min_thresh);
   1790         soc_reg_field_set(unit, thresh_reg_red, &val,
   1791                           RED_DROPENDPOINTf, max_thresh);
   1792         SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1793     }
   1794     if (flags & BCM_COSQ_DISCARD_NONTCP) {
   1795         addr = soc_reg_addr(unit, thresh_reg_non_tcp, port, cosq);
   1796         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1797         soc_reg_field_set(unit, thresh_reg_non_tcp, &val,
   1798                           NONTCP_DROPSTARTPOINTf, min_thresh);
   1799         soc_reg_field_set(unit, thresh_reg_non_tcp, &val,
   1800                           NONTCP_DROPENDPOINTf, max_thresh);
   1801         SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   1802     }
   1803     return BCM_E_NONE;
   1804 }
   1805 
   1806 STATIC int     
   1807 _bcm_tr_cosq_discard_get(int unit, bcm_port_t port, uint32 flags,
   1808                          bcm_cos_queue_t cosq, soc_reg_t config_reg,
   1809                          soc_reg_t thresh_reg_green,
   1810                          soc_reg_t thresh_reg_yellow,
   1811                          soc_reg_t thresh_reg_red,
   1812                          soc_reg_t thresh_reg_non_tcp,
   1813                          uint32 *min_thresh, uint32 *max_thresh,
   1814                          int *drop_probability, int *gain)
   1815 {
   1816     uint32 val, addr, drop_rate;
   1817 
   1818     addr = soc_reg_addr(unit, config_reg, port, cosq);
   1819     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1820 
   1821     /* Get the weight */
   1822     *gain = soc_reg_field_get(unit, config_reg, val, WEIGHTf);
   1823 
   1824     /* Get the drop probabilty */
   1825     if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   1826         drop_rate = soc_reg_field_get(unit, config_reg, val,
   1827                                       YELLOW_MAXDROPRATEf);
   1828     } else if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   1829         drop_rate = soc_reg_field_get(unit, config_reg, val,
   1830                                       RED_MAXDROPRATEf);
   1831     } else {
   1832         drop_rate = soc_reg_field_get(unit, config_reg, val,
   1833                                       MAXDROPRATEf);
   1834     }
   1835     *drop_probability = _bcm_tr_drop_prob_to_percent(drop_rate);
   1836 
   1837     /* Get the min and max thresholds */
   1838     if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   1839         addr = soc_reg_addr(unit, thresh_reg_yellow, port, cosq);
   1840         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1841         *min_thresh = soc_reg_field_get(unit, thresh_reg_yellow, val,
   1842                                         YELLOW_DROPSTARTPOINTf);
   1843         *max_thresh = soc_reg_field_get(unit, thresh_reg_yellow, val,
   1844                                         YELLOW_DROPENDPOINTf);
   1845     } else if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   1846         addr = soc_reg_addr(unit, thresh_reg_red, port, cosq);
   1847         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1848         *min_thresh = soc_reg_field_get(unit, thresh_reg_red, val,
   1849                                         RED_DROPSTARTPOINTf);
   1850         *max_thresh = soc_reg_field_get(unit, thresh_reg_red, val,
   1851                                         RED_DROPENDPOINTf);
   1852     } else {
   1853         addr = soc_reg_addr(unit, thresh_reg_green, port, cosq);
   1854         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   1855         *min_thresh = soc_reg_field_get(unit, thresh_reg_green, val, 
   1856                                         DROPSTARTPOINTf);
   1857         *max_thresh = soc_reg_field_get(unit, thresh_reg_green, val, 
   1858                                         DROPENDPOINTf);
   1859     }
   1860     return BCM_E_NONE;
   1861 }
   1862 
   1863 #define ABS(n) (((n) < 0) ? -(n) : (n))
   1864 
   1865 int
   1866 bcm_tr_cosq_discard_port_set(int unit, bcm_port_t port,
   1867                              bcm_cos_queue_t cosq,
   1868                              uint32 color,
   1869                              int drop_start,
   1870                              int drop_slope,
   1871                              int average_time)
   1872 {
   1873     bcm_module_t modid;
   1874     bcm_port_t local_port;
   1875     bcm_trunk_t trunk_id;
   1876     bcm_pbmp_t pbmp;
   1877     int i, gain, cosq_start, num_cosq;
   1878     uint32 min_thresh, max_thresh, shared_limit;
   1879     uint32 rval, bits;
   1880 
   1881     if (!_tr_num_port_cosq[unit]) {
   1882         return BCM_E_INIT;
   1883     }
   1884 
   1885     if (drop_start < 0 || drop_start > 100 ||
   1886         drop_slope < 0 || drop_slope > 90) {
   1887         return BCM_E_PARAM;
   1888     }
   1889 
   1890     if (BCM_GPORT_IS_SET(port)) {
   1891         if (BCM_GPORT_IS_SCHEDULER(port)) {
   1892             BCM_IF_ERROR_RETURN
   1893                 (_bcm_tr_cosq_resolve_mod_port(unit, port, &modid,
   1894                                                &local_port, &trunk_id));
   1895         } else {
   1896             BCM_IF_ERROR_RETURN
   1897                 (bcm_esw_port_local_get(unit, port, &local_port));
   1898         }
   1899         BCM_PBMP_PORT_SET(pbmp, local_port);
   1900     } else {
   1901         if (port == -1) {
   1902             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   1903         } else if (IS_CPU_PORT(unit, port) || !SOC_PORT_VALID(unit, port)) {
   1904             return BCM_E_PORT;
   1905         } else {
   1906             BCM_PBMP_PORT_SET(pbmp, port);
   1907             local_port = port;
   1908         }
   1909     }
   1910 
   1911     if (BCM_GPORT_IS_SCHEDULER(port)) {
   1912         if (_tr_num_port_cosq[unit][local_port] == 0) {
   1913             return BCM_E_NOT_FOUND;
   1914         } else if (cosq < -1 || cosq >= _tr_num_port_cosq[unit][local_port]) {
   1915             return BCM_E_PARAM;
   1916         } else if (cosq == -1) {
   1917             cosq_start = 8;
   1918             num_cosq = _tr_num_port_cosq[unit][local_port];
   1919         } else {
   1920             cosq_start = cosq + 8;
   1921             num_cosq = 1;
   1922         }
   1923     } else {
   1924         if (cosq < -1 || cosq >= _tr_num_cosq[unit]) {
   1925             return BCM_E_PARAM;
   1926         } else if (cosq == -1) {
   1927             cosq_start = 0;
   1928             num_cosq = 8;
   1929         } else {
   1930             cosq_start = cosq;
   1931             num_cosq = 1;
   1932         }
   1933     }
   1934 
   1935     /*
   1936      * average queue size is reculated every 4us, the formula is
   1937      * avg_qsize(t + 1) =
   1938      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   1939      * gain = log2(average_time / 4)
   1940      */
   1941     bits = (average_time / 4) & 0xffff;
   1942     bits |= bits >> 1;
   1943     bits |= bits >> 2;
   1944     bits |= bits >> 4;
   1945     bits |= bits >> 8;
   1946     gain = _shr_popcount(bits);
   1947     /* Don't allow negative value of gain */
   1948     if (gain) {
   1949         gain -= 1;
   1950     }
   1951 
   1952     /*
   1953      * per-port packet limit may be disabled.
   1954      * per-port per-cos packet limit may be set to use dynamic method.
   1955      * therefore drop_start percentage is based on per-device total shared
   1956      * packets.
   1957      */
   1958     SOC_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMIT_PACKETr(unit, &rval));
   1959     shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMIT_PACKETr,
   1960                                      rval, OP_BUFFER_SHARED_LIMIT_PACKETf);
   1961     min_thresh = drop_start * shared_limit / 100;
   1962 
   1963     /* Calculate the max threshold. For a given slope (angle in 
   1964      * degrees), determine how many packets are in the range from
   1965      * 0% drop probability to 100% drop probability. Add that
   1966      * number to the min_treshold to the the max_threshold.
   1967      */
   1968     max_thresh = min_thresh + _bcm_tr_angle_to_packets(drop_slope);
   1969     if (max_thresh > TR_PACKET_FIELD_MAX(unit)) {
   1970         max_thresh = TR_PACKET_FIELD_MAX(unit);
   1971     }
   1972 
   1973     BCM_PBMP_ITER(pbmp, local_port) {
   1974         for (i = cosq_start; i < (cosq_start + num_cosq); i++) { 
   1975             BCM_IF_ERROR_RETURN
   1976                 (_bcm_tr_cosq_discard_set(unit, local_port, color, i,
   1977                                           WREDCONFIG_PACKETr,
   1978                                           WREDPARAM_PACKETr,
   1979                                           WREDPARAM_YELLOW_PACKETr,
   1980                                           WREDPARAM_RED_PACKETr,
   1981                                           WREDPARAM_NONTCP_PACKETr,
   1982                                           min_thresh, max_thresh, 100, gain));
   1983         }
   1984     }
   1985     return BCM_E_NONE;
   1986 }
   1987 
   1988 int
   1989 bcm_tr_cosq_discard_port_get(int unit, bcm_port_t port,
   1990                              bcm_cos_queue_t cosq,
   1991                              uint32 color,
   1992                              int *drop_start,
   1993                              int *drop_slope,
   1994                              int *average_time)
   1995 {
   1996     bcm_module_t modid;
   1997     bcm_port_t local_port;
   1998     bcm_trunk_t trunk_id;
   1999     bcm_pbmp_t pbmp;
   2000     int gain, drop_prob;
   2001     uint32 min_thresh, max_thresh, shared_limit;
   2002     uint32 rval;
   2003 
   2004     if (!_tr_num_port_cosq[unit]) {
   2005         return BCM_E_INIT;
   2006     }
   2007 
   2008     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   2009         return BCM_E_PARAM;
   2010     }
   2011 
   2012     if (BCM_GPORT_IS_SET(port)) {
   2013         if (BCM_GPORT_IS_SCHEDULER(port)) {
   2014             BCM_IF_ERROR_RETURN
   2015                 (_bcm_tr_cosq_resolve_mod_port(unit, port, &modid,
   2016                                                &local_port, &trunk_id));
   2017         } else {
   2018             BCM_IF_ERROR_RETURN
   2019                 (bcm_esw_port_local_get(unit, port, &local_port));
   2020         }
   2021         BCM_PBMP_PORT_SET(pbmp, local_port);
   2022     } else {
   2023         if (port == -1) {
   2024 #ifdef BCM_ENDURO_SUPPORT
   2025             if (SOC_IS_ENDURO(unit)) {
   2026                 BCM_PBMP_ASSIGN(pbmp, PBMP_E_ALL(unit));
   2027             } else 		
   2028 #endif /* BCM_ENDURO_SUPPORT */
   2029             {
   2030                 BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   2031             }
   2032         } else if (IS_CPU_PORT(unit, port) || !SOC_PORT_VALID(unit, port)) {
   2033             return BCM_E_PORT;
   2034         } else {
   2035             BCM_PBMP_PORT_SET(pbmp, port);
   2036             local_port = port;
   2037         }
   2038     }
   2039 
   2040     if (BCM_GPORT_IS_SCHEDULER(port)) {
   2041         if (_tr_num_port_cosq[unit][local_port] == 0) {
   2042             return BCM_E_NOT_FOUND;
   2043         } else if (cosq < -1 || cosq >= _tr_num_port_cosq[unit][local_port]) {
   2044             return BCM_E_PARAM;
   2045         } else if (cosq == -1) {
   2046             cosq = 8;
   2047         } else {
   2048             cosq = cosq + 8;
   2049         }
   2050     } else {
   2051         if (cosq < -1 || cosq >= _tr_num_cosq[unit]) {
   2052             return BCM_E_PARAM;
   2053         } else if (cosq == -1) {
   2054             cosq = 0;
   2055         }
   2056     }
   2057 
   2058     BCM_PBMP_ITER(pbmp, local_port) {
   2059         BCM_IF_ERROR_RETURN
   2060             (_bcm_tr_cosq_discard_get(unit, local_port, color, cosq,
   2061                                       WREDCONFIG_PACKETr,
   2062                                       WREDPARAM_PACKETr,
   2063                                       WREDPARAM_YELLOW_PACKETr,
   2064                                       WREDPARAM_RED_PACKETr,
   2065                                       WREDPARAM_NONTCP_PACKETr,
   2066                                       &min_thresh, &max_thresh, &drop_prob,
   2067                                       &gain));
   2068 
   2069         /*
   2070          * average queue size is reculated every 4us, the formula is
   2071          * avg_qsize(t + 1) =
   2072          *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   2073          */
   2074         *average_time = (1 << gain) * 4;
   2075 
   2076         /*
   2077          * per-port packet limit may be disabled.
   2078          * per-port per-cos packet limit may be set to use dynamic method.
   2079          * therefore drop_start percentage is based on per-device total shared
   2080          * packets.
   2081          */
   2082         SOC_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMIT_PACKETr(unit, &rval));
   2083         shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMIT_PACKETr,
   2084                                          rval, OP_BUFFER_SHARED_LIMIT_PACKETf);
   2085         if (min_thresh >= shared_limit) {
   2086             *drop_start = 100;
   2087         } else {
   2088             *drop_start = min_thresh * 100 / shared_limit;
   2089         }
   2090 
   2091         /* Calculate the slope using the min and max threshold.
   2092          * The angle is calculated knowing drop probability at min
   2093          * threshold is 0% and drop probability at max threshold is 100%.
   2094          */
   2095         *drop_slope = _bcm_tr_packets_to_angle(max_thresh - min_thresh);
   2096         break;
   2097     }
   2098 
   2099     return BCM_E_NONE;
   2100 }
   2101 
   2102 STATIC int
   2103 _bcm_tr_cosq_port_sched_set(int unit, soc_reg_t config_reg,
   2104                             soc_reg_t weight_reg, soc_reg_t minsp_reg,
   2105                             bcm_port_t port, bcm_cos_queue_t start_cosq,
   2106                             int num_weights, const int weights[],
   2107                             int mode)
   2108 {
   2109     int t, i;
   2110     uint32 cfg_addr, cosw_addr, minsp_addr, cfg, cosw, minsp;
   2111     int mbits = 0;
   2112     int weight_max, sel, quanta;
   2113 
   2114     cfg_addr = soc_reg_addr(unit, config_reg, port, 0);
   2115     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, cfg_addr, &cfg));
   2116 
   2117     switch (mode) {
   2118     case BCM_COSQ_STRICT:
   2119         mbits = 0;
   2120         break;
   2121     case BCM_COSQ_ROUND_ROBIN:
   2122         mbits = 1;
   2123         break;
   2124     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   2125         mbits = 2;
   2126         /*
   2127          * All weight values must fit within 7 bits.
   2128          * If weight is 0, this queue is run in strict mode,
   2129          * others run in WRR mode.
   2130          */
   2131         for(i = 0; i < num_weights; i++) {
   2132             if (weights[i] > TR_WRR_WEIGHT_MAX) {
   2133                 return BCM_E_PARAM;
   2134             }
   2135         }
   2136         for (i = 0; i < num_weights; i++) {
   2137             cosw_addr = soc_reg_addr(unit, weight_reg, port, start_cosq + i);
   2138             SOC_IF_ERROR_RETURN(soc_reg32_read(unit, cosw_addr, &cosw));
   2139             soc_reg_field_set(unit, weight_reg, &cosw, COSWEIGHTSf,
   2140                               weights[i]);
   2141             SOC_IF_ERROR_RETURN(soc_reg32_write(unit, cosw_addr, cosw));
   2142         }
   2143         break;
   2144     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   2145         mbits = 3;
   2146 
   2147         weight_max = 0;
   2148         for (i = 0; i < num_weights; i++) {
   2149             if (weight_max < weights[i]) {
   2150                 weight_max = weights[i];
   2151             }
   2152         }
   2153 
   2154         for (sel = 0; sel <= 3; sel++) {
   2155             if (weight_max <= TR_DRR_WEIGHT_MAX * (1 << (sel + 1))) {
   2156                 break;
   2157             }
   2158         }
   2159         if (sel > 3) {
   2160             return BCM_E_PARAM;
   2161         }
   2162         quanta = 1 << (sel + 1);
   2163         soc_reg_field_set(unit, config_reg, &cfg, MTU_QUANTA_SELECTf, sel);
   2164         for (i = 0; i < num_weights; i++) {
   2165             cosw_addr = soc_reg_addr(unit, weight_reg, port, start_cosq + i);
   2166             SOC_IF_ERROR_RETURN(soc_reg32_read(unit, cosw_addr, &cosw));
   2167             /* the unit of weight for WDRR is specified mtu quanta */
   2168             soc_reg_field_set(unit, weight_reg, &cosw, COSWEIGHTSf,
   2169                               (weights[i] + quanta - 1) / quanta);
   2170             SOC_IF_ERROR_RETURN(soc_reg32_write(unit, cosw_addr, cosw));
   2171         }
   2172         break;
   2173     case BCM_COSQ_BOUNDED_DELAY:        /* not supported in xgs */
   2174     default:
   2175         return BCM_E_PARAM;
   2176     }
   2177 
   2178     if ((mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) ||
   2179         (mode == BCM_COSQ_DEFICIT_ROUND_ROBIN)) {
   2180         /* Set strict priority bit if weight is zero */
   2181         minsp_addr = soc_reg_addr(unit, minsp_reg, port, 0);
   2182         SOC_IF_ERROR_RETURN
   2183             (soc_reg32_read(unit, minsp_addr, &minsp));
   2184         for(i = 0; i < num_weights; i++) {
   2185             t = start_cosq + i;
   2186             if (weights[i] == 0) {
   2187                 minsp |= (1 << t);
   2188             } else {
   2189                 minsp &= ~(1 << t);
   2190             }
   2191         }
   2192         SOC_IF_ERROR_RETURN
   2193             (soc_reg32_write(unit, minsp_addr, minsp));
   2194     }
   2195 
   2196     /* Program the scheduling mode */
   2197     soc_reg_field_set(unit, config_reg, &cfg, SCHEDULING_SELECTf, mbits);
   2198     SOC_IF_ERROR_RETURN(soc_reg32_write(unit, cfg_addr, cfg));
   2199 
   2200     return BCM_E_NONE;
   2201 }
   2202 
   2203 STATIC int
   2204 _bcm_tr_cosq_port_sched_get(int unit, soc_reg_t config_reg,
   2205                             soc_reg_t weight_reg, bcm_port_t port,
   2206                             bcm_cos_queue_t start_cosq,
   2207                             int num_weights, int weights[], int *mode)
   2208 {
   2209     uint32 addr, cfg, cosw;
   2210     int mbits, i;
   2211     uint32 quanta;
   2212 
   2213     addr = soc_reg_addr(unit, config_reg, port, 0);
   2214     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &cfg));
   2215     mbits = soc_reg_field_get(unit, config_reg, cfg, SCHEDULING_SELECTf);
   2216 
   2217     switch (mbits) {
   2218     case 0:
   2219         *mode = BCM_COSQ_STRICT;
   2220         break;
   2221     case 1:
   2222         *mode = BCM_COSQ_ROUND_ROBIN;
   2223         break;
   2224     case 2:
   2225         *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   2226         for (i = 0; i < num_weights; i++) {
   2227             addr = soc_reg_addr(unit, weight_reg, port, start_cosq + i);
   2228             SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &cosw));
   2229             weights[i] = soc_reg_field_get(unit, weight_reg, cosw,
   2230                                            COSWEIGHTSf);
   2231         }
   2232         break;
   2233     case 3:
   2234         *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   2235         switch (soc_reg_field_get(unit, config_reg, cfg, MTU_QUANTA_SELECTf)) {
   2236         case 0: /* quanta is 2k bytes */
   2237             quanta = 2;
   2238             break;
   2239         case 1: /* quanta is 4k bytes */
   2240             quanta = 4;
   2241             break;
   2242         case 2: /* quanta is 8k bytes */
   2243             quanta = 8;
   2244             break;
   2245         case 3: /* quanta is 16k bytes */
   2246             quanta = 16;
   2247             break;
   2248         default:
   2249             return SOC_E_INTERNAL;
   2250         }
   2251         for (i = 0; i < num_weights; i++) {
   2252             addr = soc_reg_addr(unit, weight_reg, port, start_cosq + i);
   2253             SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &cosw));
   2254             /* the unit of weight for WDRR is specified mtu quanta */
   2255             weights[i] = soc_reg_field_get(unit, weight_reg, cosw,
   2256                                            COSWEIGHTSf) * quanta;
   2257         }
   2258         break;
   2259     default:
   2260         return BCM_E_INTERNAL;
   2261     }
   2262 
   2263     return BCM_E_NONE;
   2264 }
   2265 
   2266 /*
   2267  * Function:
   2268  *      bcm_cosq_port_sched_set
   2269  * Purpose:
   2270  *      Set up class-of-service policy and corresponding weights and delay
   2271  * Parameters:
   2272  *      unit - StrataSwitch unit number.
   2273  *      pbm - port bitmap
   2274  *      mode - Scheduling mode, one of BCM_COSQ_xxx
   2275  *      weights - Weights for each COS queue
   2276  *                Only for BCM_COSQ_WEIGHTED_FAIR_ROUND_ROBIN mode.
   2277  *                For DRR Weight is specified in Kbytes
   2278  *      delay - This parameter is not used 
   2279  * Returns:
   2280  *      BCM_E_XXX
   2281  */
   2282 
   2283 int
   2284 bcm_tr_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
   2285                            int mode, const int weights[], int delay)
   2286 {
   2287     bcm_port_t port;
   2288     uint32 rval, mbits;
   2289     int i,max_weight;
   2290 
   2291     mbcm_driver[unit]->mbcm_cosq_sched_weight_max_get(unit, mode, &max_weight);
   2292     if((mode != BCM_COSQ_STRICT) && (mode != BCM_COSQ_ROUND_ROBIN) &&
   2293              (max_weight != BCM_COSQ_WEIGHT_UNLIMITED)) {
   2294         for(i = 0; i < NUM_COS(unit); i++) {
   2295             if((weights[i] < 0) || (weights[i] > max_weight)) {
   2296                 return BCM_E_PARAM;
   2297             }
   2298         }
   2299     }
   2300 
   2301     PBMP_ITER(pbm, port) {
   2302         /* coverity[overrun-local : FALSE] */
   2303         if (IS_CPU_PORT(unit, port) && !SOC_IS_ENDURO(unit)) {
   2304             switch (mode) {
   2305             case BCM_COSQ_STRICT:
   2306                 mbits = 0;
   2307                 break;
   2308             case BCM_COSQ_ROUND_ROBIN:
   2309                 mbits = 1;
   2310                 break;
   2311             case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   2312             case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   2313                 if (BCM_PBMP_NEQ(pbm, PBMP_CMIC(unit))) {
   2314                     continue;
   2315                 }
   2316                 return BCM_E_PARAM;
   2317             default:
   2318                 return BCM_E_PARAM;
   2319             }
   2320 
   2321             if (SOC_IS_TR_VL(unit)) {
   2322                 SOC_IF_ERROR_RETURN(READ_ES_CPU_SCHEDULERr(unit, &rval));
   2323                 soc_reg_field_set(unit, ES_CPU_SCHEDULERr, &rval, MODEf,
   2324                                   mbits);
   2325                 SOC_IF_ERROR_RETURN(WRITE_ES_CPU_SCHEDULERr(unit, rval));
   2326                 continue;
   2327             } /* Scorpion uses the call below for allowed modes on CPU */
   2328         }
   2329     
   2330         BCM_IF_ERROR_RETURN
   2331             (_bcm_tr_cosq_port_sched_set(unit,
   2332                                          ESCONFIGr, COSWEIGHTSr,
   2333                                          MINSPCONFIGr,
   2334                                          port, 0, 8, weights, mode));
   2335     }
   2336     return BCM_E_NONE;
   2337 }
   2338 
   2339 /*
   2340  * Function:
   2341  *      bcm_cosq_port_sched_get
   2342  * Purpose:
   2343  *      Retrieve class-of-service policy and corresponding weights and delay
   2344  * Parameters:
   2345  *      unit     - StrataSwitch unit number.
   2346  *      pbm      - port bitmap
   2347  *      mode     - (output) Scheduling mode, one of BCM_COSQ_xxx
   2348  *      weights  - (output) Weights for each COS queue
   2349  *                          Only for BCM_COSQ_WEIGHTED_ROUND_ROBIN and
   2350  *                          BCM_COSQ_DEFICIT_ROUND_ROBIN mode.
   2351  *                 For DRR Weight is specified in Kbytes
   2352  *      delay    - This parameter is not used
   2353  * Returns:
   2354  *      BCM_E_XXX
   2355  * Notes:
   2356  *      Actually just returns data for the first port in the bitmap
   2357  */
   2358 
   2359 int
   2360 bcm_tr_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
   2361                            int *mode, int weights[], int *delay)
   2362 {
   2363     bcm_port_t port;
   2364     uint32 rval;
   2365 
   2366     PBMP_ITER(pbm, port) {
   2367         /* coverity[overrun-local : FALSE] */
   2368         if (IS_CPU_PORT(unit, port)) {
   2369             if (BCM_PBMP_NEQ(pbm, PBMP_CMIC(unit))) {
   2370                 continue;
   2371             }
   2372             if (SOC_IS_TR_VL(unit) && !SOC_IS_ENDURO(unit)) {
   2373                 SOC_IF_ERROR_RETURN(READ_ES_CPU_SCHEDULERr(unit, &rval));
   2374                 if (soc_reg_field_get(unit, ES_CPU_SCHEDULERr,
   2375                                       rval, MODEf)) {
   2376                     *mode = BCM_COSQ_ROUND_ROBIN;
   2377                 } else {
   2378                     *mode = BCM_COSQ_STRICT;
   2379                 }
   2380                 return BCM_E_NONE;
   2381             } /* Scorpion uses the call below for CPU */
   2382         }
   2383         BCM_IF_ERROR_RETURN
   2384             (_bcm_tr_cosq_port_sched_get(unit, ESCONFIGr, COSWEIGHTSr,
   2385                                          port, 0, 8, weights, mode));
   2386         break;
   2387     }
   2388     return BCM_E_NONE;
   2389 }
   2390 
   2391 /*
   2392  * Function:
   2393  *      bcm_tr_cosq_sched_weight_max_get
   2394  * Purpose:
   2395  *      Retrieve maximum weights for given COS policy.
   2396  * Parameters:
   2397  *      unit - StrataSwitch unit number.
   2398  *      mode - Scheduling mode, one of BCM_COSQ_xxx
   2399  *      weight_max - (output) Maximum weight for COS queue.
   2400  *              For DRR mode Weight is specified in Kbytes
   2401  *              0 if mode is BCM_COSQ_STRICT.
   2402  *              1 if mode is BCM_COSQ_ROUND_ROBIN.
   2403  *              -1 if not applicable to mode.
   2404  * Returns:
   2405  *      BCM_E_XXX
   2406  */
   2407 
   2408 int
   2409 bcm_tr_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   2410 {
   2411     switch (mode) {
   2412     case BCM_COSQ_STRICT:
   2413         *weight_max = BCM_COSQ_WEIGHT_STRICT;
   2414         break;
   2415     case BCM_COSQ_ROUND_ROBIN:
   2416         *weight_max = BCM_COSQ_WEIGHT_MIN;
   2417         break;
   2418     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   2419         *weight_max = TR_WRR_WEIGHT_MAX;
   2420         break;
   2421     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   2422         *weight_max = TR_DRR_WEIGHT_MAX * 16; /* Maximum MTU quanta */
   2423         break;
   2424     default:
   2425         *weight_max = BCM_COSQ_WEIGHT_UNLIMITED;
   2426         return BCM_E_PARAM;
   2427     }
   2428 
   2429     return BCM_E_NONE;
   2430 }
   2431 
   2432 /*
   2433  * Function:
   2434  *      bcm_cosq_gport_add
   2435  * Purpose:
   2436  *
   2437  * Parameters:
   2438  *      unit - (IN) Unit number.
   2439  *      port - (IN) Physical port.
   2440  *      numq - (IN) Number of COS queues.
   2441  *      flags - (IN) Flags.
   2442  *      gport - (IN/OUT) GPORT ID.
   2443  * Returns:
   2444  *      BCM_E_XXX
   2445  */     
   2446 int 
   2447 bcm_tr_cosq_gport_add(int unit, bcm_gport_t port, int numq,
   2448                       uint32 flags, bcm_gport_t *gport)
   2449 {
   2450     bcm_module_t modid, mod_out;
   2451     bcm_port_t local_port, port_out;
   2452     bcm_trunk_t trunk_id;
   2453     int gport_id;
   2454 
   2455     if ((numq <= 0) || (numq > 16) ||
   2456         (!BCM_GPORT_IS_LOCAL(port) && !BCM_GPORT_IS_MODPORT(port))) {
   2457         return BCM_E_PARAM;
   2458     }
   2459     if (flags & (BCM_COSQ_GPORT_WITH_ID | BCM_COSQ_GPORT_OVERLAY | 
   2460         BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_MCAST_QUEUE |
   2461         BCM_COSQ_GPORT_MCAST_QUEUE_GROUP | BCM_COSQ_GPORT_SUBSCRIBER |
   2462         BCM_COSQ_GPORT_EGRESS_GROUP | BCM_COSQ_GPORT_DISABLE |
   2463         BCM_COSQ_GPORT_CALENDAR)) {
   2464         return BCM_E_UNAVAIL;
   2465     }
   2466 
   2467     BCM_IF_ERROR_RETURN
   2468         (_bcm_tr_cosq_resolve_mod_port(unit, port, &modid,
   2469                                        &local_port, &trunk_id));
   2470 
   2471     /* Verify that the specified port is for my modid and that 
   2472      * it is capable of hierarchical queueing.
   2473      */
   2474     if (!_tr_num_port_cosq[unit]) {
   2475         return BCM_E_INIT;
   2476     } else if (!SOC_PBMP_MEMBER(_tr_cosq_24q_ports[unit], local_port)) {
   2477         return BCM_E_PORT;
   2478     } else if (_tr_num_port_cosq[unit][local_port]) {
   2479         return BCM_E_EXISTS;
   2480     }
   2481     /* Call delete routine to init HW settings */
   2482     BCM_IF_ERROR_RETURN (_bcm_tr_cosq_gport_delete(unit, local_port));
   2483 
   2484     _tr_num_port_cosq[unit][local_port] = numq;
   2485 
   2486     /* The GPORT ID for SCHEDULER is the modid/port from application
   2487      * space. This allows the GPORT ID to be used on remote module
   2488      * API calls. Convert from local space to application space.
   2489      */
   2490     BCM_IF_ERROR_RETURN
   2491         (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   2492                                 modid, local_port, &mod_out, &port_out));
   2493     gport_id = (mod_out << 8) | port_out;
   2494     BCM_GPORT_SCHEDULER_SET(*gport, gport_id);
   2495     return BCM_E_NONE;
   2496 }
   2497  
   2498 STATIC int
   2499 _bcm_tr_cosq_gport_delete(int unit, bcm_port_t port)
   2500 {
   2501     int cosq, weights[16];
   2502     uint32 val;
   2503 
   2504     /* Detach from physical port */
   2505     BCM_IF_ERROR_RETURN
   2506         (soc_reg_field32_modify(unit, COS_MODEr, port, SELECTf, 0x0));
   2507     BCM_IF_ERROR_RETURN
   2508         (soc_reg_field32_modify(unit, ING_COS_MODEr, port, SELECTf, 0x0));
   2509 
   2510     /* Clear bandwidth of all Stage1 COSQs */
   2511     for (cosq = 8; cosq < 24; cosq++) {
   2512         BCM_IF_ERROR_RETURN
   2513             (bcm_tr_cosq_port_bandwidth_set(unit, port, cosq, 0, 0, 0, 0));
   2514     }
   2515 
   2516     /* Clear bandwidth of S1 output queue */
   2517     cosq = 24;
   2518     BCM_IF_ERROR_RETURN
   2519         (bcm_tr_cosq_port_bandwidth_set(unit, port, cosq, 0, 0, 0, 0));
   2520 
   2521     /* Clear weights of all Stage1 COSQs */
   2522     for (cosq = 0; cosq < 16; cosq++) {
   2523         weights[cosq] = 0;
   2524     }
   2525     BCM_IF_ERROR_RETURN
   2526         (_bcm_tr_cosq_port_sched_set(unit, S1V_CONFIGr, S1V_COSWEIGHTSr,
   2527                                      S1V_MINSPCONFIGr, port, 0, 16,
   2528                                      weights, BCM_COSQ_WEIGHTED_ROUND_ROBIN));
   2529 
   2530     /* Clear weight for S1 output queue */
   2531     cosq = 8;
   2532     BCM_IF_ERROR_RETURN(READ_COSWEIGHTSr(unit, port, cosq, &val));
   2533     soc_reg_field_set(unit, COSWEIGHTSr, &val, COSWEIGHTSf, 0);
   2534     BCM_IF_ERROR_RETURN(WRITE_COSWEIGHTSr(unit, port, cosq, val));
   2535 
   2536     /* Clear discard settings for all Stage1 COSQs */
   2537     for (cosq = 8; cosq < 24; cosq++) {
   2538         BCM_IF_ERROR_RETURN
   2539             (_bcm_tr_cosq_discard_set(unit, port, 
   2540                                       BCM_COSQ_DISCARD_COLOR_ALL | 
   2541                                       BCM_COSQ_DISCARD_NONTCP, cosq,
   2542                                       WREDCONFIG_PACKETr,
   2543                                       WREDPARAM_PACKETr,
   2544                                       WREDPARAM_YELLOW_PACKETr,
   2545                                       WREDPARAM_RED_PACKETr,
   2546                                       WREDPARAM_NONTCP_PACKETr,
   2547                                       TR_PACKET_FIELD_MAX(unit), 
   2548                                       TR_PACKET_FIELD_MAX(unit), 100, 0));
   2549     }
   2550 
   2551     _tr_num_port_cosq[unit][port] = 0;
   2552 
   2553     return BCM_E_NONE;
   2554 }
   2555 
   2556 /*      
   2557  * Function:
   2558  *      bcm_cosq_gport_delete
   2559  * Purpose:
   2560  *      
   2561  * Parameters:
   2562  *      unit - (IN) Unit number.
   2563  *      gport - (IN) GPORT ID.
   2564  * Returns:
   2565  *      BCM_E_XXX
   2566  */
   2567 int
   2568 bcm_tr_cosq_gport_delete(int unit, bcm_gport_t gport)
   2569 {
   2570     bcm_module_t modid;
   2571     bcm_port_t local_port;
   2572     bcm_trunk_t trunk_id;
   2573 
   2574     BCM_IF_ERROR_RETURN
   2575         (_bcm_tr_cosq_resolve_mod_port(unit, gport, &modid,
   2576                                        &local_port, &trunk_id));
   2577     if (BCM_GPORT_IS_SCHEDULER(gport)) {
   2578         if (!_tr_num_port_cosq[unit]) {
   2579             return BCM_E_INIT;
   2580         } else if (_tr_num_port_cosq[unit][local_port] == 0) {
   2581             return BCM_E_NOT_FOUND;
   2582         }
   2583     } else if(BCM_GPORT_IS_LOCAL(gport) ||
   2584             BCM_GPORT_IS_MODPORT(gport)) {
   2585         if (!_tr_num_port_cosq[unit]) {
   2586             return BCM_E_INIT;
   2587         }
   2588     } else {
   2589         return BCM_E_PARAM;
   2590     }
   2591     BCM_IF_ERROR_RETURN (_bcm_tr_cosq_gport_delete(unit, local_port));
   2592     return BCM_E_NONE;
   2593 }
   2594     
   2595 /*
   2596  * Function:
   2597  *      bcm_cosq_gport_traverse
   2598  * Purpose:
   2599  *      Walks through the valid COSQ GPORTs and calls
   2600  *      the user supplied callback function for each entry.
   2601  * Parameters:
   2602  *      unit       - (IN) bcm device.
   2603  *      trav_fn    - (IN) Callback function.
   2604  *      user_data  - (IN) User data to be passed to callback function.
   2605  * Returns:
   2606  *      BCM_E_NONE - Success.
   2607  *      BCM_E_XXX
   2608  */
   2609 int     
   2610 bcm_tr_cosq_gport_traverse(int unit, bcm_cosq_gport_traverse_cb cb,
   2611                            void *user_data)
   2612 {
   2613     bcm_module_t my_modid, mod_out;
   2614     bcm_port_t port, port_out;
   2615     bcm_gport_t gport, sched_gport;
   2616     int gport_id;
   2617     uint32 flags = BCM_COSQ_GPORT_SCHEDULER;
   2618     int rv = SOC_E_NONE;
   2619 
   2620     if (_tr_num_port_cosq[unit]) {
   2621         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   2622         BCM_PBMP_ITER(_tr_cosq_24q_ports[unit], port) {
   2623             if (_tr_num_port_cosq[unit][port]) {
   2624 
   2625                 /* Construct physical port GPORT ID */
   2626                 BCM_IF_ERROR_RETURN
   2627                     (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   2628                                             my_modid, port, &mod_out, &port_out));
   2629                 BCM_GPORT_MODPORT_SET(gport, mod_out, port_out);
   2630 
   2631                 /* Construct scheduler GPORT ID */
   2632                 gport_id = (mod_out << 8) | port_out;
   2633                 BCM_GPORT_SCHEDULER_SET(sched_gport, gport_id);
   2634 
   2635                 /* Call application call-back */
   2636                 rv = cb(unit, gport, _tr_num_port_cosq[unit][port],
   2637                         flags, sched_gport, user_data);
   2638                if (BCM_FAILURE(rv)) {
   2639 #ifdef BCM_CB_ABORT_ON_ERR
   2640                    if (SOC_CB_ABORT_ON_ERR(unit)) {
   2641                        return rv;
   2642                    }
   2643 #endif
   2644                }
   2645             }
   2646         } 
   2647     } else {
   2648         return BCM_E_INIT;
   2649     }
   2650     return BCM_E_NONE;
   2651 }
   2652 
   2653 STATIC int
   2654 _bcm_tr_cosq_gport_bandwidth_port_resolve(int unit, bcm_gport_t gport,
   2655                                           bcm_cos_queue_t cosq,
   2656                                           bcm_port_t *local_port,
   2657                                           bcm_cos_queue_t *cosq_start,
   2658                                           bcm_cos_queue_t *cosq_end)
   2659 {
   2660     bcm_module_t modid;
   2661     bcm_trunk_t trunk_id;
   2662 
   2663     if (BCM_GPORT_IS_SET(gport)) {
   2664         BCM_IF_ERROR_RETURN
   2665             (_bcm_tr_cosq_resolve_mod_port(unit, gport, &modid,
   2666                                            local_port, &trunk_id));
   2667     } else {
   2668         *local_port = gport;
   2669         if (!SOC_PORT_VALID(unit, gport)) {
   2670             return BCM_E_PORT;
   2671         }
   2672     }
   2673 
   2674     if (!_tr_num_port_cosq[unit]) {
   2675         return BCM_E_INIT;
   2676     }
   2677 
   2678     if (cosq < -1) {
   2679         return BCM_E_PARAM;
   2680     }
   2681 
   2682     if (BCM_GPORT_IS_SCHEDULER(gport)) {
   2683         if (_tr_num_port_cosq[unit][*local_port] == 0) {
   2684             return BCM_E_NOT_FOUND;
   2685         } else if (cosq < 0) {
   2686             *cosq_start = 8;
   2687             *cosq_end = 23;
   2688         } else if (cosq >= _tr_num_port_cosq[unit][*local_port]) {
   2689             return BCM_E_PARAM;
   2690         } else {
   2691             *cosq_start = *cosq_end = (cosq + 8);
   2692         }
   2693     } else if (cosq == TR_SCHEDULER_COSQ) {
   2694         if (!SOC_PBMP_MEMBER(_tr_cosq_24q_ports[unit], *local_port)) {
   2695             return BCM_E_PORT;
   2696         }
   2697         /* Output of S1 scheduler is configured using register offset 24 */
   2698         *cosq_start = *cosq_end = 24;
   2699     } else {
   2700         if (IS_CPU_PORT(unit, *local_port)) {
   2701             if (cosq >=  NUM_CPU_COSQ(unit)) {
   2702                 return BCM_E_PARAM;
   2703             } else if (cosq < 0) {
   2704                 *cosq_start = 0;
   2705                 *cosq_end =  NUM_CPU_COSQ(unit) - 1 ; 
   2706             } else {
   2707                 *cosq_start = *cosq_end = cosq;
   2708             }
   2709         } else {
   2710             if (cosq >= _tr_num_cosq[unit]) {
   2711                 return BCM_E_PARAM;
   2712             } else if (cosq < 0) {
   2713                 *cosq_start = 0;
   2714                 *cosq_end = 7;
   2715             } else {
   2716                 *cosq_start = *cosq_end = cosq;
   2717             }
   2718         }
   2719     }
   2720 
   2721     return BCM_E_NONE;
   2722 }
   2723 
   2724 /*  
   2725  * Function:
   2726  *      bcm_cosq_gport_bandwidth_set
   2727  * Purpose:
   2728  *       
   2729  * Parameters:
   2730  *      unit - (IN) Unit number.
   2731  *      gport - (IN) GPORT ID.
   2732  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   2733  *      kbits_sec_min - (IN) minimum bandwidth, kbits/sec.
   2734  *      kbits_sec_max - (IN) maximum bandwidth, kbits/sec.
   2735  *      flags - (IN) BCM_COSQ_BW_*
   2736  * Returns:
   2737  *      BCM_E_XXX 
   2738  */ 
   2739 int
   2740 bcm_tr_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
   2741                                 bcm_cos_queue_t cosq, uint32 kbits_sec_min,
   2742                                 uint32 kbits_sec_max, uint32 flags)
   2743 {
   2744     bcm_port_t local_port;
   2745     int i;
   2746     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
   2747 
   2748     BCM_IF_ERROR_RETURN
   2749         (_bcm_tr_cosq_gport_bandwidth_port_resolve(unit, gport, cosq,
   2750                                                    &local_port,
   2751                                                    &cosq_start, &cosq_end));
   2752 
   2753     for (i = cosq_start; i <= cosq_end; i++) {
   2754         BCM_IF_ERROR_RETURN
   2755             (bcm_tr_cosq_port_bandwidth_set(unit, local_port, i,
   2756                                             kbits_sec_min,
   2757                                             kbits_sec_max,
   2758                                             kbits_sec_max,
   2759                                             flags));
   2760     }
   2761     return BCM_E_NONE;
   2762 }
   2763 
   2764 /*
   2765  * Function:
   2766  *      bcm_cosq_gport_bandwidth_get
   2767  * Purpose:
   2768  *
   2769  * Parameters:
   2770  *      unit - (IN) Unit number.
   2771  *      gport - (IN) GPORT ID.
   2772  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   2773  *      kbits_sec_min - (OUT) minimum bandwidth, kbits/sec.
   2774  *      kbits_sec_max - (OUT) maximum bandwidth, kbits/sec.
   2775  *      flags - (OUT) BCM_COSQ_BW_*
   2776  * Returns:
   2777  *      BCM_E_XXX
   2778  */
   2779 int
   2780 bcm_tr_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
   2781                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
   2782                                 uint32 *kbits_sec_max, uint32 *flags)
   2783 {
   2784     bcm_port_t local_port;
   2785     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
   2786     uint32 kbits_sec_burst;    /* Dummy variable */
   2787 
   2788     *kbits_sec_min = *kbits_sec_max = *flags = 0;
   2789 
   2790     BCM_IF_ERROR_RETURN
   2791         (_bcm_tr_cosq_gport_bandwidth_port_resolve(unit, gport, cosq,
   2792                                                    &local_port,
   2793                                                    &cosq_start, &cosq_end));
   2794 
   2795     BCM_IF_ERROR_RETURN
   2796         (bcm_tr_cosq_port_bandwidth_get(unit, local_port, cosq_start,
   2797                                         kbits_sec_min, kbits_sec_max,
   2798                                         &kbits_sec_burst, flags));
   2799     return BCM_E_NONE;
   2800 }
   2801 
   2802 /*  
   2803  * Function:
   2804  *      bcm_tr_cosq_gport_bandwidth_burst_set
   2805  * Purpose:
   2806  *       
   2807  * Parameters:
   2808  *      unit - (IN) Unit number.
   2809  *      gport - (IN) GPORT ID.
   2810  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   2811  *      kbits_burst - (IN) maximum burst, kbits.
   2812  * Returns:
   2813  *      BCM_E_XXX 
   2814  */ 
   2815 int
   2816 bcm_tr_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport,
   2817                                       bcm_cos_queue_t cosq,
   2818                                       uint32 kbits_burst_min,
   2819                                       uint32 kbits_burst_max)
   2820 {
   2821     bcm_port_t local_port, port;
   2822     int i;
   2823     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
   2824     uint32 kbits_sec_min, kbits_sec_max, flags;
   2825     uint32 kbits_sec_burst; /* Dummy variable */
   2826 
   2827     if (gport < 0) {
   2828         PBMP_ALL_ITER(unit, port) {
   2829             BCM_IF_ERROR_RETURN
   2830                 (_bcm_tr_cosq_gport_bandwidth_port_resolve(unit, port, cosq,
   2831                                                            &local_port,
   2832                                                            &cosq_start, &cosq_end));
   2833             for (i = cosq_start; i <= cosq_end; i++) {
   2834                 BCM_IF_ERROR_RETURN
   2835                     (_bcm_tr_cosq_bucket_get(unit, local_port, i,
   2836                                                     &kbits_sec_min, &kbits_sec_max,
   2837                                                     &kbits_sec_burst,&kbits_sec_burst,&flags));
   2838                 BCM_IF_ERROR_RETURN
   2839                     (_bcm_tr_cosq_bucket_set(unit, local_port, i,
   2840                                                     kbits_sec_min,
   2841                                                     kbits_sec_max,
   2842                                                     kbits_burst_min,
   2843                                                     kbits_burst_max,
   2844                                                     flags));
   2845             }
   2846         }
   2847         return BCM_E_NONE;
   2848     }
   2849 
   2850     BCM_IF_ERROR_RETURN
   2851         (_bcm_tr_cosq_gport_bandwidth_port_resolve(unit, gport, cosq,
   2852                                                    &local_port,
   2853                                                    &cosq_start, &cosq_end));
   2854 
   2855     for (i = cosq_start; i <= cosq_end; i++) {
   2856         BCM_IF_ERROR_RETURN
   2857             (_bcm_tr_cosq_bucket_get(unit, local_port, cosq_start,
   2858                                             &kbits_sec_min, &kbits_sec_max,
   2859                                             &kbits_sec_burst, &kbits_sec_burst,&flags));
   2860         BCM_IF_ERROR_RETURN
   2861             (_bcm_tr_cosq_bucket_set(unit, local_port, i,
   2862                                             kbits_sec_min,
   2863                                             kbits_sec_max,
   2864                                             kbits_burst_min,
   2865                                             kbits_burst_max,
   2866                                             flags));
   2867     }
   2868     return BCM_E_NONE;
   2869 }
   2870 
   2871 /*
   2872  * Function:
   2873  *      bcm_tr_cosq_gport_bandwidth_burst_get
   2874  * Purpose:
   2875  *
   2876  * Parameters:
   2877  *      unit - (IN) Unit number.
   2878  *      gport - (IN) GPORT ID.
   2879  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   2880  *      kbits_burst - (OUT) maximum burst, kbits.
   2881  * Returns:
   2882  *      BCM_E_XXX
   2883  */
   2884 int
   2885 bcm_tr_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport,
   2886                                       bcm_cos_queue_t cosq,
   2887                                       uint32 *kbits_burst_min,
   2888                                       uint32 *kbits_burst_max)
   2889 {
   2890     bcm_port_t local_port, port;
   2891     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
   2892     uint32 kbits_sec_min, kbits_sec_max, flags;    /* Dummy variables */
   2893 
   2894     if (gport < 0) {
   2895         port = SOC_PORT_MIN(unit,all);
   2896 
   2897         BCM_IF_ERROR_RETURN
   2898             (_bcm_tr_cosq_gport_bandwidth_port_resolve(unit, port, cosq,
   2899                                                        &local_port,
   2900                                                        &cosq_start, &cosq_end));
   2901     } else {
   2902         BCM_IF_ERROR_RETURN
   2903             (_bcm_tr_cosq_gport_bandwidth_port_resolve(unit, gport, cosq,
   2904                                                        &local_port,
   2905                                                        &cosq_start, &cosq_end));
   2906     }
   2907 
   2908     kbits_sec_min = kbits_sec_max = flags = 0;
   2909 
   2910     BCM_IF_ERROR_RETURN
   2911         (_bcm_tr_cosq_bucket_get(unit, local_port, cosq_start,
   2912                                         &kbits_sec_min, &kbits_sec_max,
   2913                                         kbits_burst_min,kbits_burst_max, &flags));
   2914     return BCM_E_NONE;
   2915 }
   2916 
   2917 /*
   2918  * Function:
   2919  *      bcm_cosq_gport_sched_set
   2920  * Purpose:
   2921  *
   2922  * Parameters:
   2923  *      unit - (IN) Unit number.
   2924  *      gport - (IN) GPORT ID.
   2925  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   2926  *      mode - (IN) Scheduling mode, one of BCM_COSQ_xxx
   2927  *      weight - (IN) Weight for the specified COS queue(s)
   2928  *               Unused if mode is BCM_COSQ_STRICT.
   2929  * Returns:
   2930  *      BCM_E_XXX
   2931  */
   2932 int
   2933 bcm_tr_cosq_gport_sched_set(int unit, bcm_gport_t gport,
   2934                             bcm_cos_queue_t cosq, int mode, int weight)
   2935 {
   2936     bcm_module_t modid;
   2937     bcm_port_t local_port;
   2938     bcm_trunk_t trunk_id;
   2939     int i;
   2940 	int numq;
   2941     bcm_cos_queue_t cosq_start = 0;
   2942     int num_weights = 1, weights[64];
   2943     soc_reg_t config_reg = ESCONFIGr;
   2944     soc_reg_t weight_reg = COSWEIGHTSr;
   2945     soc_reg_t minsp_reg = MINSPCONFIGr;
   2946 
   2947     BCM_IF_ERROR_RETURN
   2948         (_bcm_tr_cosq_resolve_mod_port(unit, gport, &modid,
   2949                                        &local_port, &trunk_id));
   2950 
   2951         if (!_tr_num_port_cosq[unit]) {
   2952             return BCM_E_INIT;
   2953         }
   2954         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   2955             if (_tr_num_port_cosq[unit][local_port] == 0) {
   2956                 return BCM_E_NOT_FOUND;
   2957             } else if (cosq >= _tr_num_port_cosq[unit][local_port]) {
   2958                 return BCM_E_PARAM;
   2959             } else if (cosq < 0) {
   2960                 cosq_start = 0;
   2961                 num_weights = 16;
   2962                 for (i = 0; i < num_weights; i++) {
   2963                     if (i < _tr_num_port_cosq[unit][local_port]) {
   2964                         weights[i] = weight;
   2965                     } else {
   2966                         weights[i] = 0;
   2967                     }
   2968                 }
   2969             } else {
   2970                 cosq_start = cosq;
   2971                 num_weights = 1;
   2972                 weights[0] = weight;
   2973             }
   2974             config_reg = S1V_CONFIGr;
   2975             weight_reg = S1V_COSWEIGHTSr;
   2976             minsp_reg = S1V_MINSPCONFIGr;
   2977         } else if (IS_CPU_PORT(unit, local_port)) {
   2978             numq = SOC_INFO(unit).num_cpu_cosq;
   2979             if (cosq >= numq) {
   2980                 return BCM_E_PARAM;
   2981             } else if (cosq < 0) {
   2982                 cosq_start = 0;
   2983                 num_weights = NUM_CPU_COSQ(unit);
   2984                 for (i = 0; i < num_weights; i++) {
   2985                     weights[i] = weight;
   2986                 } 
   2987             } else {	
   2988                 cosq_start = cosq;
   2989                 num_weights = 1;
   2990                 weights[0] = weight;
   2991             }
   2992 		} else if (cosq == TR_SCHEDULER_COSQ) {
   2993             if (!SOC_PBMP_MEMBER(_tr_cosq_24q_ports[unit], local_port)) {
   2994                 return BCM_E_PORT;
   2995             }
   2996             /* Weight for output of S1 scheduler is configured using offset 8 
   2997              * of COSWEIGHTS register.
   2998              */
   2999             cosq_start = 8;
   3000             num_weights = 1;
   3001             weights[0] = weight;
   3002         } else {
   3003             if (cosq >= _tr_num_cosq[unit]) {
   3004                 return BCM_E_PARAM;
   3005             } else if (cosq < 0) {
   3006                 cosq_start = 0;
   3007                 num_weights = 8;
   3008                 for (i = 0; i < num_weights; i++) {
   3009                     if (i < _tr_num_cosq[unit]) {
   3010                         weights[i] = weight;
   3011                     } else {
   3012                         weights[i] = 0;
   3013                     }
   3014                 }
   3015             } else {
   3016                 cosq_start = cosq;
   3017                 num_weights = 1;
   3018                 weights[0] = weight;
   3019             }
   3020         }
   3021 
   3022         /* coverity[uninit_use_in_call : FALSE] */
   3023         BCM_IF_ERROR_RETURN
   3024             (_bcm_tr_cosq_port_sched_set(unit, config_reg, weight_reg, minsp_reg,
   3025                                          local_port, cosq_start, num_weights,
   3026                                          weights, mode));
   3027     return BCM_E_NONE;
   3028 }
   3029 
   3030 /*
   3031  * Function:
   3032  *      bcm_cosq_gport_sched_get
   3033  * Purpose:
   3034  *
   3035  * Parameters:
   3036  *      unit - (IN) Unit number.
   3037  *      gport - (IN) GPORT ID.
   3038  *      cosq - (IN) COS queue
   3039  *      mode - (OUT) Scheduling mode, one of BCM_COSQ_xxx
   3040  *      weight - (OUT) Weight for the specified COS queue(s)
   3041  *               Unused if mode is BCM_COSQ_STRICT.
   3042  * Returns:
   3043  *      BCM_E_XXX
   3044  */
   3045 int
   3046 bcm_tr_cosq_gport_sched_get(int unit, bcm_gport_t gport, 
   3047                             bcm_cos_queue_t cosq, int *mode, int *weight)
   3048 {   
   3049     bcm_module_t modid;
   3050     bcm_port_t local_port;
   3051     bcm_trunk_t trunk_id;
   3052     soc_reg_t config_reg = ESCONFIGr;
   3053     soc_reg_t weight_reg = COSWEIGHTSr;
   3054 
   3055     *mode = *weight = 0;
   3056 
   3057     BCM_IF_ERROR_RETURN
   3058         (_bcm_tr_cosq_resolve_mod_port(unit, gport, &modid,
   3059                                        &local_port, &trunk_id));
   3060         if (!_tr_num_port_cosq[unit]) {
   3061             return BCM_E_INIT;
   3062         }
   3063         if (BCM_GPORT_IS_SCHEDULER(gport)) {
   3064             if (_tr_num_port_cosq[unit][local_port] == 0) {
   3065                 return BCM_E_NOT_FOUND;
   3066             } else if (cosq >= _tr_num_port_cosq[unit][local_port]) {
   3067                 return BCM_E_PARAM;
   3068             } else if (cosq < 0) {
   3069                 cosq = 0;
   3070             }
   3071             config_reg = S1V_CONFIGr;
   3072             weight_reg = S1V_COSWEIGHTSr;
   3073         } else if (cosq == TR_SCHEDULER_COSQ) {
   3074             if (!SOC_PBMP_MEMBER(_tr_cosq_24q_ports[unit], local_port)) {
   3075                 return BCM_E_PORT;
   3076             }
   3077             /* Weight for output of S1 scheduler is configured using offset 8 
   3078              * of COSWEIGHTS register.
   3079              */
   3080             cosq = 8;
   3081         } else {
   3082             if (cosq >= _tr_num_cosq[unit]) {
   3083                 return BCM_E_PARAM;
   3084             } else if (cosq < 0) {
   3085                 cosq = 0;
   3086             }
   3087         }
   3088         BCM_IF_ERROR_RETURN
   3089             (_bcm_tr_cosq_port_sched_get(unit, config_reg, weight_reg, 
   3090                                          local_port, cosq, 1,
   3091                                          weight, mode));
   3092     return BCM_E_NONE;
   3093 }
   3094 
   3095 /*
   3096  * Function:
   3097  *      bcm_cosq_gport_discard_set
   3098  * Purpose:
   3099  *
   3100  * Parameters:
   3101  *      unit    - (IN) Unit number.
   3102  *      port    - (IN) GPORT ID.
   3103  *      cosq    - (IN) COS queue to configure
   3104  *      discard - (IN) Discard settings
   3105  * Returns:
   3106  *      BCM_E_XXX
   3107  */
   3108 int
   3109 bcm_tr_cosq_gport_discard_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   3110                               bcm_cosq_gport_discard_t *discard)
   3111 {
   3112     bcm_module_t modid;
   3113     bcm_port_t local_port;
   3114     bcm_trunk_t trunk_id;
   3115     uint32 min_thresh, max_thresh;
   3116     int cell_size, cell_field_max;
   3117 
   3118     if ((discard == NULL) || 
   3119         (discard->gain < 0) || (discard->gain > 15) ||
   3120         (discard->drop_probability < 0) || (discard->drop_probability > 100)) {
   3121         return BCM_E_PARAM;
   3122     }
   3123 
   3124 #ifdef BCM_SCORPION_SUPPORT
   3125     if (SOC_IS_SC_CQ(unit)) {
   3126         if (!(discard->flags & BCM_COSQ_DISCARD_BYTES)) {
   3127             /* Scorpion only supports byte accounting for WRED */ 
   3128             return BCM_E_UNAVAIL;
   3129         }
   3130         cell_size      = _BCM_SC_COSQ_CELLSIZE;
   3131         cell_field_max = SC_CELL_FIELD_MAX;
   3132     } else
   3133 #endif /* BCM_SCORPION_SUPPORT */
   3134     {
   3135         cell_size      = _BCM_TR_COSQ_CELLSIZE;
   3136         cell_field_max = TR_CELL_FIELD_MAX(unit);
   3137     }
   3138 
   3139     min_thresh = discard->min_thresh;
   3140     max_thresh = discard->max_thresh;
   3141     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   3142         /* Convert bytes to cells */
   3143         min_thresh += (cell_size - 1);
   3144         min_thresh /= cell_size;
   3145 
   3146         max_thresh += (cell_size - 1);
   3147         max_thresh /= cell_size;
   3148 
   3149         if ((min_thresh > cell_field_max) || 
   3150             (max_thresh > cell_field_max)) {
   3151             return BCM_E_PARAM;
   3152         }
   3153     } else { /* BCM_COSQ_DISCARD_PACKETS */
   3154         if ((min_thresh > TR_PACKET_FIELD_MAX(unit)) || 
   3155             (max_thresh > TR_PACKET_FIELD_MAX(unit))) {
   3156             return BCM_E_PARAM;
   3157         }
   3158     }
   3159 
   3160     if (port != BCM_GPORT_INVALID) {
   3161         BCM_IF_ERROR_RETURN
   3162             (_bcm_tr_cosq_resolve_mod_port(unit, port, &modid,
   3163                                            &local_port, &trunk_id));
   3164         if (cosq < 0) {
   3165             /* per-port discard settings */
   3166             if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   3167                 BCM_IF_ERROR_RETURN
   3168                     (_bcm_tr_cosq_discard_set(unit, local_port,
   3169                                               discard->flags, 0,
   3170                                               PORT_WREDCONFIG_CELLr,
   3171                                               PORT_WREDPARAM_CELLr,
   3172                                               PORT_WREDPARAM_YELLOW_CELLr,
   3173                                               PORT_WREDPARAM_RED_CELLr,
   3174                                               PORT_WREDPARAM_NONTCP_CELLr,
   3175                                               min_thresh, max_thresh, 
   3176                                               discard->drop_probability,
   3177                                               discard->gain));
   3178                 BCM_IF_ERROR_RETURN
   3179                     (_bcm_tr_cosq_discard_cap_enable_set(unit, local_port, 0,
   3180                                                          PORT_WREDCONFIG_CELLr, 
   3181                                                          discard->flags));
   3182 
   3183             } else { /* BCM_COSQ_DISCARD_PACKETS */
   3184                 BCM_IF_ERROR_RETURN
   3185                     (_bcm_tr_cosq_discard_set(unit, local_port,
   3186                                               discard->flags, 0,
   3187                                               PORT_WREDCONFIG_PACKETr,
   3188                                               PORT_WREDPARAM_PACKETr,
   3189                                               PORT_WREDPARAM_YELLOW_PACKETr,
   3190                                               PORT_WREDPARAM_RED_PACKETr,
   3191                                               PORT_WREDPARAM_NONTCP_PACKETr,
   3192                                               min_thresh, max_thresh, 
   3193                                               discard->drop_probability,
   3194                                               discard->gain));
   3195                 BCM_IF_ERROR_RETURN
   3196                     (_bcm_tr_cosq_discard_cap_enable_set(unit, local_port, 0,
   3197                                                          PORT_WREDCONFIG_PACKETr, 
   3198                                                          discard->flags));
   3199             }
   3200         } else {
   3201             /* per-port/per-cos discard settings */
   3202             if (BCM_GPORT_IS_SCHEDULER(port)) {
   3203                 if (_tr_num_port_cosq[unit][local_port] == 0) {
   3204                     return BCM_E_NOT_FOUND;
   3205                 } else if (cosq >= _tr_num_port_cosq[unit][local_port]) {
   3206                     return BCM_E_PARAM;
   3207                 } else {
   3208                     cosq = cosq + 8;
   3209                 }
   3210             } else if (cosq >= _tr_num_cosq[unit]) {
   3211                 return BCM_E_PARAM;
   3212             }
   3213 
   3214             if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   3215                 BCM_IF_ERROR_RETURN
   3216                     (_bcm_tr_cosq_discard_set(unit, local_port,
   3217                                               discard->flags, cosq,
   3218                                               WREDCONFIG_CELLr,
   3219                                               WREDPARAM_CELLr,
   3220                                               WREDPARAM_YELLOW_CELLr,
   3221                                               WREDPARAM_RED_CELLr,
   3222                                               WREDPARAM_NONTCP_CELLr,
   3223                                               min_thresh, max_thresh, 
   3224                                               discard->drop_probability,
   3225                                               discard->gain));
   3226                 BCM_IF_ERROR_RETURN
   3227                     (_bcm_tr_cosq_discard_cap_enable_set(unit, local_port, cosq,
   3228                                                          WREDCONFIG_CELLr, 
   3229                                                          discard->flags));
   3230             } else { /* BCM_COSQ_DISCARD_PACKETS */
   3231                 BCM_IF_ERROR_RETURN
   3232                     (_bcm_tr_cosq_discard_set(unit, local_port,
   3233                                               discard->flags, cosq,
   3234                                               WREDCONFIG_PACKETr,
   3235                                               WREDPARAM_PACKETr,
   3236                                               WREDPARAM_YELLOW_PACKETr,
   3237                                               WREDPARAM_RED_PACKETr,
   3238                                               WREDPARAM_NONTCP_PACKETr,
   3239                                               min_thresh, max_thresh, 
   3240                                               discard->drop_probability,
   3241                                               discard->gain));
   3242                 BCM_IF_ERROR_RETURN
   3243                     (_bcm_tr_cosq_discard_cap_enable_set(unit, local_port, cosq,
   3244                                                          WREDCONFIG_PACKETr, 
   3245                                                          discard->flags));
   3246             }
   3247         }
   3248     } else {
   3249         /* chip-wide discard settings */
   3250         if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   3251             BCM_IF_ERROR_RETURN
   3252                 (_bcm_tr_cosq_discard_set(unit, REG_PORT_ANY, discard->flags,
   3253                                           0, GLOBAL_WREDCONFIG_CELLr,
   3254                                           GLOBAL_WREDPARAM_CELLr,
   3255                                           GLOBAL_WREDPARAM_YELLOW_CELLr,
   3256                                           GLOBAL_WREDPARAM_RED_CELLr,
   3257                                           GLOBAL_WREDPARAM_NONTCP_CELLr,
   3258                                           min_thresh, max_thresh, 
   3259                                           discard->drop_probability,
   3260                                           discard->gain));
   3261             BCM_IF_ERROR_RETURN
   3262                 (_bcm_tr_cosq_discard_cap_enable_set(unit, REG_PORT_ANY, 0,
   3263                                                      GLOBAL_WREDCONFIG_CELLr, 
   3264                                                      discard->flags));
   3265         } else { /* BCM_COSQ_DISCARD_PACKETS */
   3266             BCM_IF_ERROR_RETURN
   3267                 (_bcm_tr_cosq_discard_set(unit, REG_PORT_ANY, discard->flags,
   3268                                           0, GLOBAL_WREDCONFIG_PACKETr,
   3269                                           GLOBAL_WREDPARAM_PACKETr,
   3270                                           GLOBAL_WREDPARAM_YELLOW_PACKETr,
   3271                                           GLOBAL_WREDPARAM_RED_PACKETr,
   3272                                           GLOBAL_WREDPARAM_NONTCP_PACKETr,
   3273                                           min_thresh, max_thresh, 
   3274                                           discard->drop_probability,
   3275                                           discard->gain));
   3276             BCM_IF_ERROR_RETURN
   3277                 (_bcm_tr_cosq_discard_cap_enable_set(unit, REG_PORT_ANY, 0,
   3278                                                      GLOBAL_WREDCONFIG_PACKETr, 
   3279                                                      discard->flags));
   3280         }
   3281     }
   3282     return BCM_E_NONE;
   3283 }
   3284 
   3285 /*
   3286  * Function:
   3287  *      bcm_cosq_gport_discard_get
   3288  * Purpose:
   3289  *
   3290  * Parameters:
   3291  *      unit    - (IN) Unit number.
   3292  *      port    - (IN) GPORT ID.
   3293  *      cosq    - (IN) COS queue to get
   3294  *      discard - (IN/OUT) Discard settings
   3295  * Returns:
   3296  *      BCM_E_XXX
   3297  */
   3298 int
   3299 bcm_tr_cosq_gport_discard_get(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   3300                               bcm_cosq_gport_discard_t *discard)
   3301 {
   3302     bcm_module_t modid;
   3303     bcm_port_t local_port;
   3304     bcm_trunk_t trunk_id;
   3305     uint32 min_thresh, max_thresh;
   3306 
   3307     if (discard == NULL) {
   3308         return BCM_E_PARAM;
   3309     }
   3310 #ifdef BCM_SCORPION_SUPPORT
   3311     if (SOC_IS_SC_CQ(unit)) {
   3312         if (!(discard->flags & BCM_COSQ_DISCARD_BYTES)) {
   3313             return BCM_E_UNAVAIL;
   3314         }
   3315     }
   3316 #endif
   3317 
   3318     if (port != BCM_GPORT_INVALID) {
   3319         BCM_IF_ERROR_RETURN
   3320             (_bcm_tr_cosq_resolve_mod_port(unit, port, &modid,
   3321                                            &local_port, &trunk_id));
   3322         if (cosq < 0) {
   3323             /* per-port discard settings */
   3324             if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   3325                 BCM_IF_ERROR_RETURN
   3326                     (_bcm_tr_cosq_discard_get(unit, local_port,
   3327                                               discard->flags, 0,
   3328                                               PORT_WREDCONFIG_CELLr,
   3329                                               PORT_WREDPARAM_CELLr,
   3330                                               PORT_WREDPARAM_YELLOW_CELLr,
   3331                                               PORT_WREDPARAM_RED_CELLr,
   3332                                               PORT_WREDPARAM_NONTCP_CELLr,
   3333                                               &min_thresh, &max_thresh, 
   3334                                               &discard->drop_probability,
   3335                                               &discard->gain));
   3336                 BCM_IF_ERROR_RETURN
   3337                     (_bcm_tr_cosq_discard_cap_enable_get(unit, local_port, 0,
   3338                                                          PORT_WREDCONFIG_CELLr, 
   3339                                                          &discard->flags));
   3340             } else { /* BCM_COSQ_DISCARD_PACKETS */
   3341                 BCM_IF_ERROR_RETURN
   3342                     (_bcm_tr_cosq_discard_get(unit, local_port,
   3343                                               discard->flags, 0,
   3344                                               PORT_WREDCONFIG_PACKETr,
   3345                                               PORT_WREDPARAM_PACKETr,
   3346                                               PORT_WREDPARAM_YELLOW_PACKETr,
   3347                                               PORT_WREDPARAM_RED_PACKETr,
   3348                                               PORT_WREDPARAM_NONTCP_PACKETr,
   3349                                               &min_thresh, &max_thresh, 
   3350                                               &discard->drop_probability,
   3351                                               &discard->gain));
   3352                 BCM_IF_ERROR_RETURN
   3353                     (_bcm_tr_cosq_discard_cap_enable_get(unit, local_port, 0,
   3354                                                          PORT_WREDCONFIG_PACKETr, 
   3355                                                          &discard->flags));
   3356             }
   3357         } else {
   3358             /* per-port/per-cos discard settings */
   3359             if (SOC_IS_TR_VL(unit)) {
   3360                 if (BCM_GPORT_IS_SCHEDULER(port)) {
   3361                     if (_tr_num_port_cosq[unit][local_port] == 0) {
   3362                         return BCM_E_NOT_FOUND;
   3363                     } else if (cosq >= _tr_num_port_cosq[unit][local_port]) {
   3364                         return BCM_E_PARAM;
   3365                     } else {
   3366                         cosq = cosq + 8;
   3367                     }
   3368                 } else if (cosq >= _tr_num_cosq[unit]) {
   3369                     return BCM_E_PARAM;
   3370                 }
   3371             } else {
   3372                 if (cosq < BCM_COS_MIN || cosq > BCM_COS_MAX) {
   3373                     return BCM_E_PARAM;
   3374                 }
   3375             }
   3376 
   3377             if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   3378                 BCM_IF_ERROR_RETURN
   3379                     (_bcm_tr_cosq_discard_get(unit, local_port,
   3380                                               discard->flags, cosq,
   3381                                               WREDCONFIG_CELLr,
   3382                                               WREDPARAM_CELLr,
   3383                                               WREDPARAM_YELLOW_CELLr,
   3384                                               WREDPARAM_RED_CELLr,
   3385                                               WREDPARAM_NONTCP_CELLr,
   3386                                               &min_thresh, &max_thresh, 
   3387                                               &discard->drop_probability,
   3388                                               &discard->gain));
   3389                 BCM_IF_ERROR_RETURN
   3390                     (_bcm_tr_cosq_discard_cap_enable_get(unit, local_port, cosq,
   3391                                                          WREDCONFIG_CELLr, 
   3392                                                          &discard->flags));
   3393             } else { /* BCM_COSQ_DISCARD_PACKETS */
   3394                 BCM_IF_ERROR_RETURN
   3395                     (_bcm_tr_cosq_discard_get(unit, local_port,
   3396                                               discard->flags, cosq,
   3397                                               WREDCONFIG_PACKETr,
   3398                                               WREDPARAM_PACKETr,
   3399                                               WREDPARAM_YELLOW_PACKETr,
   3400                                               WREDPARAM_RED_PACKETr,
   3401                                               WREDPARAM_NONTCP_PACKETr,
   3402                                               &min_thresh, &max_thresh, 
   3403                                               &discard->drop_probability,
   3404                                               &discard->gain));
   3405                 BCM_IF_ERROR_RETURN
   3406                     (_bcm_tr_cosq_discard_cap_enable_get(unit, local_port, cosq,
   3407                                                          WREDCONFIG_PACKETr, 
   3408                                                          &discard->flags));
   3409             }
   3410         }
   3411     } else {
   3412         /* chip-wide discard settings */
   3413         if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   3414             BCM_IF_ERROR_RETURN
   3415                 (_bcm_tr_cosq_discard_get(unit, REG_PORT_ANY, discard->flags,
   3416                                           0, GLOBAL_WREDCONFIG_CELLr,
   3417                                           GLOBAL_WREDPARAM_CELLr,
   3418                                           GLOBAL_WREDPARAM_YELLOW_CELLr,
   3419                                           GLOBAL_WREDPARAM_RED_CELLr,
   3420                                           GLOBAL_WREDPARAM_NONTCP_CELLr,
   3421                                           &min_thresh, &max_thresh, 
   3422                                           &discard->drop_probability,
   3423                                           &discard->gain));
   3424             BCM_IF_ERROR_RETURN
   3425                 (_bcm_tr_cosq_discard_cap_enable_get(unit, REG_PORT_ANY, 0,
   3426                                                      GLOBAL_WREDCONFIG_CELLr, 
   3427                                                      &discard->flags));
   3428         } else { /* BCM_COSQ_DISCARD_PACKETS */
   3429             BCM_IF_ERROR_RETURN
   3430                 (_bcm_tr_cosq_discard_get(unit, REG_PORT_ANY, discard->flags,
   3431                                           0, GLOBAL_WREDCONFIG_PACKETr,
   3432                                           GLOBAL_WREDPARAM_PACKETr,
   3433                                           GLOBAL_WREDPARAM_YELLOW_PACKETr,
   3434                                           GLOBAL_WREDPARAM_RED_PACKETr,
   3435                                           GLOBAL_WREDPARAM_NONTCP_PACKETr,
   3436                                           &min_thresh, &max_thresh, 
   3437                                           &discard->drop_probability,
   3438                                           &discard->gain));
   3439             BCM_IF_ERROR_RETURN
   3440                 (_bcm_tr_cosq_discard_cap_enable_get(unit, REG_PORT_ANY, 0,
   3441                                                      GLOBAL_WREDCONFIG_PACKETr, 
   3442                                                      &discard->flags));
   3443         }
   3444     }
   3445 
   3446     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   3447         /* Convert cells to bytes */
   3448         min_thresh *= _BCM_TR_COSQ_CELLSIZE;
   3449         max_thresh *= _BCM_TR_COSQ_CELLSIZE;
   3450     }
   3451     discard->min_thresh = min_thresh;
   3452     discard->max_thresh = max_thresh;
   3453 
   3454     return BCM_E_NONE;
   3455 }
   3456 
   3457 /* 
   3458  * Function:
   3459  *      bcm_cosq_gport_attach
   3460  * Purpose:
   3461  *      
   3462  * Parameters: 
   3463  *      unit       - (IN) Unit number.
   3464  *      sched_port - (IN) Scheduler GPORT ID.
   3465  *      input_port - (IN) GPORT to attach to.
   3466  *      cosq       - (IN) COS queue to attach to.
   3467  * Returns:
   3468  *      BCM_E_XXX
   3469  */
   3470 int
   3471 bcm_tr_cosq_gport_attach(int unit, bcm_gport_t sched_gport, 
   3472                          bcm_gport_t input_gport, bcm_cos_queue_t cosq)
   3473 {
   3474     bcm_module_t sched_modid, input_modid;
   3475     bcm_port_t sched_port, input_port;
   3476     bcm_trunk_t trunk_id;
   3477 
   3478     if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) {
   3479         return BCM_E_PARAM;
   3480     } else if (!_tr_num_port_cosq[unit]) {
   3481         return BCM_E_INIT;
   3482     } else if (cosq < 0) {
   3483         cosq = TR_SCHEDULER_COSQ;
   3484     } else if (cosq != TR_SCHEDULER_COSQ) {
   3485         return BCM_E_PARAM;
   3486     }
   3487 
   3488     BCM_IF_ERROR_RETURN
   3489         (_bcm_tr_cosq_resolve_mod_port(unit, sched_gport, &sched_modid,
   3490                                        &sched_port, &trunk_id));
   3491 
   3492         BCM_IF_ERROR_RETURN
   3493             (_bcm_tr_cosq_resolve_mod_port(unit, input_gport, &input_modid,
   3494                                            &input_port, &trunk_id));
   3495 
   3496         if (_tr_num_port_cosq[unit][sched_port] == 0) {
   3497             /* GPORT has not been added. */
   3498             return BCM_E_NOT_FOUND;
   3499         } else if ((sched_modid != input_modid) || (sched_port != input_port)) {
   3500             /* Be sure the GPORT matches to the physical port */
   3501             return BCM_E_PARAM;
   3502         }
   3503 
   3504         BCM_IF_ERROR_RETURN
   3505             (soc_reg_field32_modify(unit, ING_COS_MODEr, input_port, 
   3506                                     SELECTf, 0x3)); /* VLAN_COS */
   3507         BCM_IF_ERROR_RETURN
   3508             (soc_reg_field32_modify(unit, COS_MODEr, input_port, 
   3509                                     SELECTf, 0x3)); /* VLAN_COS */
   3510     return BCM_E_NONE;
   3511 }   
   3512 
   3513 /*
   3514  * Function:
   3515  *      bcm_cosq_gport_detach
   3516  * Purpose:
   3517  * 
   3518  * Parameters:
   3519  *      unit       - (IN) Unit number.
   3520  *      sched_port - (IN) Scheduler GPORT ID.
   3521  *      input_port - (IN) GPORT to detach from.
   3522  *      cosq       - (IN) COS queue to detach from.
   3523  * Returns:
   3524  *      BCM_E_XXX
   3525  * Notes:
   3526  */
   3527 int     
   3528 bcm_tr_cosq_gport_detach(int unit, bcm_gport_t sched_gport,
   3529                          bcm_gport_t input_gport, bcm_cos_queue_t cosq)
   3530 {
   3531     bcm_module_t sched_modid, input_modid;
   3532     bcm_port_t sched_port, input_port;
   3533     bcm_trunk_t trunk_id;
   3534 
   3535     if (!BCM_GPORT_IS_SCHEDULER(sched_gport)) {
   3536         return BCM_E_PORT;
   3537     } else if (!_tr_num_port_cosq[unit]) {
   3538         return BCM_E_INIT;
   3539     } else if ((cosq > 0) && (cosq != TR_SCHEDULER_COSQ)) {
   3540         return BCM_E_NOT_FOUND;
   3541     }
   3542 
   3543     BCM_IF_ERROR_RETURN
   3544         (_bcm_tr_cosq_resolve_mod_port(unit, sched_gport, &sched_modid,
   3545                                        &sched_port, &trunk_id));
   3546        BCM_IF_ERROR_RETURN
   3547            (_bcm_tr_cosq_resolve_mod_port(unit, input_gport, &input_modid,
   3548                                           &input_port, &trunk_id));
   3549         if (_tr_num_port_cosq[unit][sched_port] == 0) {
   3550             /* GPORT has not been added. */
   3551             return BCM_E_NOT_FOUND;
   3552         } else if ((sched_modid != input_modid) || (sched_port != input_port)) {
   3553             /* Be sure the GPORT matches to the physical port */
   3554             return BCM_E_PORT;
   3555         }
   3556     
   3557         BCM_IF_ERROR_RETURN
   3558             (soc_reg_field32_modify(unit, COS_MODEr, input_port, SELECTf, 0x0));
   3559         BCM_IF_ERROR_RETURN
   3560             (soc_reg_field32_modify(unit, ING_COS_MODEr, input_port, SELECTf, 0x0));
   3561     return BCM_E_NONE;
   3562 }
   3563 
   3564 /*
   3565  * Function:
   3566  *      bcm_cosq_gport_attach_get
   3567  * Purpose:
   3568  *
   3569  * Parameters:
   3570  *      unit       - (IN) Unit number.
   3571  *      sched_port - (IN) Scheduler GPORT ID.
   3572  *      input_port - (OUT) GPORT attached to.
   3573  *      cosq       - (OUT) COS queue attached to.
   3574  * Returns:
   3575  *      BCM_E_XXX
   3576  * Notes:
   3577  */
   3578 int
   3579 bcm_tr_cosq_gport_attach_get(int unit, bcm_gport_t sched_gport,
   3580                              bcm_gport_t *input_gport, bcm_cos_queue_t *cosq)
   3581 {
   3582     bcm_module_t sched_modid, input_modid;
   3583     bcm_port_t sched_port, input_port;
   3584     bcm_trunk_t trunk_id;
   3585     uint32 val;
   3586 
   3587     if (!BCM_GPORT_IS_SCHEDULER(sched_gport) ||
   3588         !cosq || !input_gport) {
   3589         return BCM_E_PARAM;
   3590     } else if (!_tr_num_port_cosq[unit]) {
   3591         return BCM_E_INIT;
   3592     }
   3593 
   3594     BCM_IF_ERROR_RETURN
   3595         (_bcm_tr_cosq_resolve_mod_port(unit, sched_gport, &sched_modid,
   3596                                        &sched_port, &trunk_id));
   3597         if (_tr_num_port_cosq[unit][sched_port] == 0) {
   3598             /* GPORT has not been added. */
   3599             return BCM_E_NOT_FOUND;
   3600         }
   3601 
   3602         BCM_IF_ERROR_RETURN(READ_COS_MODEr(unit, sched_port, &val));
   3603         if (soc_reg_field_get(unit, COS_MODEr, val, SELECTf) == 3) {
   3604             /* GPORT has been attached */
   3605             *cosq = TR_SCHEDULER_COSQ;
   3606 
   3607             BCM_IF_ERROR_RETURN
   3608                 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   3609                                         sched_modid, sched_port,
   3610                                         &input_modid, &input_port));
   3611             BCM_GPORT_MODPORT_SET(*input_gport, input_modid, input_port);
   3612         } else {
   3613             /* GPORT has not been attached */
   3614             return BCM_E_NOT_FOUND;
   3615         }
   3616     return BCM_E_NONE;
   3617 }
   3618 
   3619 #ifdef BCM_SCORPION_SUPPORT
   3620 STATIC int 
   3621 _bcm_sc_cosq_discard_all_disable (int unit)
   3622 {
   3623     bcm_port_t port;
   3624     bcm_cos_queue_t cosq;
   3625     soc_reg_t config_reg;
   3626     uint32 val, addr;
   3627 
   3628     PBMP_ALL_ITER(unit, port) {
   3629         if (IS_CPU_PORT(unit, port)) {
   3630             continue;
   3631         }
   3632         /* Cosq level disabling */
   3633         config_reg = WREDCONFIG_CELLr;
   3634         for (cosq = 0; cosq < 8; cosq++) {
   3635              addr = soc_reg_addr(unit, config_reg, port, cosq);
   3636              SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   3637              soc_reg_field_set(unit, config_reg, &val, CAP_AVERAGEf, 0);
   3638              soc_reg_field_set(unit, config_reg, &val, ENABLEf, 0);
   3639              SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   3640         }
   3641 
   3642         /* Port level disabling */
   3643         config_reg = PORT_WREDCONFIG_CELLr;
   3644         addr = soc_reg_addr(unit, config_reg, port, 0);
   3645         SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   3646         soc_reg_field_set(unit, config_reg, &val, CAP_AVERAGEf, 0);
   3647         soc_reg_field_set(unit, config_reg, &val, ENABLEf, 0);
   3648         SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   3649     }
   3650 
   3651     /* Chip level disabling */
   3652     config_reg = GLOBAL_WREDCONFIG_CELLr;
   3653     addr = soc_reg_addr(unit, config_reg, REG_PORT_ANY, 0);
   3654     SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &val));
   3655     soc_reg_field_set(unit, config_reg, &val, CAP_AVERAGEf, 0);
   3656     soc_reg_field_set(unit, config_reg, &val, ENABLEf, 0);
   3657     SOC_IF_ERROR_RETURN(soc_reg32_write(unit, addr, val));
   3658    
   3659     return BCM_E_NONE;
   3660 }
   3661 
   3662 int
   3663 bcm_sc_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   3664                                bcm_cos_queue_t cosq,
   3665                                uint32 kbits_sec_min,
   3666                                uint32 kbits_sec_max,
   3667                                uint32 kbits_sec_burst,
   3668                                uint32 flags)
   3669 {
   3670     uint32 regval;
   3671     uint32 bucket_val = 0;
   3672     uint32 refresh_rate, bucketsize, granularity = 3, meter_flags = 0;
   3673     int    refresh_bitsize, bucket_bitsize;
   3674 
   3675 
   3676     /*
   3677      * To set the new Bandwidth settings, the procedure adopted is
   3678      * a. reset MAXBUCKETCONFIG, MINBUCKETCONFIG, MAXBUCKET,MINBUCKET
   3679      * b. update MAXBUCKETCONFIG and MINBUCKETCONFIG with new values passed
   3680      * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it.
   3681      */
   3682 
   3683     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
   3684     if (soc_reg_field_get(unit, MISCCONFIGr, regval, ITU_MODE_SELf)) {
   3685         meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   3686     }
   3687     meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   3688 
   3689     if (!IS_CPU_PORT(unit,port)) {
   3690         /* Disable egress metering for this port */
   3691         BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIG1r(unit, port, cosq, &regval));
   3692         soc_reg_field_set(unit, MAXBUCKETCONFIG1r, &regval, REFRESHf, 0);
   3693         BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIG1r(unit, port, cosq, regval));
   3694 
   3695         BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIGr(unit, port, cosq, &regval));
   3696         soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval, THRESHOLDf, 0);
   3697         BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIGr(unit, port, cosq, regval));
   3698     } else {
   3699         BCM_IF_ERROR_RETURN(READ_CPUPKTMAXBUCKETCONFIGr(unit, cosq, &regval));
   3700         soc_reg_field_set(unit, CPUPKTMAXBUCKETCONFIGr,&regval, PKT_MAX_THD_SELf,0);
   3701         soc_reg_field_set(unit, CPUPKTMAXBUCKETCONFIGr,&regval, PKT_MAX_REFRESHf,0);
   3702         BCM_IF_ERROR_RETURN(WRITE_CPUPKTMAXBUCKETCONFIGr(unit, cosq, regval));
   3703     }
   3704     if (!IS_CPU_PORT(unit,port)) {
   3705         BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIG1r(unit, port, cosq, &regval));
   3706         soc_reg_field_set(unit, MINBUCKETCONFIG1r, &regval, REFRESHf, 0);
   3707         BCM_IF_ERROR_RETURN(WRITE_MINBUCKETCONFIG1r(unit, port, cosq, regval));
   3708 
   3709         BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIGr(unit, port, cosq, &regval));
   3710         soc_reg_field_set(unit, MINBUCKETCONFIGr, &regval, THRESHOLDf, 0);
   3711         BCM_IF_ERROR_RETURN(WRITE_MINBUCKETCONFIGr(unit, port, cosq, regval));
   3712         /* Reset the MAXBUCKET register */
   3713         soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, MAX_BUCKETf, 0);
   3714         soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, OUT_PROFILE_FLAGf, 0);
   3715         BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETr(unit, port, cosq, bucket_val));
   3716 
   3717         /*reset the MINBUCKET register value*/
   3718         soc_reg_field_set(unit, MINBUCKETr, &bucket_val, MIN_BUCKETf, 0);
   3719         soc_reg_field_set(unit, MINBUCKETr, &bucket_val, OUT_PROFILE_FLAGf, 0);
   3720         BCM_IF_ERROR_RETURN(WRITE_MINBUCKETr(unit, port, cosq, bucket_val));
   3721 
   3722         refresh_bitsize =
   3723             soc_reg_field_length(unit, MINBUCKETCONFIG1r, REFRESHf);
   3724         bucket_bitsize =
   3725             soc_reg_field_length(unit, MINBUCKETCONFIGr, THRESHOLDf);
   3726         BCM_IF_ERROR_RETURN
   3727             (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_min, kbits_sec_min,
   3728                               meter_flags, refresh_bitsize, bucket_bitsize,
   3729                               &refresh_rate, &bucketsize, &granularity));
   3730 
   3731         regval = 0;
   3732         soc_reg_field_set(unit, MINBUCKETCONFIGr, &regval,
   3733                           METER_GRANf, granularity);
   3734         soc_reg_field_set(unit, MINBUCKETCONFIGr,
   3735                               &regval, THRESHOLDf, bucketsize);
   3736         BCM_IF_ERROR_RETURN
   3737             (WRITE_MINBUCKETCONFIGr(unit, port, cosq, regval));
   3738 
   3739         regval = 0;
   3740         soc_reg_field_set(unit, MINBUCKETCONFIG1r, &regval,
   3741                               REFRESHf, refresh_rate);
   3742         BCM_IF_ERROR_RETURN
   3743             (WRITE_MINBUCKETCONFIG1r(unit, port, cosq, regval));
   3744     }
   3745 
   3746 
   3747     if (!IS_CPU_PORT(unit,port)) {
   3748         refresh_bitsize =
   3749             soc_reg_field_length(unit, MAXBUCKETCONFIG1r, REFRESHf);
   3750         bucket_bitsize =
   3751             soc_reg_field_length(unit, MAXBUCKETCONFIGr, THRESHOLDf);
   3752     } else {
   3753         bucket_bitsize = soc_reg_field_length(unit, CPUPKTMAXBUCKETCONFIGr,
   3754                                               PKT_MAX_THD_SELf);
   3755         refresh_bitsize = soc_reg_field_length(unit, CPUPKTMAXBUCKETCONFIGr,
   3756                                               PKT_MAX_REFRESHf);
   3757     }
   3758     BCM_IF_ERROR_RETURN
   3759         (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_max, kbits_sec_burst,
   3760                           meter_flags, refresh_bitsize, bucket_bitsize,
   3761                           &refresh_rate, &bucketsize, &granularity));
   3762 
   3763 
   3764     if (!IS_CPU_PORT(unit,port)) {
   3765         regval = 0;
   3766         soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval,
   3767                           METER_GRANf, granularity);
   3768         soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval, THRESHOLDf,
   3769                           bucketsize);
   3770         BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIGr(unit, port, cosq, regval));
   3771 
   3772         regval = 0;                                                         
   3773         soc_reg_field_set(unit, MAXBUCKETCONFIG1r, &regval,
   3774                               REFRESHf, refresh_rate);
   3775         BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIG1r(unit, port, cosq, regval));
   3776     } else {
   3777         regval = 0;
   3778         soc_reg_field_set(unit, CPUPKTMAXBUCKETCONFIGr, &regval, PKT_MAX_THD_SELf, 
   3779                                 bucketsize);
   3780         soc_reg_field_set(unit, CPUPKTMAXBUCKETCONFIGr, &regval, PKT_MAX_REFRESHf, 
   3781                                 refresh_rate);
   3782         BCM_IF_ERROR_RETURN(WRITE_CPUPKTMAXBUCKETCONFIGr(unit, cosq, regval));
   3783     }
   3784 
   3785     /* 10MISCCONFIG.METERING_CLK_EN is set by chip init */
   3786     return BCM_E_NONE;
   3787 }
   3788 
   3789 int
   3790 bcm_sc_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   3791                                bcm_cos_queue_t cosq,
   3792                                uint32 *kbits_sec_min,
   3793                                uint32 *kbits_sec_max,
   3794                                uint32 *kbits_sec_burst,
   3795                                uint32 *flags)
   3796 {
   3797     uint32 regval;
   3798     uint32 refresh_rate = 0, bucketsize = 0,
   3799         granularity = 3, meter_flags = 0;
   3800     uint32 kbits_min_burst; /* Placeholder, since burst is unused for min */
   3801 
   3802     if (!kbits_sec_min || !kbits_sec_max || !kbits_sec_burst || !flags) {
   3803         return (BCM_E_PARAM);
   3804     }
   3805 
   3806     BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
   3807     if (soc_reg_field_get(unit, MISCCONFIGr, regval, ITU_MODE_SELf)) {
   3808         meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   3809     }
   3810 
   3811     if (!IS_CPU_PORT(unit,port)) {
   3812         meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   3813         BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIGr(unit, port, cosq, &regval));
   3814         granularity = soc_reg_field_get(unit, MAXBUCKETCONFIGr,
   3815                                         regval, METER_GRANf);
   3816         bucketsize = soc_reg_field_get(unit, MAXBUCKETCONFIGr,
   3817                                        regval, THRESHOLDf);
   3818         BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIG1r(unit, port, cosq, &regval));
   3819         refresh_rate = soc_reg_field_get(unit, MAXBUCKETCONFIG1r,
   3820                                          regval, REFRESHf);
   3821     } else {
   3822         BCM_IF_ERROR_RETURN(READ_CPUPKTMAXBUCKETCONFIGr(unit, cosq, &regval));
   3823         bucketsize = soc_reg_field_get(unit, CPUPKTMAXBUCKETCONFIGr,
   3824                                        regval, PKT_MAX_THD_SELf);
   3825         refresh_rate = soc_reg_field_get(unit, CPUPKTMAXBUCKETCONFIGr,
   3826                                          regval, PKT_MAX_REFRESHf);
   3827     }
   3828 
   3829     BCM_IF_ERROR_RETURN
   3830         (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   3831                                            granularity, meter_flags,
   3832                                            kbits_sec_max, kbits_sec_burst));
   3833 
   3834     if (!IS_CPU_PORT(unit,port)) {
   3835         BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIGr(unit, port, cosq, &regval));
   3836         granularity = soc_reg_field_get(unit, MINBUCKETCONFIGr,
   3837                                         regval, METER_GRANf);
   3838         BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIG1r(unit, port, cosq, &regval));
   3839         refresh_rate = soc_reg_field_get(unit, MINBUCKETCONFIG1r,
   3840                                          regval, REFRESHf);
   3841     } 
   3842 
   3843     BCM_IF_ERROR_RETURN
   3844         (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, 0,
   3845                                            granularity, meter_flags,
   3846                                            kbits_sec_min, &kbits_min_burst));
   3847 
   3848     *flags = 0;
   3849 
   3850     return BCM_E_NONE;
   3851 }
   3852 
   3853 int
   3854 bcm_sc_cosq_discard_set(int unit, uint32 flags)
   3855 {
   3856     bcm_port_t port;
   3857     bcm_cos_queue_t cosq;
   3858     soc_reg_t config_reg = WREDCONFIG_CELLr;
   3859 
   3860     PBMP_ALL_ITER(unit, port) {
   3861         if (IS_CPU_PORT(unit, port)) {
   3862             continue;
   3863         }
   3864         for (cosq = 0; cosq < 8; cosq++) {
   3865             BCM_IF_ERROR_RETURN
   3866                 (_bcm_tr_cosq_discard_cap_enable_set(unit, port, cosq,
   3867                                                      config_reg, flags));
   3868         }
   3869     }
   3870     return BCM_E_NONE;
   3871 }
   3872 
   3873 int
   3874 bcm_sc_cosq_discard_get(int unit, uint32 *flags)
   3875 {
   3876     int rv = BCM_E_NONE;
   3877     bcm_port_t port;
   3878     soc_reg_t config_reg = WREDCONFIG_CELLr;
   3879 
   3880     PBMP_ALL_ITER(unit, port) {
   3881         if (IS_CPU_PORT(unit, port)) {
   3882             continue;
   3883         }
   3884         *flags = 0;
   3885         rv = _bcm_tr_cosq_discard_cap_enable_get(unit, port, 0,
   3886                                                  config_reg, flags);
   3887         break;
   3888     }
   3889     return rv;
   3890 }
   3891 
   3892 int
   3893 bcm_sc_cosq_discard_port_set(int unit, bcm_port_t port,
   3894                              bcm_cos_queue_t cosq,
   3895                              uint32 color,
   3896                              int drop_start,
   3897                              int drop_slope,
   3898                              int average_time)
   3899 {
   3900     bcm_module_t modid;
   3901     bcm_port_t local_port;
   3902     bcm_trunk_t trunk_id;
   3903     bcm_pbmp_t pbmp;
   3904     _bcm_gport_dest_t dest;
   3905     bcm_gport_t gport;
   3906     int i, cosq_start, num_cosq;
   3907     uint32 shared_limit;
   3908     uint32 rval, bits;
   3909     bcm_cosq_gport_discard_t discard;
   3910 
   3911     if (!_tr_num_cosq[unit]) {
   3912         return BCM_E_INIT;
   3913     }
   3914 
   3915     if (drop_start < 0 || drop_start > 100 ||
   3916         drop_slope < 0 || drop_slope > 90) {
   3917         return BCM_E_PARAM;
   3918     }
   3919 
   3920     if (BCM_GPORT_IS_SET(port)) {
   3921         BCM_IF_ERROR_RETURN
   3922             (_bcm_tr_cosq_resolve_mod_port(unit, port, &modid,
   3923                                            &local_port, &trunk_id));
   3924         BCM_PBMP_PORT_SET(pbmp, local_port);
   3925     } else {
   3926         if (port == -1) {
   3927             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   3928         } else if (!SOC_PORT_VALID(unit, port)) {
   3929             return BCM_E_PORT;
   3930         } else {
   3931             BCM_PBMP_PORT_SET(pbmp, port);
   3932         }
   3933     }
   3934 
   3935     if (cosq < -1 || cosq >= _tr_num_cosq[unit]) {
   3936         return BCM_E_PARAM;
   3937     } else if (cosq == -1) {
   3938         cosq_start = 0;
   3939         num_cosq = _tr_num_cosq[unit];
   3940     } else {
   3941         cosq_start = cosq;
   3942         num_cosq = 1;
   3943     }
   3944 
   3945     /* Init structure */
   3946     bcm_cosq_gport_discard_t_init(&discard);
   3947 
   3948     /* BCM_COSQ_DISCARD_ENABLE & BCM_COSQ_DISCARD_CAP_AVERAGE
   3949      * from current state */
   3950     bcm_sc_cosq_discard_get(unit, &(discard.flags));
   3951 
   3952     discard.flags |= color;
   3953 
   3954     /*
   3955      * average queue size is reculated every 4us, the formula is
   3956      * avg_qsize(t + 1) =
   3957      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   3958      * gain = log2(average_time / 4)
   3959      */
   3960     bits = (average_time / 4) & 0xffff;
   3961     bits |= bits >> 1;
   3962     bits |= bits >> 2;
   3963     bits |= bits >> 4;
   3964     bits |= bits >> 8;
   3965     discard.gain = _shr_popcount(bits);
   3966     /* Don't alow negative value of gain */
   3967     if (discard.gain) {
   3968         discard.gain -= 1;
   3969     }
   3970 
   3971     /*
   3972      * per-port cell limit may be disabled.
   3973      * per-port per-cos cell limit may be set to use dynamic method.
   3974      * therefore drop_start percentage is based on per-device total shared
   3975      * cells.
   3976      */
   3977     SOC_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMITr(unit, &rval));
   3978     shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMITr,
   3979                                      rval, OP_BUFFER_SHARED_LIMITf);
   3980     discard.min_thresh = drop_start * shared_limit / 100;
   3981 
   3982     /* Calculate the max threshold. For a given slope (angle in 
   3983      * degrees), determine how many cells are in the range from
   3984      * 0% drop probability to 100% drop probability. Add that
   3985      * number to the min_threshold for the the max_threshold.
   3986      */
   3987 
   3988     /* Because SC_CELL_FIELD_MAX == TR_PACKET_FIELD_MAX(unit),
   3989      * we can use the TR packet converter as our cell converter */
   3990     discard.max_thresh = discard.min_thresh +
   3991         _bcm_tr_angle_to_packets(drop_slope);
   3992     if (discard.max_thresh > SC_CELL_FIELD_MAX) {
   3993         discard.max_thresh = SC_CELL_FIELD_MAX;
   3994     }
   3995 
   3996     /* Put thresholds in units of bytes */
   3997     discard.min_thresh *= _BCM_TR_COSQ_CELLSIZE;
   3998     discard.max_thresh *= _BCM_TR_COSQ_CELLSIZE;
   3999     discard.flags |= BCM_COSQ_DISCARD_BYTES;
   4000 
   4001     /* We use drop probabily of 1 here.  Use bcm_cosq_gport_discard_set
   4002      * for more flexibility. */
   4003     discard.drop_probability = 100;
   4004 
   4005     BCM_PBMP_ITER(pbmp, local_port) {
   4006         _bcm_gport_dest_t_init(&dest);
   4007         dest.port = local_port;
   4008         dest.gport_type = _SHR_GPORT_TYPE_LOCAL;
   4009         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, &gport));
   4010         for (i = cosq_start; i < (cosq_start + num_cosq); i++) { 
   4011             BCM_IF_ERROR_RETURN
   4012                 (bcm_tr_cosq_gport_discard_set(unit, gport, i, &discard));
   4013         }
   4014     }
   4015     return BCM_E_NONE;
   4016 }
   4017 
   4018 int
   4019 bcm_sc_cosq_discard_port_get(int unit, bcm_port_t port,
   4020                              bcm_cos_queue_t cosq,
   4021                              uint32 color,
   4022                              int *drop_start,
   4023                              int *drop_slope,
   4024                              int *average_time)
   4025 {
   4026     bcm_module_t modid;
   4027     bcm_port_t local_port;
   4028     bcm_trunk_t trunk_id;
   4029     bcm_pbmp_t pbmp;
   4030     _bcm_gport_dest_t dest;
   4031     bcm_gport_t gport;
   4032     uint32 min_thresh, max_thresh, shared_limit;
   4033     uint32 rval;
   4034     bcm_cosq_gport_discard_t discard;
   4035 
   4036     if (!_tr_num_cosq[unit]) {
   4037         return BCM_E_INIT;
   4038     }
   4039 
   4040     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   4041         return BCM_E_PARAM;
   4042     }
   4043 
   4044     if (BCM_GPORT_IS_SET(port)) {
   4045         BCM_IF_ERROR_RETURN
   4046             (_bcm_tr_cosq_resolve_mod_port(unit, port, &modid,
   4047                                            &local_port, &trunk_id));
   4048         BCM_PBMP_PORT_SET(pbmp, local_port);
   4049     } else {
   4050         if (port == -1) {
   4051             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   4052         } else if (!SOC_PORT_VALID(unit, port)) {
   4053             return BCM_E_PORT;
   4054         } else {
   4055             BCM_PBMP_PORT_SET(pbmp, port);
   4056         }
   4057     }
   4058 
   4059     if (cosq < -1 || cosq >= _tr_num_cosq[unit]) {
   4060         return BCM_E_PARAM;
   4061     } else if (cosq == -1) {
   4062         cosq = 0;
   4063     }
   4064 
   4065     BCM_PBMP_ITER(pbmp, local_port) {
   4066         _bcm_gport_dest_t_init(&dest);
   4067         dest.port = local_port;
   4068         dest.gport_type = _SHR_GPORT_TYPE_LOCAL;
   4069         BCM_IF_ERROR_RETURN(_bcm_esw_gport_construct(unit, &dest, &gport));
   4070 
   4071         /* Init structure */
   4072         bcm_cosq_gport_discard_t_init(&discard);
   4073 
   4074         /* Prepare input flags */
   4075         /* Convert color to flags */
   4076         discard.flags |= color;
   4077         discard.flags |= BCM_COSQ_DISCARD_BYTES;
   4078 
   4079         BCM_IF_ERROR_RETURN
   4080             (bcm_tr_cosq_gport_discard_get(unit, gport, cosq, &discard));
   4081 
   4082         /*
   4083          * average queue size is reculated every 4us, the formula is
   4084          * avg_qsize(t + 1) =
   4085          *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   4086          */
   4087         *average_time = (1 << discard.gain) * 4;
   4088 
   4089         /* Change bytes to cells for the following calculations */
   4090         min_thresh = discard.min_thresh / _BCM_SC_COSQ_CELLSIZE;
   4091         max_thresh = discard.max_thresh / _BCM_SC_COSQ_CELLSIZE;
   4092 
   4093         /*
   4094          * per-port cell limit may be disabled.
   4095          * per-port per-cos cell limit may be set to use dynamic method.
   4096          * therefore drop_start percentage is based on per-device total shared
   4097          * cells.
   4098          */
   4099         SOC_IF_ERROR_RETURN(READ_OP_BUFFER_SHARED_LIMITr(unit, &rval));
   4100         shared_limit = soc_reg_field_get(unit, OP_BUFFER_SHARED_LIMITr,
   4101                                          rval, OP_BUFFER_SHARED_LIMITf);
   4102         *drop_start = min_thresh * 100 / shared_limit;
   4103 
   4104         /* Calculate the slope using the min and max threshold.
   4105          * The angle is calculated knowing drop probability at min
   4106          * threshold is 0% and drop probability at max threshold is 100%.
   4107          */
   4108         *drop_slope = _bcm_tr_packets_to_angle(max_thresh - min_thresh);
   4109         break;
   4110     }
   4111 
   4112     return BCM_E_NONE;
   4113 }
   4114 
   4115 /*
   4116  * Function:
   4117  *      bcm_sc_cosq_gport_sched_set
   4118  * Purpose:
   4119  *
   4120  * Parameters:
   4121  *      unit - (IN) Unit number.
   4122  *      gport - (IN) GPORT ID.
   4123  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   4124  *      mode - (IN) Scheduling mode, one of BCM_COSQ_xxx
   4125  *      weight - (IN) Weight for the specified COS queue(s)
   4126  *               Unused if mode is BCM_COSQ_STRICT.
   4127  * Returns:
   4128  *      BCM_E_XXX
   4129  */
   4130 int
   4131 bcm_sc_cosq_gport_sched_set(int unit, bcm_gport_t gport,
   4132                             bcm_cos_queue_t cosq, int mode, int weight)
   4133 {
   4134     bcm_module_t modid;
   4135     bcm_port_t local_port;
   4136     bcm_trunk_t trunk_id;
   4137     int i;
   4138     bcm_cos_queue_t cosq_start = 0;
   4139     int num_weights = 1, weights[16];
   4140 
   4141     /* Note, we use the TR functions here, but they work for Scorpion */
   4142     BCM_IF_ERROR_RETURN
   4143         (_bcm_tr_cosq_resolve_mod_port(unit, gport, &modid,
   4144                                        &local_port, &trunk_id));
   4145 
   4146     if (cosq >= _tr_num_cosq[unit]) {
   4147         return BCM_E_PARAM;
   4148     } else if (cosq < 0) {
   4149         cosq_start = 0;
   4150         num_weights = 8;
   4151         for (i = 0; i < num_weights; i++) {
   4152             if (i < _tr_num_cosq[unit]) {
   4153                 weights[i] = weight;
   4154             } else {
   4155                 weights[i] = 0;
   4156             }
   4157         }
   4158     } else {
   4159         cosq_start = cosq;
   4160         num_weights = 1;
   4161         weights[0] = weight;
   4162     }
   4163 
   4164     BCM_IF_ERROR_RETURN
   4165         (_bcm_tr_cosq_port_sched_set(unit, ESCONFIGr, COSWEIGHTSr,
   4166                                      MINSPCONFIGr, local_port,
   4167                                      cosq_start, num_weights,
   4168                                      weights, mode));
   4169     return BCM_E_NONE;
   4170 }
   4171 
   4172 /*
   4173  * Function:
   4174  *      bcm_sc_cosq_gport_sched_get
   4175  * Purpose:
   4176  *
   4177  * Parameters:
   4178  *      unit - (IN) Unit number.
   4179  *      gport - (IN) GPORT ID.
   4180  *      cosq - (IN) COS queue
   4181  *      mode - (OUT) Scheduling mode, one of BCM_COSQ_xxx
   4182  *      weight - (OUT) Weight for the specified COS queue(s)
   4183  *               Unused if mode is BCM_COSQ_STRICT.
   4184  * Returns:
   4185  *      BCM_E_XXX
   4186  */
   4187 int
   4188 bcm_sc_cosq_gport_sched_get(int unit, bcm_gport_t gport, 
   4189                             bcm_cos_queue_t cosq, int *mode, int *weight)
   4190 {   
   4191     bcm_module_t modid;
   4192     bcm_port_t local_port;
   4193     bcm_trunk_t trunk_id;
   4194 
   4195     *mode = *weight = 0;
   4196 
   4197     /* Note, we use the TR functions here, but they work for Scorpion */
   4198     BCM_IF_ERROR_RETURN
   4199         (_bcm_tr_cosq_resolve_mod_port(unit, gport, &modid,
   4200                                        &local_port, &trunk_id));
   4201     if (cosq >= _tr_num_cosq[unit]) {
   4202         return BCM_E_PARAM;
   4203     } else if (cosq < 0) {
   4204         cosq = 0;
   4205     }
   4206     BCM_IF_ERROR_RETURN
   4207         (_bcm_tr_cosq_port_sched_get(unit, ESCONFIGr, COSWEIGHTSr, 
   4208                                      local_port, cosq, 1,
   4209                                      weight, mode));
   4210     return BCM_E_NONE;
   4211 }
   4212 
   4213 #endif /* BCM_SCORPION_SUPPORT */
   4214 
   4215 #ifndef BCM_SW_STATE_DUMP_DISABLE
   4216 /*
   4217  * Function:
   4218  *     bcm_tr_cosq_sw_dump
   4219  * Purpose:
   4220  *     Displays COS Queue information maintained by software.
   4221  * Parameters:
   4222  *     unit - Device unit number
   4223  * Returns:
   4224  *     None
   4225  */
   4226 void
   4227 bcm_tr_cosq_sw_dump(int unit)
   4228 {
   4229     int  i;
   4230     int  port_count;
   4231 
   4232     LOG_CLI((BSL_META_U(unit,
   4233                         "\nSW Information COSQ - Unit %d\n"), unit));
   4234 
   4235     /* Number COSQ */
   4236     LOG_CLI((BSL_META_U(unit,
   4237                         "    Number: %d\n"), _tr_num_cosq[unit]));
   4238 
   4239     /* Number of COSQs per port */
   4240     port_count = _bcm_tr_cosq_port_count_get(unit);
   4241     LOG_CLI((BSL_META_U(unit,
   4242                         "    Number COSQ per port:\n")));
   4243     if (_tr_num_port_cosq[unit] != NULL) {
   4244         for (i = 0; i < port_count; i++) {
   4245             LOG_CLI((BSL_META_U(unit,
   4246                                 "        Port %2d: %d\n"), i,
   4247                      _tr_num_port_cosq[unit][i]));
   4248         }
   4249     }
   4250 
   4251     /* COSQ Map profile */
   4252     /* Display those entries with reference count > 0 */
   4253     LOG_CLI((BSL_META_U(unit,
   4254                         "    COSQ Map Profile:\n")));
   4255     if (_tr_cos_map_profile[unit] != NULL) {
   4256         int     num_entries;
   4257         int     ref_count;
   4258         int     entries_per_set;
   4259         uint32  index;
   4260         port_cos_map_entry_t *entry_p;
   4261         uint32  cosq, hg_cosq;
   4262 
   4263         num_entries = soc_mem_index_count
   4264             (unit, _tr_cos_map_profile[unit]->tables[0].mem);
   4265         LOG_CLI((BSL_META_U(unit,
   4266                             "        Number of entries: %d\n"), num_entries));
   4267         LOG_CLI((BSL_META_U(unit,
   4268                             "        Index RefCount EntriesPerSet - "
   4269                  "COS HG_COS\n")));
   4270 
   4271         for (index = 0; index < num_entries;
   4272              index += TR_COS_MAP_ENTRIES_PER_SET) {
   4273             if (SOC_FAILURE
   4274                 (soc_profile_mem_ref_count_get(unit,
   4275                                                _tr_cos_map_profile[unit],
   4276                                                index, &ref_count))) {
   4277                 break;
   4278             }
   4279 
   4280             if (ref_count <= 0) {
   4281                 continue;
   4282             }
   4283 
   4284             for (i = 0; i < TR_COS_MAP_ENTRIES_PER_SET; i++) {
   4285                 entries_per_set =
   4286                     _tr_cos_map_profile[unit]->tables[0].entries[index+i].entries_per_set;
   4287                 LOG_CLI((BSL_META_U(unit,
   4288                                     "       %5d %8d %13d    "),
   4289                          index + i, ref_count, entries_per_set));
   4290 
   4291                 entry_p = SOC_PROFILE_MEM_ENTRY(unit,
   4292                                                 _tr_cos_map_profile[unit],
   4293                                                 port_cos_map_entry_t *,
   4294                                                 index + i);
   4295                 cosq = soc_mem_field32_get(unit,
   4296                                            PORT_COS_MAPm,
   4297                                            entry_p,
   4298                                            COSf);
   4299                 LOG_CLI((BSL_META_U(unit,
   4300                                     "%2d "), cosq));
   4301                 if (soc_mem_field_valid(unit, PORT_COS_MAPm, HG_COSf)) {
   4302                     hg_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm,
   4303                                                   entry_p,
   4304                                                   HG_COSf);
   4305                     LOG_CLI((BSL_META_U(unit,
   4306                                         "   %2d"), hg_cosq));
   4307                 }
   4308                 LOG_CLI((BSL_META_U(unit,
   4309                                     "\n")));
   4310             }
   4311         }
   4312     }
   4313 
   4314     return;
   4315 }
   4316 #endif /*  BCM_SW_STATE_DUMP_DISABLE */
   4317 
   4318 #else /* BCM_TRX_SUPPORT */
   4319 int _tr_cosq_not_empty;
   4320 #endif  /* BCM_TRX_SUPPORT */
   4321