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


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * COS Queue Management
      8  * Purpose: API to set different cosq, priorities, and scheduler registers.
      9  */
     10 
     11 #include <shared/bsl.h>
     12 
     13 #include <sal/core/libc.h>
     14 #include <soc/defs.h>
     15 #if defined(BCM_HURRICANE_SUPPORT)
     16 #include <soc/drv.h>
     17 #include <soc/scache.h>
     18 #include <soc/profile_mem.h>
     19 #include <soc/debug.h>
     20 #include <soc/hurricane.h>
     21 
     22 #include <bcm/error.h>
     23 #include <bcm/cosq.h>
     24 
     25 #include <bcm_int/esw/cosq.h>
     26 #include <bcm_int/esw/mbcm.h>
     27 #include <bcm_int/esw/firebolt.h>
     28 #include <bcm_int/esw/hurricane.h>
     29 #ifdef BCM_GREYHOUND_SUPPORT
     30 #include <bcm_int/esw/greyhound.h>
     31 #include <bcm_int/esw/ecn.h>
     32 #endif /* BCM_GREYHOUND_SUPPORT */
     33 #ifdef BCM_HURRICANE3_SUPPORT
     34 #include <bcm_int/esw/hurricane3.h>
     35 #endif /* BCM_HURRICANE3_SUPPORT */
     36 
     37 #include <bcm_int/esw_dispatch.h>
     38 
     39 #ifdef BCM_WARM_BOOT_SUPPORT
     40 #include <bcm_int/esw/switch.h>
     41 #endif /* BCM_WARM_BOOT_SUPPORT */
     42 
     43 
     44 #define BCM_HU_MTU_QUANTA_ID_COUNT 4
     45 #define BCM_HU_COS_WEIGHT_MAX      0x7f
     46 
     47 
     48 /* COSQ where output of hierarchical COSQs scheduler is attached */
     49 
     50 /* MMU cell size in bytes */
     51 
     52 
     53 #define	MMU_CELL_SIZE		128	/* not overrideable */
     54 #define   MMU_FLOW_PERCENT	90
     55 #define   MMU_FLOW_FANIN		4
     56 #define   MMU_FLOW_PKTMIN		8	/* not overrideable */
     57 #define	MMU_RED_DROP_PERCENT	60
     58 #define	MMU_YELLOW_DROP_PERCENT	80
     59 #define	MMU_STATIC_BYTES	(1536 * 1)
     60 #define	MMU_STATIC_PERCENT	50	/* not used if STATIC_BYTES set */
     61 #define	MMU_RESET_BYTES		(1536 * 2)
     62 #define	MMU_RESET_MIN_PERCENT	50	/* not overrideable */
     63 #define	MMU_OVERCOMMIT		1	/* non-stack dynamic cell overcommit */
     64 #define	MMU_OVERCOMMIT_STACK	2	/* stack dynamic cell overcommit */
     65 
     66 #define BCM_HU_CNG_PKT_LIMIT_GRANULARITY       4
     67 #define HU_DRR_KBYTES   (1)
     68 #define HU_DRR_WEIGHT_MAX       0x7f
     69 #define HU_WRR_WEIGHT_MAX       0x7f
     70 
     71 /* COS Map profile entries per set */
     72 #define HU_COS_MAP_ENTRIES_PER_SET    16
     73 
     74 #define HU_BURST_GRANULARITY   64 /* 64bytes */
     75 #define HU_BURST_GRANULARITY_DEFAULT   HU_BURST_GRANULARITY
     76 #define HU_BURST_GRANULARITY_128B   128 /* 128 bytes */
     77 #define HU_BW_FIELD_MAX        0x3FFFF
     78 
     79 
     80 
     81 /* Cache of COS_MAP Profile Table */
     82 STATIC soc_profile_mem_t *_hu_cos_map_profile[BCM_MAX_NUM_UNITS] = {NULL};
     83 
     84 #ifdef BCM_GREYHOUND_SUPPORT
     85 #define GH_CELL_FIELD_MAX       0x3fff
     86 /* MMU cell size in bytes */
     87 #define _BCM_GH_BYTES_PER_CELL            128   /* bytes */
     88 #define _BCM_GH_BYTES_TO_CELLS(_byte_)  \
     89     (((_byte_) + _BCM_GH_BYTES_PER_CELL - 1) / _BCM_GH_BYTES_PER_CELL)
     90 
     91 STATIC soc_profile_mem_t *_bcm_gh_wred_profile[BCM_MAX_NUM_UNITS];
     92 
     93 /* WRED update interval unit : us */
     94 STATIC int _bcm_gh_wred_update_interval[BCM_MAX_NUM_UNITS];
     95 
     96 #endif /* BCM_GREYHOUND_SUPPORT */
     97 
     98 /* Number of COSQs configured for this device */
     99 STATIC int _hu_num_cosq[SOC_MAX_NUM_DEVICES];
    100 
    101 
    102 STATIC soc_field_t
    103 _hu_cosfld[] = {
    104                 COS0THDMODEf,
    105                 COS1THDMODEf,
    106                 COS2THDMODEf,
    107                 COS3THDMODEf,
    108                 COS4THDMODEf,
    109                 COS5THDMODEf,
    110                 COS6THDMODEf,
    111                 COS7THDMODEf,
    112             };
    113 
    114 /*      
    115  *  Convert HW drop probability to percent value
    116  */     
    117 STATIC int       
    118 _bcm_hu_hw_drop_prob_to_api_val[] = {
    119     1000,  /* 0  */
    120     125,   /* 1  */
    121     63,    /* 2  */
    122     31,    /* 3  */
    123     16,    /* 4  */
    124     8,     /* 5  */
    125     4,     /* 6  */
    126     2,     /* 7  */
    127 };
    128 
    129 STATIC int       
    130 _bcm_hu2_hw_drop_prob_to_api_val[] = {
    131     1000,  /* 0  */
    132     63,   /* 1  */
    133     31,    /* 2  */
    134     16,    /* 3  */
    135     8,    /* 4  */
    136     4,     /* 5  */
    137     2,     /* 6  */
    138     1,     /* 7  */
    139 };
    140 
    141 
    142 static int MTU_HU_Quanta[BCM_HU_MTU_QUANTA_ID_COUNT] = {
    143     2 *  HU_DRR_KBYTES,     /* Quanta of 2048 bytes */
    144     4 *  HU_DRR_KBYTES,     /* Quanta of 4096 bytes */
    145     8 *  HU_DRR_KBYTES,     /* Quanta of 8192 bytes */
    146    16 *  HU_DRR_KBYTES      /* Quanta of 16384 bytes */
    147 };
    148 
    149 /*Forward Declaration*/
    150 STATIC int
    151 _bcm_hu_cosq_port_sched_get(int unit, soc_reg_t config_reg, 
    152                             soc_reg_t weight_reg, bcm_port_t port,
    153                             bcm_cos_queue_t start_cosq,
    154                             int num_weights, int weights[], int *mode);
    155 
    156 STATIC int
    157 _bcm_hu_cosq_config_set(int unit, int numq);
    158 
    159 STATIC int     
    160 _bcm_hu_cosq_port_sched_set(int unit, soc_reg_t config_reg, 
    161                             soc_reg_t weight_reg, bcm_port_t port,
    162                             bcm_cos_queue_t start_cosq,
    163                             int num_weights, const int weights[], 
    164                             int mode);
    165 
    166 STATIC int
    167 _bcm_hu_api_val_to_hw_drop_prob(int api_val) {
    168    int i;
    169    for (i = 7; i > 0 ; i--) {
    170       if (api_val <= _bcm_hu_hw_drop_prob_to_api_val[i]) {
    171           break;
    172       }
    173    }
    174    return i;
    175 }
    176 
    177 STATIC int
    178 _bcm_hu2_api_val_to_hw_drop_prob(int api_val) {
    179    int i;
    180    for (i = 7; i > 0 ; i--) {
    181       if (api_val <= _bcm_hu2_hw_drop_prob_to_api_val[i]) {
    182           break;
    183       }
    184    }
    185    return i;
    186 }
    187 
    188 
    189 static int
    190 _bcm_hu_cos_max_weight(const int weight[])
    191 {
    192     int i, max_weight = 0;
    193 
    194     /* find max weight */
    195     for (i = 0; i < 8; i++ ) {
    196         if (max_weight < weight[i]) {
    197             max_weight = weight[i];
    198         }
    199     }
    200     return max_weight;
    201 }
    202 
    203 
    204 STATIC int
    205 _bcm_hu_cosq_resolve_mod_port(int unit, bcm_gport_t gport,
    206                               bcm_module_t *modid, bcm_port_t *port,
    207                               bcm_trunk_t *trunk_id, int *is_local)
    208 {
    209     int gport_id;
    210 
    211     BCM_IF_ERROR_RETURN
    212         (_bcm_esw_gport_resolve(unit, gport, modid,
    213                                 port, trunk_id, &gport_id));
    214     BCM_IF_ERROR_RETURN(
    215         _bcm_esw_modid_is_local(unit, *modid, is_local));
    216 
    217     return BCM_E_NONE;
    218 }
    219 
    220 /*
    221  * Calculates the Quanta needed for COS according to its weight
    222  */
    223 static int
    224 _bcm_hu_cos_drr_weights_to_quanta(const int weight[])
    225 {
    226     int i, max_weight = 0;
    227 
    228     max_weight = _bcm_hu_cos_max_weight(weight);
    229 
    230     for (i = 0; i < BCM_HU_MTU_QUANTA_ID_COUNT; i++ ) {
    231         if (max_weight <= MTU_HU_Quanta[i] * BCM_HU_COS_WEIGHT_MAX) {
    232             return i;   /* Right Quanta was found */
    233         }
    234     }
    235     return -1;  /* In case of too big weight return negative value */
    236 }
    237 /*
    238  * Convert the number of kbytes (1024 bytes) that can transmtted in one run
    239  * to weight encoding 
    240  */
    241 static int
    242 _bcm_hu_mtu_cos_drr_kbytes_to_weight(int kbytes, int MTUQuantaSel)
    243 {
    244     int cos_weight = 0;
    245     int weight_found = FALSE, low_weight_boundary, hi_weight_boundary;
    246 
    247     /* Search for right weight */
    248     low_weight_boundary = 1;
    249     hi_weight_boundary = BCM_HU_COS_WEIGHT_MAX;
    250 
    251     /* Boundary conditions */
    252     if (kbytes >= hi_weight_boundary * MTU_HU_Quanta[MTUQuantaSel]) {
    253         cos_weight = hi_weight_boundary;
    254         weight_found = TRUE;
    255     }
    256     if (kbytes <= low_weight_boundary * MTU_HU_Quanta[MTUQuantaSel]) {
    257         cos_weight = low_weight_boundary;
    258         weight_found = TRUE;
    259     }
    260     while (!weight_found) {
    261         cos_weight =  (hi_weight_boundary + low_weight_boundary) / 2;
    262         if (kbytes <= cos_weight * MTU_HU_Quanta[MTUQuantaSel]) {
    263            if (kbytes > ((cos_weight - 1) * MTU_HU_Quanta[MTUQuantaSel])) {
    264                weight_found = TRUE;
    265            } else {
    266                hi_weight_boundary = cos_weight;
    267            }
    268         } else {
    269             if (kbytes <= ((cos_weight + 1) * MTU_HU_Quanta[MTUQuantaSel])) {
    270                 cos_weight++;
    271                 weight_found = TRUE;
    272             } else {
    273                 low_weight_boundary = cos_weight;
    274             }
    275         }
    276     } /* Here weight should be found */
    277     return cos_weight;
    278 }
    279 
    280 /*
    281  * Convert the encoded weights to number of kbytes that can transmtted
    282  * in one run.
    283  */
    284 static int
    285 _bcm_hu_mtu_cos_drr_weight_to_kbytes(int weight, int MTUQuantaSel)
    286 {
    287     return (weight * MTU_HU_Quanta[MTUQuantaSel]);
    288 }
    289 
    290 #ifdef BCM_WARM_BOOT_SUPPORT
    291 
    292 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    293 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
    294 
    295 /*
    296  * Function:
    297  *      bcm_hu_cosq_sync
    298  * Purpose:
    299  *      Record COSQ module persistent info for Level 2 Warm Boot.
    300  * Parameters:
    301  *      unit - Unit number.
    302  * Returns:
    303  *      BCM_E_XXX
    304  */
    305 int
    306 bcm_hu_cosq_sync(int unit)
    307 {
    308     soc_scache_handle_t scache_handle;
    309     uint8               *cosq_scache_ptr;
    310     uint32              num_cosq;
    311 
    312     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    313     BCM_IF_ERROR_RETURN
    314         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    315                                  0, &cosq_scache_ptr, 
    316                                  BCM_WB_DEFAULT_VERSION, NULL));
    317     
    318     /* Number COSQ */
    319     num_cosq = _hu_num_cosq[unit];
    320     sal_memcpy(cosq_scache_ptr, &num_cosq, sizeof(num_cosq));
    321         
    322     return BCM_E_NONE;
    323 }
    324 
    325 /*
    326  * Function:
    327  *      _bcm_hu_cosq_reinit
    328  * Purpose:
    329  *      Recover COSQ software state.
    330  * Parameters:
    331  *      unit - Unit number.
    332  * Returns:
    333  *      BCM_E_XXX
    334  */
    335 STATIC int
    336 _bcm_hu_cosq_reinit(int unit)
    337 {
    338     int                 rv;
    339     soc_scache_handle_t scache_handle;
    340     uint8               *cosq_scache_ptr;
    341     uint32              num_cosq;
    342 #ifdef BCM_GREYHOUND_SUPPORT    
    343     int i, profile_index;
    344     mmu_wred_config_entry_t qentry;
    345 #endif /* BCM_GREYHOUND_SUPPORT */
    346     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    347     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    348                                  0, &cosq_scache_ptr, 
    349                                  BCM_WB_DEFAULT_VERSION, NULL);
    350 
    351     if (rv == BCM_E_NOT_FOUND) {
    352         cosq_scache_ptr = NULL;
    353     } else if (BCM_FAILURE(rv)) {
    354         return rv;
    355     }
    356 
    357     if (cosq_scache_ptr != NULL) {
    358         /* Number COSQ */
    359         sal_memcpy(&num_cosq, cosq_scache_ptr, sizeof(num_cosq));
    360         _hu_num_cosq[unit] = num_cosq;
    361     } else {
    362         _hu_num_cosq[unit] = _bcm_esw_cosq_config_property_get(unit);
    363     }
    364 
    365 #ifdef BCM_GREYHOUND_SUPPORT
    366 	if (soc_feature(unit, soc_feature_discard_ability)) {
    367         for (i = soc_mem_index_min(unit, MMU_WRED_CONFIGm);
    368              i <= soc_mem_index_max(unit, MMU_WRED_CONFIGm); i++) {
    369             BCM_IF_ERROR_RETURN(
    370                   soc_mem_read(unit, MMU_WRED_CONFIGm, 
    371                     MEM_BLOCK_ALL, i, &qentry));
    372              
    373             profile_index = soc_mem_field32_get(unit, MMU_WRED_CONFIGm, 
    374                 &qentry, PROFILE_INDEXf);
    375              
    376             BCM_IF_ERROR_RETURN
    377                 (soc_profile_mem_reference(unit, _bcm_gh_wred_profile[unit],
    378                                            profile_index, 1));
    379         }
    380     }
    381 #endif /* BCM_GREYHOUND_SUPPORT */
    382     
    383     return BCM_E_NONE;
    384 }
    385 #endif /* BCM_WARM_BOOT_SUPPORT */
    386 
    387 /* Function:
    388  *      bcm_hu_cosq_init
    389  * Purpose:
    390  *      Initialize (clear) all COS schedule/mapping state.
    391  * Parameters:
    392  *      unit - StrataSwitch unit number.
    393  * Returns:
    394  *      BCM_E_XXX
    395  */
    396 
    397 int
    398 bcm_hu_cosq_init(int unit)
    399 {
    400      STATIC int _hu_max_cosq = -1;
    401     int num_cos = 0;
    402 #ifdef BCM_WARM_BOOT_SUPPORT
    403     int                 rv;
    404     soc_scache_handle_t scache_handle;
    405     uint32              cosq_scache_size;
    406     uint8               *cosq_scache_ptr;
    407 #endif /* BCM_WARM_BOOT_SUPPORT */
    408 #ifdef BCM_GREYHOUND_SUPPORT
    409     static soc_mem_t wred_mems[6] = {
    410         MMU_WRED_DROP_PROFILE_GREENm, 
    411         MMU_WRED_DROP_PROFILE_YELLOWm,
    412         MMU_WRED_DROP_PROFILE_REDm,
    413         MMU_WRED_MARK_PROFILE_GREENm,
    414         MMU_WRED_MARK_PROFILE_YELLOWm,
    415         MMU_WRED_MARK_PROFILE_REDm
    416     };
    417 
    418     int entry_words[6];
    419     uint32              interval;
    420 #endif /* BCM_GREYHOUND_SUPPORT */
    421 
    422     if (_hu_max_cosq < 0) {
    423         _hu_max_cosq = NUM_COS(unit);
    424         NUM_COS(unit) = 8;
    425     }
    426 
    427     if (!SOC_WARM_BOOT(unit)) {    /* Cold Boot */
    428         BCM_IF_ERROR_RETURN (bcm_hu_cosq_detach(unit, 0));
    429 #if defined(BCM_GREYHOUND_SUPPORT)
    430         if (soc_feature(unit, soc_feature_discard_ability)) {
    431             BCM_IF_ERROR_RETURN(
    432                 soc_mem_clear(unit, MMU_WRED_CONFIGm, COPYNO_ALL, TRUE));
    433         }
    434 #endif /* BCM_GREYHOUND_SUPPORT */
    435     }
    436 
    437     num_cos = _bcm_esw_cosq_config_property_get(unit);
    438 
    439 #ifdef BCM_GREYHOUND_SUPPORT
    440     if (soc_feature(unit, soc_feature_discard_ability)) {
    441         /* Create profile for MMU_WRED_DROP_CURVE_PROFILE_x tables */
    442         if (_bcm_gh_wred_profile[unit] == NULL) {
    443             _bcm_gh_wred_profile[unit] = 
    444                     sal_alloc(sizeof(soc_profile_mem_t), "WRED Profile Mem");
    445             if (_bcm_gh_wred_profile[unit] == NULL) {
    446                 return BCM_E_MEMORY;
    447             }
    448             soc_profile_mem_t_init(_bcm_gh_wred_profile[unit]);
    449         } else {
    450             soc_profile_mem_destroy(unit, _bcm_gh_wred_profile[unit]);
    451         }
    452 
    453         entry_words[0] =
    454             sizeof(mmu_wred_drop_profile_green_entry_t) / sizeof(uint32);
    455         entry_words[1] =
    456             sizeof(mmu_wred_drop_profile_yellow_entry_t) / sizeof(uint32);
    457         entry_words[2] =
    458             sizeof(mmu_wred_drop_profile_red_entry_t) / sizeof(uint32);
    459         entry_words[3] =
    460             sizeof(mmu_wred_mark_profile_green_entry_t) / sizeof(uint32);
    461         entry_words[4] =
    462             sizeof(mmu_wred_mark_profile_yellow_entry_t) / sizeof(uint32);
    463         entry_words[5] =
    464             sizeof(mmu_wred_mark_profile_red_entry_t) / sizeof(uint32);
    465         BCM_IF_ERROR_RETURN
    466             (soc_profile_mem_create(unit, wred_mems, entry_words, 6,
    467                                     _bcm_gh_wred_profile[unit]));
    468 
    469         /*
    470          * WRED update inetrval
    471          * For the SKUs that system core clock is at 300Mhz,
    472          * the WRED update interval is changed to 1us from 2us(default)
    473          */
    474         if (SOC_IS_GREYHOUND(unit)) {
    475             if (soc_feature(unit, soc_feature_core_clock_300m)) {
    476                 _bcm_gh_wred_update_interval[unit] = 1; /* 1 us */
    477                     BCM_IF_ERROR_RETURN(
    478                         soc_reg_field32_modify(unit, TIME_DOMAINr,
    479                             REG_PORT_ANY, WRED_UPDATE_INTERVALf, 0));
    480             } else {
    481                 _bcm_gh_wred_update_interval[unit] = 2; /* 2 us */
    482             }
    483         } else {
    484             /* HURRICANE3 */
    485             /* WRED_UPDATE_INTERVAL = 240 * (1+2/16) * core_clock_period */
    486             interval =  240 * (1+2/16) / SOC_INFO(unit).frequency;
    487             BCM_IF_ERROR_RETURN(
    488                     soc_reg_field32_modify(unit, TIME_DOMAINr,
    489                         REG_PORT_ANY, WRED_UPDATE_INTERVALf, interval));
    490              _bcm_gh_wred_update_interval[unit] = interval + 1;
    491         }
    492     }
    493 #endif /* BCM_GREYHOUND_SUPPORT */        
    494 
    495 #ifdef BCM_WARM_BOOT_SUPPORT
    496     /* Warm boot level 2 cache size */
    497     cosq_scache_size = sizeof(uint32); /* Number COSQ */
    498 
    499     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    500     rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
    501                                  (0 == SOC_WARM_BOOT(unit)),
    502                                  cosq_scache_size, &cosq_scache_ptr, 
    503                                  BCM_WB_DEFAULT_VERSION, NULL);
    504     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    505         return rv;
    506     }
    507 
    508     if (SOC_WARM_BOOT(unit)) {
    509         BCM_IF_ERROR_RETURN(_bcm_hu_cosq_reinit(unit));
    510         num_cos = _hu_num_cosq[unit];
    511     }
    512 #endif /* BCM_WARM_BOOT_SUPPORT */
    513 
    514     return bcm_hu_cosq_config_set(unit, num_cos);
    515 }
    516 
    517 
    518 
    519 
    520 
    521 int     
    522 bcm_hu_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
    523                               int mode, const int weights[], int delay)
    524 {
    525     uint32 wrr;
    526     int                 port;
    527     uint32              cosarbsel;
    528     int mbits = 0;
    529     int                 i, max_weight;
    530     int                 enc_weights[8];
    531     int                 MTUQuantaSel = 0;
    532     int                 num_cosq;
    533     
    534     COMPILER_REFERENCE(delay);
    535 
    536     /* Activated cosq number */
    537     num_cosq = _hu_num_cosq[unit];
    538 
    539     mbcm_driver[unit]->mbcm_cosq_sched_weight_max_get(unit, mode, &max_weight);
    540     if((mode != BCM_COSQ_STRICT) && (mode != BCM_COSQ_ROUND_ROBIN) &&
    541              (max_weight != BCM_COSQ_WEIGHT_UNLIMITED)) {
    542         for(i = 0; i < num_cosq; i++) {
    543             if((weights[i] < 0) || (weights[i] > max_weight)) {
    544                 return BCM_E_PARAM;
    545             }
    546         }
    547     }
    548 
    549     switch (mode) {
    550     case BCM_COSQ_STRICT:
    551         mbits = 0;
    552         break;
    553     case BCM_COSQ_ROUND_ROBIN:
    554         mbits = 1;
    555         break;
    556     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
    557         mbits = 2;
    558         /*
    559          * All weight values must fit within 7 bits.
    560          * If weight is 0, this queue is run in strict mode,
    561          * others run in WRR mode.
    562          */
    563 
    564         for(i = 0; i < num_cosq; i++) {
    565             enc_weights[i] = weights[i];
    566         }
    567         break;
    568     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
    569         mbits = 3;
    570         if (soc_feature(unit, soc_feature_linear_drr_weight)) {
    571             MTUQuantaSel = _bcm_hu_cos_drr_weights_to_quanta(weights);
    572             if (MTUQuantaSel < 0) {
    573                 return BCM_E_PARAM;
    574             }
    575             for (i = 0; i < num_cosq; i++) {
    576                 if (weights[i]) {
    577                     enc_weights[i] =
    578                         _bcm_hu_mtu_cos_drr_kbytes_to_weight(weights[i],
    579                                 MTUQuantaSel);
    580                 } else {
    581                     enc_weights[i] = weights[i];
    582                 }
    583             }
    584         }/*soc_feature_linear_drr_weight*/
    585         break;
    586     case BCM_COSQ_BOUNDED_DELAY:        /* not supported in xgs */
    587     default:
    588         return BCM_E_PARAM;
    589     }
    590 
    591     PBMP_ITER(pbm, port) {
    592         cosarbsel = 0;
    593         soc_reg_field_set(unit, XQCOSARBSELr, &cosarbsel, COSARBf, mbits);
    594         if ((mode == BCM_COSQ_DEFICIT_ROUND_ROBIN) &&
    595                 (soc_feature(unit, soc_feature_linear_drr_weight))) {
    596             soc_reg_field_set(unit, XQCOSARBSELr, &cosarbsel,
    597                     MTU_QUANTA_SELECTf, MTUQuantaSel);
    598         }
    599         SOC_IF_ERROR_RETURN(WRITE_XQCOSARBSELr(unit, port, cosarbsel));
    600     }
    601 
    602     if ((mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) ||
    603         (mode == BCM_COSQ_DEFICIT_ROUND_ROBIN)) {
    604         /*
    605          * Weighted Fair Queueing scheduling among vaild COSs
    606          */
    607         PBMP_ITER(pbm, port) {
    608             if (soc_feature(unit, soc_feature_linear_drr_weight)) {
    609                 for (i = 0; i < num_cosq; i++) {
    610                     SOC_IF_ERROR_RETURN(READ_WRRWEIGHT_COSr(unit, port,
    611                                         i, &wrr));
    612                     soc_reg_field_set(unit, WRRWEIGHT_COSr, &wrr,
    613                               WEIGHTf, enc_weights[i]);
    614                     SOC_IF_ERROR_RETURN(WRITE_WRRWEIGHT_COSr(unit, port,
    615                                         i, wrr));
    616                 }
    617             }
    618         }
    619     }
    620     return BCM_E_NONE;
    621 }
    622 
    623 /*
    624  * Function:
    625  *      bcm_cosq_port_sched_get
    626  * Purpose:
    627  *      Retrieve class-of-service policy and corresponding weights and delay
    628  * Parameters:
    629  *      unit     - StrataSwitch unit number.
    630  *      pbm      - port bitmap
    631  *      mode     - (output) Scheduling mode, one of BCM_COSQ_xxx
    632  *      weights  - (output) Weights for each COS queue
    633  *                          Only for BCM_COSQ_WEIGHTED_ROUND_ROBIN and
    634  *                          BCM_COSQ_DEFICIT_ROUND_ROBIN mode.
    635  *                 For DRR Weight is specified in Kbytes
    636  *      delay    - This parameter is not used
    637  * Returns:
    638  *      BCM_E_XXX
    639  * Notes:
    640  *      Actually just returns data for the first port in the bitmap
    641  */
    642 
    643 int
    644 bcm_hu_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
    645                            int *mode, int weights[], int *delay)
    646 {
    647     uint32              cosarbsel, wrr;
    648     int                 mbits, port,i;
    649     int                 MTUQuantaSel = -1;	
    650     int                 num_cosq;
    651 
    652     /* Activated cosq number */
    653     num_cosq = _hu_num_cosq[unit];
    654 
    655     mbits = -1;
    656     PBMP_ITER(pbm, port) {
    657         SOC_IF_ERROR_RETURN(READ_XQCOSARBSELr(unit, port, &cosarbsel));
    658         mbits = soc_reg_field_get(unit, XQCOSARBSELr, cosarbsel, COSARBf);
    659         if(soc_feature(unit, soc_feature_linear_drr_weight)) {
    660             MTUQuantaSel =
    661                 soc_reg_field_get(unit, XQCOSARBSELr, cosarbsel,
    662                                   MTU_QUANTA_SELECTf);
    663         }
    664         break;
    665     }
    666     switch (mbits) {
    667     case 0:
    668         *mode = BCM_COSQ_STRICT;
    669         break;
    670     case 1:
    671         *mode = BCM_COSQ_ROUND_ROBIN;
    672         break;
    673     case 2:
    674         *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
    675         break;
    676     case 3:
    677         *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
    678         break;
    679     default:
    680         return BCM_E_INTERNAL;
    681     }
    682     if ((mbits == 2) || (mbits == 3)) {
    683         wrr = 0;
    684         if (soc_feature(unit, soc_feature_linear_drr_weight)) {
    685             PBMP_ITER(pbm, port) {
    686                 for (i = 0; i < num_cosq; i++) {
    687                     SOC_IF_ERROR_RETURN(READ_WRRWEIGHT_COSr(unit, port,
    688                                                             i, &wrr));
    689                     weights[i] = soc_reg_field_get(unit, WRRWEIGHT_COSr,
    690                                                    wrr, WEIGHTf);
    691                 }
    692             }
    693         }
    694         if (mbits == 3) {
    695             int i;
    696             for(i = 0; i < num_cosq; i++) {
    697                 if (soc_feature(unit, soc_feature_linear_drr_weight)) {
    698                         weights[i] =
    699                             _bcm_hu_mtu_cos_drr_weight_to_kbytes(weights[i],
    700                                                              MTUQuantaSel);
    701                 } 
    702             }
    703         }
    704     }
    705     if (delay) {
    706         *delay = 0;
    707     }
    708     return BCM_E_NONE;
    709 }
    710 
    711 
    712 int
    713 bcm_hu_cosq_port_bandwidth_set(int unit, bcm_port_t port,
    714                                bcm_cos_queue_t cosq,
    715                                uint32 kbits_sec_min,
    716                                uint32 kbits_sec_max,
    717                                uint32 kbits_sec_burst,
    718                                uint32 flags)
    719 {
    720     uint32 regval, rval = 0;
    721     uint32 bucket_val = 0;
    722     uint32  burst_size = 0;
    723     uint32 refresh_rate, bucketsize, granularity = 3, meter_flags = 0;
    724     int    refresh_bitsize, bucket_bitsize;
    725     uint32 fval = 0;
    726     uint32 eav_gran = HU_BURST_GRANULARITY_DEFAULT;
    727 
    728     /*
    729      * To set the new Bandwidth settings, the procedure adopted is
    730      * a. reset MAXBUCKETCONFIG, MINBUCKETCONFIG, MAXBUCKET,MINBUCKET
    731      * b. update MAXBUCKETCONFIG and MINBUCKETCONFIG with new values passed
    732      * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it.
    733      */
    734 
    735    /*for hurricane there is only one formula for ITU weight hence no need of selection*/
    736 
    737     /* Disable egress metering for this port */
    738     BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIGr(unit, port, cosq, &regval));
    739     soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval, MAX_REFRESHf, 0);
    740     soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval, MAX_THD_SELf, 0);
    741     BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIGr(unit, port, cosq, regval));
    742 
    743     BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIGr(unit, port, cosq, &regval));
    744     soc_reg_field_set(unit, MINBUCKETCONFIGr, &regval, MIN_REFRESHf, 0);
    745     soc_reg_field_set(unit, MINBUCKETCONFIGr, &regval, MIN_THD_SELf, 0);
    746     BCM_IF_ERROR_RETURN(WRITE_MINBUCKETCONFIGr(unit, port, cosq, regval));
    747 
    748     /*reset the MAXBUCKET register*/
    749     soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, MAX_BUCKETf, 0);
    750     soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, IN_PROFILE_FLAGf, 0);
    751     BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETr(unit, port, cosq, bucket_val));
    752 
    753     /*reset the MINBUCKET register value*/
    754     soc_reg_field_set(unit, MINBUCKETr, &bucket_val, MIN_BUCKETf, 0);
    755     soc_reg_field_set(unit, MINBUCKETr, &bucket_val, IN_PROFILE_FLAGf, 0);
    756     BCM_IF_ERROR_RETURN(WRITE_MINBUCKETr(unit, port, cosq, bucket_val));
    757 
    758     refresh_bitsize =
    759         soc_reg_field_length(unit, MINBUCKETCONFIGr, MIN_REFRESHf);
    760     bucket_bitsize =
    761         soc_reg_field_length(unit, MINBUCKETCONFIGr, MIN_THD_SELf);
    762 
    763     if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 
    764         meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECTIVE;
    765         meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT3;
    766         meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT5;
    767         meter_flags |= _BCM_XGS_METER_FLAG_BUCKET_IN_8KB;
    768     }
    769 
    770     BCM_IF_ERROR_RETURN
    771         (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_min, kbits_sec_min,
    772                           meter_flags, refresh_bitsize, bucket_bitsize,
    773                           &refresh_rate, &bucketsize, &granularity));
    774 
    775     if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 
    776         SOC_IF_ERROR_RETURN(READ_SHAPING_Q_GRANr(unit, port, &regval));
    777         if (soc_reg_field_valid(unit, SHAPING_Q_GRANr, MIN_Q_GRANf)) {
    778             fval = soc_reg_field_get(unit, SHAPING_Q_GRANr,
    779                                      regval, MIN_Q_GRANf);
    780             if (granularity == 5) {
    781                 fval |= (1 << cosq);
    782             } else {
    783                 fval &= ~(1 << cosq);
    784             } 
    785             soc_reg_field_set(unit, SHAPING_Q_GRANr, &regval,
    786                               MIN_Q_GRANf, fval);
    787         }
    788         SOC_IF_ERROR_RETURN(WRITE_SHAPING_Q_GRANr(unit, port, regval));
    789     }
    790  
    791 	regval = 0;
    792     soc_reg_field_set(unit, MINBUCKETCONFIGr, &regval,
    793                           MIN_REFRESHf, refresh_rate);
    794     soc_reg_field_set(unit, MINBUCKETCONFIGr, &regval,
    795 		                  MIN_THD_SELf, bucketsize);
    796     BCM_IF_ERROR_RETURN
    797         (WRITE_MINBUCKETCONFIGr(unit, port, cosq, regval));
    798 
    799     refresh_bitsize =
    800         soc_reg_field_length(unit, MAXBUCKETCONFIGr, MAX_REFRESHf);
    801     bucket_bitsize =
    802         soc_reg_field_length(unit, MAXBUCKETCONFIGr, MAX_THD_SELf);
    803 
    804     BCM_IF_ERROR_RETURN
    805         (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_max, kbits_sec_burst,
    806                           meter_flags, refresh_bitsize, bucket_bitsize,
    807                           &refresh_rate, &bucketsize, &granularity));
    808 
    809     if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 
    810         SOC_IF_ERROR_RETURN(READ_SHAPING_Q_GRANr(unit, port, &regval));
    811         if (soc_reg_field_valid(unit, SHAPING_Q_GRANr, MAX_Q_GRANf)) {
    812             fval = soc_reg_field_get(unit, SHAPING_Q_GRANr,
    813                                      regval, MAX_Q_GRANf);
    814             if (granularity == 5) {
    815                 fval |= (1 << cosq);
    816             } else {
    817                 fval &= ~(1 << cosq);
    818             } 
    819             soc_reg_field_set(unit, SHAPING_Q_GRANr, &regval,
    820                               MAX_Q_GRANf, fval);
    821         }
    822         SOC_IF_ERROR_RETURN(WRITE_SHAPING_Q_GRANr(unit, port, regval));
    823     }
    824 
    825 	regval = 0;
    826     soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval,
    827                           MAX_REFRESHf, refresh_rate);
    828     if (flags & BCM_COSQ_BW_EAV_MODE) {
    829         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) && 
    830             (granularity == 5)) {
    831             eav_gran = HU_BURST_GRANULARITY_128B;
    832         } else {
    833             eav_gran = HU_BURST_GRANULARITY_DEFAULT;
    834         }
    835         burst_size = (((kbits_sec_burst * 1000) / 8) +
    836                          (eav_gran - 1)) / eav_gran;
    837         if (burst_size > HU_BW_FIELD_MAX) {
    838             burst_size = HU_BW_FIELD_MAX;
    839         }
    840 
    841         soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval, EAV_MODEf, 1);
    842 
    843         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, EAVBUCKETCONFIG_EXTr, port, 
    844                                                                 cosq, &rval));
    845         soc_reg_field_set(unit, EAVBUCKETCONFIG_EXTr, &rval, EAV_THD_SEL_6LSBf,
    846                                                             burst_size & 0x3f);
    847         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, EAVBUCKETCONFIG_EXTr, port, 
    848                                                                   cosq, rval));
    849         soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval, MAX_THD_SELf,
    850                                                    (burst_size >> 6 & 0xFFF)); 
    851     } else {
    852         soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval, MAX_THD_SELf,
    853                           bucketsize); 
    854     }
    855     BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIGr(unit, port, cosq, regval));
    856 
    857     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
    858 
    859     return BCM_E_NONE;
    860 }
    861 
    862 /*
    863  * Function:
    864  *      bcm_cosq_gport_bandwidth_get
    865  * Purpose:
    866  *
    867  * Parameters:
    868  *      unit - (IN) Unit number.
    869  *      gport - (IN) GPORT ID.
    870  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
    871  *      kbits_sec_min - (OUT) minimum bandwidth, kbits/sec.
    872  *      kbits_sec_max - (OUT) maximum bandwidth, kbits/sec.
    873  *      flags - (OUT) BCM_COSQ_BW_*
    874  * Returns:
    875  *      BCM_E_XXX
    876  */
    877 int
    878 bcm_hu_cosq_gport_bandwidth_get(int unit, bcm_gport_t gport,
    879                                 bcm_cos_queue_t cosq, uint32 *kbits_sec_min,
    880                                 uint32 *kbits_sec_max, uint32 *flags)
    881 {
    882     bcm_module_t modid;
    883     bcm_port_t local_port;
    884     bcm_trunk_t trunk_id;
    885     int is_local;
    886     uint32 kbits_max_burst; /* Placeholder */
    887 
    888     *kbits_sec_min = *kbits_sec_max = *flags = 0;
    889 
    890     BCM_IF_ERROR_RETURN
    891         (_bcm_hu_cosq_resolve_mod_port(unit, gport, &modid,
    892                                        &local_port, &trunk_id, &is_local));
    893     
    894     if (is_local) {
    895 		
    896         if (cosq >= _hu_num_cosq[unit]) {
    897             return BCM_E_PARAM;
    898         } else if (cosq < 0) {
    899             cosq = 0;
    900         }
    901        
    902         BCM_IF_ERROR_RETURN
    903             (bcm_hu_cosq_port_bandwidth_get(unit, local_port, cosq,
    904                                             kbits_sec_min, kbits_sec_max,
    905                                            &kbits_max_burst, flags));
    906     } else {
    907         return BCM_E_PORT;
    908     }
    909     return BCM_E_NONE;
    910 }
    911 
    912 /*  
    913  * Function:
    914  *      bcm_hu_cosq_gport_bandwidth_set
    915  * Purpose:
    916  *       
    917  * Parameters:
    918  *      unit - (IN) Unit number.
    919  *      gport - (IN) GPORT ID.
    920  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
    921  *      kbits_sec_min - (IN) minimum bandwidth, kbits/sec.
    922  *      kbits_sec_max - (IN) maximum bandwidth, kbits/sec.
    923  *      flags - (IN) BCM_COSQ_BW_*
    924  * Returns:
    925  *      BCM_E_XXX 
    926  */ 
    927 int
    928 bcm_hu_cosq_gport_bandwidth_set(int unit, bcm_gport_t gport,
    929                                 bcm_cos_queue_t cosq, uint32 kbits_sec_min,
    930                                 uint32 kbits_sec_max, uint32 flags)
    931 {
    932     bcm_module_t modid;
    933     bcm_port_t local_port;
    934     bcm_trunk_t trunk_id;
    935     int i, is_local;
    936     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
    937 
    938     BCM_IF_ERROR_RETURN
    939         (_bcm_hu_cosq_resolve_mod_port(unit, gport, &modid,
    940                                        &local_port, &trunk_id, &is_local));
    941 
    942     if (is_local) {
    943 
    944         if (cosq >= _hu_num_cosq[unit]) {
    945             return BCM_E_PARAM;
    946         } else if (cosq < 0) {
    947             cosq_start = 0;
    948             cosq_end = _hu_num_cosq[unit] - 1;
    949         } else {
    950                 cosq_start = cosq_end = cosq;
    951             }
    952         for (i = cosq_start; i <= cosq_end; i++) {
    953             BCM_IF_ERROR_RETURN
    954                 (bcm_hu_cosq_port_bandwidth_set(unit, local_port, i,
    955                                                 kbits_sec_min,
    956                                                 kbits_sec_max,
    957                                                 kbits_sec_max,
    958                                                 flags));
    959         }
    960     } else {
    961         return BCM_E_PORT;
    962     }
    963     return BCM_E_NONE;
    964 }
    965 
    966 /*
    967  * Function:
    968  *      bcm_cosq_gport_sched_get
    969  * Purpose:
    970  *
    971  * Parameters:
    972  *      unit - (IN) Unit number.
    973  *      gport - (IN) GPORT ID.
    974  *      cosq - (IN) COS queue
    975  *      mode - (OUT) Scheduling mode, one of BCM_COSQ_xxx
    976  *      weight - (OUT) Weight for the specified COS queue(s)
    977  *               Unused if mode is BCM_COSQ_STRICT.
    978  * Returns:
    979  *      BCM_E_XXX
    980  */
    981 int
    982 bcm_hu_cosq_gport_sched_get(int unit, bcm_gport_t gport, 
    983                             bcm_cos_queue_t cosq, int *mode, int *weight)
    984 {   
    985     bcm_module_t modid;
    986     bcm_port_t local_port;
    987     bcm_trunk_t trunk_id;
    988     int is_local;
    989     soc_reg_t config_reg = XQCOSARBSELr;
    990     soc_reg_t weight_reg = WRRWEIGHT_COSr;
    991 
    992     *mode = *weight = 0;
    993 
    994     BCM_IF_ERROR_RETURN
    995         (_bcm_hu_cosq_resolve_mod_port(unit, gport, &modid,
    996                                        &local_port, &trunk_id, &is_local));
    997     if (is_local) {
    998 
    999         if (cosq >= _hu_num_cosq[unit]) {
   1000             return BCM_E_PARAM;
   1001         } else if (cosq < 0) {
   1002             cosq = 0;
   1003         }
   1004         BCM_IF_ERROR_RETURN
   1005             (_bcm_hu_cosq_port_sched_get(unit, config_reg, weight_reg, 
   1006                                          local_port, cosq, 1,
   1007                                          weight, mode));
   1008     } else {
   1009         return BCM_E_PORT;
   1010     }
   1011     return BCM_E_NONE;
   1012 }
   1013 
   1014 /*
   1015  * Function:
   1016  *      bcm_hu_cosq_gport_sched_set
   1017  * Purpose:
   1018  *
   1019  * Parameters:
   1020  *      unit - (IN) Unit number.
   1021  *      gport - (IN) GPORT ID.
   1022  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   1023  *      mode - (IN) Scheduling mode, one of BCM_COSQ_xxx
   1024  *      weight - (IN) Weight for the specified COS queue(s)
   1025  *               Unused if mode is BCM_COSQ_STRICT.
   1026  * Returns:
   1027  *      BCM_E_XXX
   1028  */
   1029 int
   1030 bcm_hu_cosq_gport_sched_set(int unit, bcm_gport_t gport,
   1031                             bcm_cos_queue_t cosq, int mode, int weight)
   1032 {
   1033     bcm_module_t modid;
   1034     bcm_port_t local_port;
   1035     bcm_trunk_t trunk_id;
   1036     int i, is_local;
   1037     bcm_cos_queue_t cosq_start = 0;
   1038     int num_weights = 1, weights[8];
   1039     soc_reg_t config_reg = XQCOSARBSELr;
   1040     soc_reg_t weight_reg = WRRWEIGHT_COSr;
   1041 
   1042     sal_memset(weights, 0, sizeof(weights));
   1043     BCM_IF_ERROR_RETURN
   1044         (_bcm_hu_cosq_resolve_mod_port(unit, gport, &modid,
   1045                                        &local_port, &trunk_id, &is_local));
   1046 
   1047     if (is_local) {
   1048         /*if (!_hu_num_port_cosq[unit]) {
   1049             return BCM_E_INIT;
   1050         }*/
   1051 
   1052             if (cosq >= _hu_num_cosq[unit]) {
   1053                 return BCM_E_PARAM;
   1054             } else if (cosq < 0) {
   1055                 cosq_start = 0;
   1056                 num_weights = 8;
   1057                 for (i = 0; i < num_weights; i++) {
   1058                     if (i < _hu_num_cosq[unit]) {
   1059                         weights[i] = weight;
   1060                     } else {
   1061                         weights[i] = 0;
   1062                     }
   1063                 }
   1064             } else {
   1065                 cosq_start = cosq;
   1066                 num_weights = 1;
   1067                 weights[0] = weight;
   1068             }
   1069 
   1070 
   1071         BCM_IF_ERROR_RETURN
   1072             (_bcm_hu_cosq_port_sched_set(unit, config_reg, weight_reg, 
   1073                                          local_port, cosq_start, num_weights,
   1074                                          weights, mode));
   1075     } else {
   1076         return BCM_E_PORT;
   1077     }
   1078     return BCM_E_NONE;
   1079 }
   1080 
   1081 
   1082 int
   1083 bcm_hu_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   1084                                bcm_cos_queue_t cosq,
   1085                                uint32 *kbits_sec_min,
   1086                                uint32 *kbits_sec_max,
   1087                                uint32 *kbits_sec_burst,
   1088                                uint32 *flags)
   1089 {
   1090     uint32 regval;
   1091     uint32 refresh_rate = 0, bucketsize = 0,
   1092         granularity = 3, meter_flags = 0;
   1093     uint32 kbits_min_burst; /* Placeholder, since burst is unused for min */
   1094     uint32 rval = 0;
   1095     uint32 bucket_lo = 0;
   1096     uint32 eav_mode = 0; 
   1097     uint32 fval = 0;
   1098     uint32 eav_gran = HU_BURST_GRANULARITY_DEFAULT;
   1099 
   1100     if (!kbits_sec_min || !kbits_sec_max || !kbits_sec_burst || !flags) {
   1101         return (BCM_E_PARAM);
   1102     }
   1103 
   1104     *flags = 0;
   1105 
   1106     if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   1107         meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1108         
   1109         granularity = 3; /* reset to default */
   1110         SOC_IF_ERROR_RETURN(READ_SHAPING_Q_GRANr(unit, port, &regval));
   1111         if (soc_reg_field_valid(unit, SHAPING_Q_GRANr, MIN_Q_GRANf)) {
   1112            fval = soc_reg_field_get(unit, SHAPING_Q_GRANr,
   1113            regval, MAX_Q_GRANf);
   1114            if (fval & (1 << cosq)) {
   1115                granularity = 5;
   1116            } 
   1117         }
   1118     }
   1119 
   1120     BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIGr(unit, port, cosq, &regval));
   1121     refresh_rate = soc_reg_field_get(unit, MAXBUCKETCONFIGr,
   1122                                              regval, MAX_REFRESHf);
   1123     bucketsize = soc_reg_field_get(unit, MAXBUCKETCONFIGr,
   1124                                              regval, MAX_THD_SELf);
   1125     eav_mode = soc_reg_field_get(unit, MAXBUCKETCONFIGr,
   1126                                              regval, EAV_MODEf);
   1127     BCM_IF_ERROR_RETURN
   1128         (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   1129                                            granularity, meter_flags,
   1130                                            kbits_sec_max, kbits_sec_burst));
   1131     if (eav_mode == 1) {
   1132         *flags |= BCM_COSQ_BW_EAV_MODE;
   1133         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, EAVBUCKETCONFIG_EXTr, 
   1134                                                   port, cosq, &rval));
   1135         bucket_lo = soc_reg_field_get(unit, EAVBUCKETCONFIG_EXTr, 
   1136                                                   rval, EAV_THD_SEL_6LSBf);
   1137         if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) && 
   1138             (granularity == 5)) {
   1139             eav_gran = HU_BURST_GRANULARITY_128B;
   1140         } else {
   1141             eav_gran = HU_BURST_GRANULARITY_DEFAULT;
   1142         }
   1143         *kbits_sec_burst = (((bucketsize << 6) | bucket_lo) * 
   1144                                eav_gran * 8) / 1000;
   1145     }
   1146 
   1147     BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIGr(unit, port, cosq, &regval));
   1148 
   1149     refresh_rate = soc_reg_field_get(unit, MINBUCKETCONFIGr,
   1150                                              regval, MIN_REFRESHf);
   1151 
   1152     if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   1153         meter_flags = 0; /* reset to default */
   1154         granularity = 3; /* reset to default */
   1155         
   1156         meter_flags |= _BCM_XGS_METER_FLAG_GRANULARITY;
   1157         SOC_IF_ERROR_RETURN(READ_SHAPING_Q_GRANr(unit, port, &regval));
   1158         if (soc_reg_field_valid(unit, SHAPING_Q_GRANr, MAX_Q_GRANf)) {
   1159             fval = soc_reg_field_get(unit, SHAPING_Q_GRANr,
   1160                                      regval, MIN_Q_GRANf);
   1161             if (fval & (1 << cosq)) {
   1162                 granularity = 5;
   1163             } 
   1164         }
   1165     }
   1166 
   1167     BCM_IF_ERROR_RETURN
   1168         (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, 0,
   1169                                            granularity, meter_flags,
   1170                                            kbits_sec_min, &kbits_min_burst));
   1171 
   1172 
   1173     return BCM_E_NONE;
   1174 }
   1175 
   1176 
   1177 STATIC int
   1178 _bcm_hu_cosq_port_sched_get(int unit, soc_reg_t config_reg, 
   1179                             soc_reg_t weight_reg, bcm_port_t port,
   1180                             bcm_cos_queue_t start_cosq,
   1181                             int num_weights, int weights[], int *mode)
   1182 {
   1183     uint32 escfg, wrr;
   1184     int mbits, i, cosq;
   1185     int MTUQuantaSel = -1;
   1186 
   1187     SOC_IF_ERROR_RETURN(READ_XQCOSARBSELr(unit, port, &escfg));
   1188     mbits = soc_reg_field_get(unit, config_reg, escfg, COSARBf);
   1189     MTUQuantaSel = soc_reg_field_get(unit, config_reg, escfg,
   1190                                      MTU_QUANTA_SELECTf);
   1191     
   1192     switch (mbits) {
   1193     case 0:
   1194         *mode = BCM_COSQ_STRICT;
   1195         break;
   1196     case 1:
   1197         *mode = BCM_COSQ_ROUND_ROBIN;
   1198         break;
   1199     case 2:
   1200         *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   1201         break;
   1202     case 3:
   1203         *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   1204         break;
   1205     default:
   1206         return BCM_E_INTERNAL;
   1207     }
   1208 
   1209     if ((mbits == 2) || (mbits == 3)) {
   1210         wrr = 0;
   1211         for(cosq = start_cosq, i = 0; i < num_weights; cosq++, i++) {
   1212             SOC_IF_ERROR_RETURN(READ_WRRWEIGHT_COSr(unit, port,
   1213                         cosq, &wrr));
   1214             weights[i] = soc_reg_field_get(unit, weight_reg, wrr,
   1215                                            WEIGHTf);
   1216         }
   1217     
   1218         if (mbits == 3) {
   1219             int i;
   1220             for(i = 0; i < num_weights; i++) {
   1221                 weights[i] = _bcm_hu_mtu_cos_drr_weight_to_kbytes(weights[i],MTUQuantaSel);
   1222             }
   1223         }
   1224     }   
   1225     return BCM_E_NONE;
   1226 }
   1227 
   1228 /*
   1229  * Convert the number of kbytes (1024 bytes) that can transmtted in one run
   1230  * to weight encoding for 
   1231  */
   1232 static int
   1233 _bcm_hu_cos_drr_kbytes_to_weight(int kbytes, int MTUQuantaSel)
   1234 {
   1235     int cos_weight = 0;
   1236     int weight_found = FALSE, low_weight_boundary, hi_weight_boundary;
   1237 
   1238     /* Search for right weight */
   1239     low_weight_boundary = 1;
   1240     hi_weight_boundary = BCM_HU_COS_WEIGHT_MAX;
   1241 
   1242     /* Boundary conditions */
   1243     if (kbytes >= hi_weight_boundary * MTU_HU_Quanta[MTUQuantaSel]) {
   1244         cos_weight = hi_weight_boundary;
   1245         weight_found = TRUE;
   1246     }
   1247     if (kbytes <= low_weight_boundary * MTU_HU_Quanta[MTUQuantaSel]) {
   1248         cos_weight = low_weight_boundary;
   1249         weight_found = TRUE;
   1250     }
   1251 
   1252     while (!weight_found) {
   1253         cos_weight =  (hi_weight_boundary + low_weight_boundary) / 2;
   1254         if (kbytes <= cos_weight * MTU_HU_Quanta[MTUQuantaSel]) {
   1255            if (kbytes > ((cos_weight - 1) * MTU_HU_Quanta[MTUQuantaSel])) {
   1256                weight_found = TRUE;
   1257            } else {
   1258                hi_weight_boundary = cos_weight;
   1259            }
   1260         } else {
   1261             if (kbytes <= ((cos_weight + 1) * MTU_HU_Quanta[MTUQuantaSel])) {
   1262                 cos_weight++;
   1263                 weight_found = TRUE;
   1264             } else {
   1265                 low_weight_boundary = cos_weight;
   1266             }
   1267         }
   1268     } /* Here weight should be found */
   1269 
   1270     return cos_weight;
   1271 }
   1272 
   1273 
   1274 STATIC int     
   1275 _bcm_hu_cosq_port_sched_set(int unit, soc_reg_t config_reg, 
   1276                             soc_reg_t weight_reg, bcm_port_t port,
   1277                             bcm_cos_queue_t start_cosq,
   1278                             int num_weights, const int weights[], 
   1279                             int mode)
   1280 {
   1281     int t, i, cosq;
   1282     uint32 wrr;
   1283     int mbits = 0;
   1284     int enc_weights[8];
   1285     int MTUQuantaSel = 0;	
   1286     
   1287     switch (mode) {
   1288     case BCM_COSQ_STRICT:
   1289         mbits = 0;
   1290         break;
   1291     case BCM_COSQ_ROUND_ROBIN:
   1292         mbits = 1;
   1293         break;
   1294     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   1295         mbits = 2;
   1296         /*
   1297          * All weight values must fit within 7 bits.
   1298          * If weight is 0, this queue is run in strict mode,
   1299          * others run in WRR mode.
   1300          */
   1301         t = 0;
   1302         for(i = 0; i < num_weights; i++) {
   1303             t |= weights[i];
   1304         }
   1305         if ((t & ~0x7f) != 0) {
   1306             return BCM_E_PARAM;
   1307         }
   1308         for(i = 0; i < num_weights; i++) {
   1309             enc_weights[i] = weights[i];
   1310         }
   1311         break;
   1312     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   1313         mbits = 3;
   1314 	MTUQuantaSel = _bcm_hu_cos_drr_weights_to_quanta(weights);
   1315 	if (MTUQuantaSel < 0) {
   1316 		return BCM_E_PARAM;
   1317 	}
   1318 
   1319         for(i = 0; i < num_weights; i++) {
   1320             if (weights[i]) {
   1321                 enc_weights[i] =
   1322                     _bcm_hu_cos_drr_kbytes_to_weight(weights[i],
   1323                             MTUQuantaSel);
   1324             } else {
   1325                 enc_weights[i] = weights[i];
   1326             }
   1327 
   1328         }
   1329         break;
   1330     case BCM_COSQ_BOUNDED_DELAY:        /* not supported in xgs */
   1331     default:
   1332         return BCM_E_PARAM;
   1333     }
   1334 
   1335     /* Program the scheduling mode */
   1336     SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, config_reg, port, 
   1337                            COSARBf, mbits));
   1338 
   1339     if ((mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) ||
   1340         (mode == BCM_COSQ_DEFICIT_ROUND_ROBIN)) {
   1341         /*
   1342          * Weighted Fair Queueing scheduling among vaild COSs
   1343          */
   1344         for(cosq = start_cosq, i = 0; i < num_weights; cosq++, i++) {
   1345             SOC_IF_ERROR_RETURN(READ_WRRWEIGHT_COSr(unit, port,
   1346                         cosq, &wrr));
   1347             /*    coverity[uninit_use_in_call : FALSE]    */
   1348             soc_reg_field_set(unit, WRRWEIGHT_COSr, &wrr,
   1349                     WEIGHTf, enc_weights[i]);
   1350             SOC_IF_ERROR_RETURN(WRITE_WRRWEIGHT_COSr(unit, port,
   1351                         cosq, wrr));
   1352 
   1353         }
   1354     }
   1355     return BCM_E_NONE;
   1356 }
   1357 
   1358 
   1359 
   1360 
   1361 /*
   1362  * Function:
   1363  *      bcm_cosq_detach
   1364  * Purpose:
   1365  *      Discard all COS schedule/mapping state.
   1366  * Parameters:
   1367  *      unit - StrataSwitch unit number.
   1368  * Returns:
   1369  *      BCM_E_XXX
   1370  */
   1371 
   1372 int
   1373 bcm_hu_cosq_detach(int unit, int software_state_only)
   1374 {
   1375     bcm_port_t port;
   1376     bcm_pbmp_t port_all;	
   1377     int weights[8];
   1378     int cosq;
   1379 
   1380 
   1381     for (cosq = 0; cosq < 8; cosq++) {
   1382         weights[cosq] = 0;
   1383     }
   1384 
   1385     if (!software_state_only)
   1386     {
   1387         PBMP_ALL_ITER(unit, port) {
   1388             if (IS_CPU_PORT(unit, port)) {
   1389                 continue;
   1390             }
   1391 
   1392             {
   1393                 /* Clear bandwidth settings on port */
   1394                 for (cosq = 0; cosq < 8; cosq++) {
   1395                      BCM_IF_ERROR_RETURN
   1396                         (bcm_hu_cosq_port_bandwidth_set(unit, port, cosq, 0, 0, 0, 0));
   1397                 }
   1398             }
   1399         }
   1400             /* Clear scheduling settings on port */
   1401             cosq = 8;
   1402 	 port_all = PBMP_ALL(unit);	
   1403             BCM_IF_ERROR_RETURN
   1404             (bcm_hu_cosq_port_sched_set(unit, port_all, BCM_COSQ_WEIGHTED_ROUND_ROBIN,
   1405                                          weights, 0));
   1406             /* Clear discard settings on port */
   1407      
   1408 
   1409 
   1410     }
   1411 
   1412     return BCM_E_NONE;
   1413 }
   1414 
   1415 /*
   1416  * Function:
   1417  *      bcm_hu_cosq_config_set
   1418  * Purpose:
   1419  *      Set the number of COS queues
   1420  * Parameters:
   1421  *      unit - Unit number.
   1422  *      numq - number of COS queues (1-8).
   1423  * Returns:
   1424  *      BCM_E_XXX
   1425  */
   1426 
   1427 int
   1428 bcm_hu_cosq_config_set(int unit, int numq)
   1429 {
   1430     int cos, prio, ratio, remain;
   1431     uint32 index;
   1432     soc_mem_t mem = PORT_COS_MAPm; 
   1433     int entry_words = sizeof(port_cos_map_entry_t) / sizeof(uint32);
   1434     bcm_pbmp_t ports;
   1435     bcm_port_t port;
   1436     port_cos_map_entry_t cos_map_array[HU_COS_MAP_ENTRIES_PER_SET];
   1437     void *entries[HU_COS_MAP_ENTRIES_PER_SET];
   1438 #ifdef BCM_GREYHOUND_SUPPORT
   1439     static soc_mem_t wred_mems[6] = {
   1440         MMU_WRED_DROP_PROFILE_GREENm, 
   1441         MMU_WRED_DROP_PROFILE_YELLOWm,
   1442         MMU_WRED_DROP_PROFILE_REDm,
   1443         MMU_WRED_MARK_PROFILE_GREENm,
   1444         MMU_WRED_MARK_PROFILE_YELLOWm,
   1445         MMU_WRED_MARK_PROFILE_REDm
   1446     };
   1447     int ii, wred_prof_count;
   1448     uint32 profile_index;
   1449     mmu_wred_drop_profile_green_entry_t entry_tcp_green;
   1450     mmu_wred_drop_profile_yellow_entry_t entry_tcp_yellow;
   1451     mmu_wred_drop_profile_red_entry_t entry_tcp_red;
   1452     mmu_wred_mark_profile_green_entry_t entry_mark_green;
   1453     mmu_wred_mark_profile_yellow_entry_t entry_mark_yellow;
   1454     mmu_wred_mark_profile_red_entry_t entry_mark_red;
   1455     void *wred_entries[6];    
   1456 #endif /* BCM_GREYHOUND_SUPPORT */
   1457 
   1458     /* Validate cosq num */
   1459     if (numq < 1) {
   1460         return BCM_E_PARAM;
   1461     }
   1462 
   1463     if (!SOC_WARM_BOOT(unit)) {
   1464         if (SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) {
   1465             SOC_IF_ERROR_RETURN(_bcm_hu_cosq_config_set(unit, numq));
   1466         }
   1467     }
   1468 
   1469     /* Map the eight 802.1 priority levels to the active cosqs */
   1470     if (numq > 8) {
   1471         numq = 8;
   1472     }
   1473     
   1474     sal_memset(cos_map_array, 0,
   1475                HU_COS_MAP_ENTRIES_PER_SET * sizeof(port_cos_map_entry_t));
   1476 
   1477     if (_hu_cos_map_profile[unit] == NULL) {
   1478         _hu_cos_map_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
   1479                                           "COS_MAP Profile Mem");
   1480         if (_hu_cos_map_profile[unit] == NULL) {
   1481             return BCM_E_MEMORY;
   1482         }
   1483         soc_profile_mem_t_init(_hu_cos_map_profile[unit]);
   1484     }
   1485 
   1486     /* Create profile table cache (or re-init if it already exists) */
   1487     SOC_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, &entry_words, 1,
   1488                                                _hu_cos_map_profile[unit]));
   1489 
   1490     if (SOC_WARM_BOOT(unit)) {    /* Warm Boot */
   1491         int     i;
   1492         uint32  val;
   1493 
   1494         /* Gather reference count for cosq map profile table */
   1495         BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
   1496         PBMP_ITER(ports, port) {
   1497             SOC_IF_ERROR_RETURN(READ_COS_MAP_SELr(unit, port, &val));
   1498             index = soc_reg_field_get(unit, COS_MAP_SELr, val, SELECTf);
   1499             index *= HU_COS_MAP_ENTRIES_PER_SET;
   1500             for (i = 0; i < HU_COS_MAP_ENTRIES_PER_SET; i++) {
   1501                 SOC_PROFILE_MEM_REFERENCE(unit, _hu_cos_map_profile[unit],
   1502                                           index + i, 1);
   1503                 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit,
   1504                                                 _hu_cos_map_profile[unit],
   1505                                                 index + i,
   1506                                                 HU_COS_MAP_ENTRIES_PER_SET);
   1507             }
   1508 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   1509             if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
   1510                 SOC_IF_ERROR_RETURN(READ_ICOS_MAP_SELr(unit, port, &val));
   1511                 index = soc_reg_field_get(unit, ICOS_MAP_SELr, val, SELECTf);
   1512                 index *= HU_COS_MAP_ENTRIES_PER_SET;
   1513                 for (i = 0; i < HU_COS_MAP_ENTRIES_PER_SET; i++) {
   1514                     SOC_PROFILE_MEM_REFERENCE(unit, _hu_cos_map_profile[unit],
   1515                                               index + i, 1);
   1516                     SOC_PROFILE_MEM_ENTRIES_PER_SET(unit,
   1517                                                     _hu_cos_map_profile[unit],
   1518                                                     index + i,
   1519                                                     HU_COS_MAP_ENTRIES_PER_SET);
   1520                 }
   1521             }
   1522 #endif /* BCM_COSQ_HIGIG_MAP_DISABLE */
   1523         }
   1524 
   1525         _hu_num_cosq[unit] = numq;
   1526 
   1527         return BCM_E_NONE;
   1528     }
   1529 
   1530     /* Cold Boot */
   1531     ratio = 8 / numq;
   1532     remain = 8 % numq;
   1533     cos = 0;
   1534     for (prio = 0; prio < 8; prio++) {
   1535         soc_mem_field32_set(unit, PORT_COS_MAPm,
   1536                             &cos_map_array[prio], COSf, cos);
   1537         if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
   1538             soc_mem_field32_set(unit, PORT_COS_MAPm,
   1539                                 &cos_map_array[prio], HG_COSf, 0);
   1540         }
   1541 
   1542         if ((prio + 1) == (((cos + 1) * ratio) +
   1543                            ((remain < (numq - cos)) ? 0 :
   1544                             (remain - (numq - cos) + 1)))) {
   1545             cos++;
   1546         }
   1547         entries[prio] = (void *) &cos_map_array[prio];
   1548     }
   1549 
   1550     /* Map remaining internal priority levels to highest priority cosq */
   1551     cos = numq - 1;
   1552     for (prio = 8; prio < 16; prio++) {
   1553         soc_mem_field32_set(unit, PORT_COS_MAPm,
   1554                             &cos_map_array[prio], COSf, cos);
   1555         if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
   1556             soc_mem_field32_set(unit, PORT_COS_MAPm,
   1557                             &cos_map_array[prio], HG_COSf, 0);
   1558         }
   1559         entries[prio] = (void *) &cos_map_array[prio];
   1560     }
   1561 
   1562     /* Map internal priority levels to CPU CoS queues */
   1563     BCM_IF_ERROR_RETURN(_bcm_esw_cpu_cosq_mapping_default_set(unit, numq));
   1564 
   1565     /* Add a profile mem entry for each port */
   1566     BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
   1567     PBMP_ITER(ports, port) {
   1568         SOC_IF_ERROR_RETURN
   1569             (soc_profile_mem_add(unit, _hu_cos_map_profile[unit],
   1570                                  (void *) &entries,
   1571                                  HU_COS_MAP_ENTRIES_PER_SET, &index));
   1572         SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, COS_MAP_SELr, port, 
   1573                                SELECTf, (index / HU_COS_MAP_ENTRIES_PER_SET)));
   1574 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   1575         if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
   1576             SOC_IF_ERROR_RETURN
   1577                 (soc_profile_mem_add(unit, _hu_cos_map_profile[unit],
   1578                                      (void *) &entries,
   1579                                      HU_COS_MAP_ENTRIES_PER_SET, &index));
   1580             SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, ICOS_MAP_SELr, port, 
   1581                                    SELECTf, (index / HU_COS_MAP_ENTRIES_PER_SET)));
   1582         }
   1583 #endif
   1584     }
   1585 
   1586 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
   1587     /* identity mapping for higig ports */
   1588 
   1589     /* map prio0->cos0, prio1->cos1, ... , prio7->cos7 */
   1590     for (prio = 0; prio < 8; prio++) {
   1591         soc_mem_field32_set(unit, PORT_COS_MAPm,
   1592                             &cos_map_array[prio], COSf, prio);
   1593         if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
   1594             soc_mem_field32_set(unit, PORT_COS_MAPm,
   1595                             &cos_map_array[prio], HG_COSf, 0);
   1596         }
   1597     }
   1598     /* Map remaining internal priority levels to highest priority cosq */
   1599     for (prio = 8; prio < 16; prio++) {
   1600         soc_mem_field32_set(unit, PORT_COS_MAPm,
   1601                             &cos_map_array[prio], COSf, 7);
   1602         if (soc_mem_field_valid(unit,PORT_COS_MAPm,HG_COSf)) {
   1603             soc_mem_field32_set(unit, PORT_COS_MAPm,
   1604                             &cos_map_array[prio], HG_COSf, 0);
   1605         }
   1606     }
   1607     PBMP_ITER(ports, port) {
   1608         if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
   1609             SOC_IF_ERROR_RETURN
   1610                 (soc_profile_mem_add(unit, _hu_cos_map_profile[unit],
   1611                                      (void *) &entries,
   1612                                      HU_COS_MAP_ENTRIES_PER_SET, &index));
   1613             soc_reg_field32_modify(unit, ICOS_MAP_SELr, port, 
   1614                                    SELECTf, (index / HU_COS_MAP_ENTRIES_PER_SET));
   1615         }
   1616     }
   1617 #endif
   1618 
   1619     _hu_num_cosq[unit] = numq;
   1620 
   1621 #if defined(BCM_GREYHOUND_SUPPORT)
   1622     if (soc_feature(unit, soc_feature_discard_ability)) {
   1623       /* Add default entries for MMU_WRED_DROP_CURVE_PROFILE_x memory profile */
   1624         sal_memset(&entry_tcp_green, 0, sizeof(entry_tcp_green));
   1625         sal_memset(&entry_tcp_yellow,0, sizeof(entry_tcp_yellow));
   1626         sal_memset(&entry_tcp_red, 0, sizeof(entry_tcp_red));
   1627         sal_memset(&entry_mark_green, 0, sizeof(entry_mark_green));
   1628         sal_memset(&entry_mark_yellow, 0, sizeof(entry_mark_yellow));
   1629         sal_memset(&entry_mark_red, 0, sizeof(entry_mark_red));
   1630         wred_entries[0] = &entry_tcp_green;
   1631         wred_entries[1] = &entry_tcp_yellow;
   1632         wred_entries[2] = &entry_tcp_red;
   1633         wred_entries[3] = &entry_mark_green;
   1634         wred_entries[4] = &entry_mark_yellow;
   1635         wred_entries[5] = &entry_mark_red;
   1636         for (ii = 0; ii < 6; ii++) {
   1637             soc_mem_field32_set(unit, wred_mems[ii], wred_entries[ii], 
   1638                                 MIN_THDf, GH_CELL_FIELD_MAX);
   1639             soc_mem_field32_set(unit, wred_mems[ii], wred_entries[ii], 
   1640                                 MAX_THDf, GH_CELL_FIELD_MAX);
   1641         }
   1642         profile_index = 0xffffffff;
   1643         wred_prof_count = soc_mem_index_count(unit, MMU_WRED_CONFIGm);
   1644         while(wred_prof_count) {
   1645             if (profile_index == 0xffffffff) {
   1646                 BCM_IF_ERROR_RETURN
   1647                     (soc_profile_mem_add(unit, 
   1648                                     _bcm_gh_wred_profile[unit],
   1649                                     wred_entries, 1, &profile_index));
   1650             } else {
   1651                 BCM_IF_ERROR_RETURN
   1652                     (soc_profile_mem_reference(unit,
   1653                                    _bcm_gh_wred_profile[unit],
   1654                                    profile_index, 0));
   1655             }
   1656             wred_prof_count -= 1;
   1657         }
   1658 
   1659         BCM_IF_ERROR_RETURN(
   1660             _bcm_esw_ecn_init(unit));
   1661                 
   1662     }
   1663 #endif /* BCM_GREYHOUND_SUPPORT */
   1664 
   1665 
   1666     return BCM_E_NONE;
   1667 }
   1668 
   1669 /*
   1670  * Function:
   1671  *      bcm_cosq_config_get
   1672  * Purpose:
   1673  *      Get the number of cos queues
   1674  * Parameters:
   1675  *      unit - StrataSwitch unit number.
   1676  *      numq - (Output) number of cosq
   1677  * Returns:
   1678  *      BCM_E_XXX
   1679  */
   1680 
   1681 int
   1682 bcm_hu_cosq_config_get(int unit, int *numq)
   1683 {
   1684     if (_hu_num_cosq[unit] == 0) {
   1685         return BCM_E_INIT;
   1686     }
   1687 
   1688     if (numq != NULL) {
   1689         *numq = _hu_num_cosq[unit];
   1690     }
   1691 
   1692     return BCM_E_NONE;
   1693 }
   1694 
   1695 int
   1696 bcm_hu_cosq_discard_set(int unit, uint32 flags)
   1697 {
   1698     return BCM_E_UNAVAIL;
   1699 }
   1700 
   1701 int
   1702 bcm_hu_cosq_discard_get(int unit, uint32* flags)
   1703 {
   1704     return BCM_E_UNAVAIL;
   1705 }
   1706 
   1707 int
   1708 bcm_hu_cosq_gport_discard_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   1709                               bcm_cosq_gport_discard_t *discard)
   1710 {
   1711     return BCM_E_UNAVAIL;
   1712 }
   1713 
   1714 int
   1715 bcm_hu_cosq_gport_discard_get(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   1716                               bcm_cosq_gport_discard_t *discard)
   1717 {
   1718     return BCM_E_UNAVAIL;
   1719 }                              
   1720 
   1721 
   1722 int
   1723 bcm_hu_cosq_discard_port_set(int unit, bcm_port_t port,
   1724                              bcm_cos_queue_t cosq,
   1725                              uint32 color,
   1726                              int drop_start,
   1727                              int drop_slope,
   1728                              int average_time)
   1729 {
   1730     bcm_port_t local_port;
   1731     bcm_pbmp_t pbmp;
   1732     int i, cosq_start, num_cosq;
   1733     uint32 min_thresh, n;
   1734     uint32 rval, encoding;
   1735     soc_reg_t reg;
   1736     soc_field_t fld;
   1737 
   1738     if (drop_start < 0 || drop_start > 100 || drop_slope > 0) {
   1739         return BCM_E_PARAM;
   1740     }
   1741 
   1742     if (BCM_GPORT_IS_SET(port)) {
   1743         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &local_port));
   1744         BCM_PBMP_PORT_SET(pbmp, local_port);
   1745     } else {
   1746         if (port == -1) {
   1747             BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   1748         } else if (!SOC_PORT_VALID(unit, port)) {
   1749             return BCM_E_PORT;
   1750         } else {
   1751             BCM_PBMP_PORT_SET(pbmp, port);
   1752         }
   1753     }
   1754 
   1755     if (cosq < -1 || cosq >= _hu_num_cosq[unit]) {
   1756         return BCM_E_PARAM;
   1757     } else if (cosq == -1) {
   1758         cosq_start = 0;
   1759         num_cosq = _hu_num_cosq[unit];
   1760     } else {
   1761         cosq_start = cosq;
   1762         num_cosq = 1;
   1763     }
   1764 
   1765     BCM_PBMP_ITER(pbmp, local_port) {
   1766         for (i = cosq_start; i < (cosq_start + num_cosq); i++) { 
   1767             /* Get the start point as a function of the HOL limit */
   1768             SOC_IF_ERROR_RETURN
   1769                 (READ_HOLCOSPKTSETLIMITr(unit, local_port, i, &rval));
   1770             n = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, rval,
   1771                                   PKTSETLIMITf);    
   1772             min_thresh = drop_start * n / 100;
   1773 
   1774             /* Set the drop rate depending on the color */
   1775             if (color == BCM_COSQ_DISCARD_COLOR_GREEN) {
   1776                 reg = CNG1COSDROPRATEr;
   1777             } else {
   1778                 reg = CNG0COSDROPRATEr;
   1779             }
   1780             BCM_IF_ERROR_RETURN(
   1781                 soc_reg32_get(unit, reg, local_port, i, &rval));
   1782 
   1783             if (SOC_IS_HURRICANE2(unit)) {
   1784                 encoding = _bcm_hu2_api_val_to_hw_drop_prob(-1 * drop_slope);
   1785             } else {
   1786                 encoding = _bcm_hu_api_val_to_hw_drop_prob(-1 * drop_slope);
   1787             }
   1788 
   1789             soc_reg_field_set(unit, reg, &rval, DROPRATEf, encoding);
   1790             BCM_IF_ERROR_RETURN(
   1791                 soc_reg32_set(unit, reg, local_port, i, rval));
   1792 
   1793             /* Enable simple RED for the (port, cos) pair */
   1794             BCM_IF_ERROR_RETURN
   1795                 (soc_reg_field32_modify(unit, SIMPLEREDCONFIGr, local_port,
   1796                                         _hu_cosfld[i], 1));
   1797             /* Set the drop threshold depending on the color */ 
   1798             if (color == BCM_COSQ_DISCARD_COLOR_GREEN) {
   1799                 reg = CNGCOSPKTLIMIT1r;
   1800                 fld = CNGPKTSETLIMIT1f;
   1801             } else {
   1802                 reg = CNGCOSPKTLIMIT0r;
   1803                 fld = CNGPKTSETLIMIT0f;
   1804             }
   1805             soc_reg_field_set(unit, reg, &rval, fld, min_thresh);
   1806             BCM_IF_ERROR_RETURN(
   1807                 soc_reg32_set(unit, reg, local_port, i, rval));
   1808         }
   1809     }
   1810 
   1811     return BCM_E_NONE;
   1812 }
   1813 
   1814 int
   1815 bcm_hu_cosq_discard_port_get(int unit, bcm_port_t port,
   1816                              bcm_cos_queue_t cosq,
   1817                              uint32 color,
   1818                              int *drop_start,
   1819                              int *drop_slope,
   1820                              int *average_time)
   1821 {
   1822     bcm_port_t local_port;
   1823     bcm_pbmp_t pbmp;
   1824     uint32 rval, n;
   1825 
   1826     if (BCM_GPORT_IS_SET(port)) {
   1827         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &local_port));
   1828         BCM_PBMP_PORT_SET(pbmp, local_port);
   1829     } else {
   1830         if (port == -1) {
   1831             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   1832         } else if (!SOC_PORT_VALID(unit, port)) {
   1833             return BCM_E_PORT;
   1834         } else {
   1835             BCM_PBMP_PORT_SET(pbmp, port);
   1836         }
   1837     }
   1838     if (cosq < -1 || cosq >= _hu_num_cosq[unit]) {
   1839         return BCM_E_PARAM;
   1840     }
   1841    
   1842     BCM_PBMP_ITER(pbmp, local_port) {
   1843         /* Get the total HOL limit first */
   1844         BCM_IF_ERROR_RETURN
   1845             (READ_HOLCOSPKTSETLIMITr(unit, local_port, 
   1846                                    cosq == -1 ? 0 : cosq, &rval));
   1847         n = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, rval, PKTSETLIMITf);
   1848 
   1849         /* Get the simple RED mode */
   1850         BCM_IF_ERROR_RETURN(READ_SIMPLEREDCONFIGr(unit, local_port, &rval));   
   1851         if (soc_reg_field_get(unit, SIMPLEREDCONFIGr, rval,
   1852                 cosq == -1 ? _hu_cosfld[0] : _hu_cosfld[cosq])) {
   1853             if (color == BCM_COSQ_DISCARD_COLOR_GREEN) {
   1854                 BCM_IF_ERROR_RETURN
   1855                     (READ_CNGCOSPKTLIMIT1r(unit, local_port, 
   1856                          cosq == -1 ? 0 : cosq, &rval));
   1857                 *drop_start = soc_reg_field_get(unit, CNGCOSPKTLIMIT1r, rval, 
   1858                                                 CNGPKTSETLIMIT1f) * 100 / n; 
   1859                 BCM_IF_ERROR_RETURN
   1860                     (READ_CNG1COSDROPRATEr(unit, local_port, 
   1861                         cosq == -1 ? 0 : cosq, &rval));
   1862                 if (SOC_IS_HURRICANE2(unit)) {
   1863                     *drop_slope = -1 * _bcm_hu2_hw_drop_prob_to_api_val[rval];
   1864                 } else {
   1865                     *drop_slope = -1 * _bcm_hu_hw_drop_prob_to_api_val[rval];
   1866                 }
   1867             } else {
   1868                 BCM_IF_ERROR_RETURN
   1869                     (READ_CNGCOSPKTLIMIT0r(unit, local_port, 
   1870                     cosq == -1 ? 0 : cosq, &rval));
   1871                 *drop_start = soc_reg_field_get(unit, CNGCOSPKTLIMIT0r, rval, 
   1872                                                 CNGPKTSETLIMIT0f) * 100 / n; 
   1873                 BCM_IF_ERROR_RETURN
   1874                     (READ_CNG0COSDROPRATEr(unit, local_port, 
   1875                         cosq == -1 ? 0 : cosq, &rval));
   1876                 if (SOC_IS_HURRICANE2(unit)) {
   1877                     *drop_slope = -1 * _bcm_hu2_hw_drop_prob_to_api_val[rval];
   1878                 } else {
   1879                     *drop_slope = -1 * _bcm_hu_hw_drop_prob_to_api_val[rval];
   1880                 }
   1881             }
   1882         }
   1883         break;
   1884     } 
   1885     return BCM_E_NONE;
   1886 }
   1887 
   1888 #if defined(BCM_GREYHOUND_SUPPORT)
   1889 
   1890 /*
   1891  *  Convert HW drop probability to percent value
   1892  */
   1893 STATIC int
   1894 _bcm_gh_hw_drop_prob_to_percent[] = {
   1895     0,     /* 0  */
   1896     1,     /* 1  */
   1897     2,     /* 2  */
   1898     3,     /* 3  */
   1899     4,     /* 4  */
   1900     5,     /* 5  */
   1901     6,     /* 6  */
   1902     7,     /* 7  */
   1903     8,     /* 8  */
   1904     9,     /* 9  */
   1905     10,    /* 10 */
   1906     25,    /* 11 */
   1907     50,    /* 12 */
   1908     75,    /* 13 */
   1909     100,   /* 14 */
   1910     -1     /* 15 */
   1911 };
   1912 
   1913 STATIC int
   1914 _bcm_gh_percent_to_drop_prob(int percent)
   1915 {
   1916    int i;
   1917 
   1918    for (i = 14; i > 0 ; i--) {
   1919       if (percent >= _bcm_gh_hw_drop_prob_to_percent[i]) {
   1920           break;
   1921       }
   1922    }
   1923    return i;
   1924 }
   1925 
   1926 STATIC int
   1927 _bcm_gh_drop_prob_to_percent(int drop_prob) {
   1928    return (_bcm_gh_hw_drop_prob_to_percent[drop_prob]);
   1929 }
   1930 
   1931 /*
   1932  * index: degree, value: contangent(degree) * 100
   1933  * max value is 0x3fff (14-bit) at 0 degree
   1934  */
   1935 STATIC int
   1936 _bcm_gh_cotangent_lookup_table[] =
   1937 {
   1938     /*  0.. 5 */  16383, 5728, 2863, 1908, 1430, 1143,
   1939     /*  6..11 */    951,  814,  711,  631,  567,  514,
   1940     /* 12..17 */    470,  433,  401,  373,  348,  327,
   1941     /* 18..23 */    307,  290,  274,  260,  247,  235,
   1942     /* 24..29 */    224,  214,  205,  196,  188,  180,
   1943     /* 30..35 */    173,  166,  160,  153,  148,  142,
   1944     /* 36..41 */    137,  132,  127,  123,  119,  115,
   1945     /* 42..47 */    111,  107,  103,  100,   96,   93,
   1946     /* 48..53 */     90,   86,   83,   80,   78,   75,
   1947     /* 54..59 */     72,   70,   67,   64,   62,   60,
   1948     /* 60..65 */     57,   55,   53,   50,   48,   46,
   1949     /* 66..71 */     44,   42,   40,   38,   36,   34,
   1950     /* 72..77 */     32,   30,   28,   26,   24,   23,
   1951     /* 78..83 */     21,   19,   17,   15,   14,   12,
   1952     /* 84..89 */     10,    8,    6,    5,    3,    1,
   1953     /* 90     */      0
   1954 };
   1955 
   1956 /*
   1957  * Given a slope (angle in degrees) from 0 to 90, return the number of cells
   1958  * in the range from 0% drop probability to 100% drop probability.
   1959  */
   1960 STATIC int
   1961 _bcm_gh_angle_to_cells(int angle)
   1962 {
   1963     return (_bcm_gh_cotangent_lookup_table[angle]);
   1964 }
   1965 
   1966 /*
   1967  * Given a number of packets in the range from 0% drop probability
   1968  * to 100% drop probability, return the slope (angle in degrees).
   1969  */
   1970 STATIC int
   1971 _bcm_gh_cells_to_angle(int packets)
   1972 {
   1973     int angle;
   1974 
   1975     for (angle = 90; angle >= 0 ; angle--) {
   1976         if (packets <= _bcm_gh_cotangent_lookup_table[angle]) {
   1977             break;
   1978         }
   1979     }
   1980     return angle;
   1981 }
   1982 
   1983 /*
   1984  * Function:
   1985  *     _bcm_gh_cosq_wred_set
   1986  * Purpose:
   1987  *     Configure queue WRED setting
   1988  * Parameters:
   1989  *     unit                - (IN) unit number
   1990  *     port                - (IN) port number or GPORT identifier
   1991  *     cosq                - (IN) COS queue number
   1992  *     flags               - (IN) BCM_COSQ_DISCARD_XXX
   1993  *     min_thresh          - (IN)
   1994  *     max_thresh          - (IN)
   1995  *     drop_probablity     - (IN)
   1996  *     gain                - (IN)
   1997  *     ignore_enable_flags - (IN)
   1998  * Returns:
   1999  *     BCM_E_XXX
   2000  * Notes:
   2001  *     If port is any form of local port, cosq is the hardware queue index.
   2002  */
   2003 STATIC int
   2004 _bcm_gh_cosq_wred_set(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   2005                       uint32 flags, uint32 min_thresh, uint32 max_thresh,
   2006                       int drop_probability, int gain, int ignore_enable_flags,
   2007                       uint32 lflags)
   2008 { 
   2009     int index;
   2010     uint32 profile_index, old_profile_index;
   2011     mmu_wred_drop_profile_green_entry_t entry_tcp_green;
   2012     mmu_wred_drop_profile_yellow_entry_t entry_tcp_yellow;
   2013     mmu_wred_drop_profile_red_entry_t entry_tcp_red;
   2014     mmu_wred_mark_profile_green_entry_t entry_mark_green;
   2015     mmu_wred_mark_profile_yellow_entry_t entry_mark_yellow;
   2016     mmu_wred_mark_profile_red_entry_t entry_mark_red;
   2017     mmu_wred_config_entry_t qentry;
   2018     void *entries[6];
   2019     soc_mem_t mems[6];
   2020     int rate, i, exists = 0;
   2021     static soc_mem_t wred_mems[6] = {
   2022         MMU_WRED_DROP_PROFILE_GREENm, 
   2023         MMU_WRED_DROP_PROFILE_YELLOWm,
   2024         MMU_WRED_DROP_PROFILE_REDm,
   2025         MMU_WRED_MARK_PROFILE_GREENm,
   2026         MMU_WRED_MARK_PROFILE_YELLOWm,
   2027         MMU_WRED_MARK_PROFILE_REDm
   2028     };
   2029 
   2030     /*  
   2031      * MEM_ADDR[7:0]={PORT_ID[4:0], QUEUE_ID[2:0]}
   2032      * PORT_ID[4:0] = 0, PORT 2,
   2033      * PORT_ID[4:0] = 1, PORT 3,
   2034      * ...
   2035      * PORT_ID[4:0] = 27, PORT 29,
   2036      * PORT_ID[4:0] = 28, Invalid,
   2037      */
   2038     if (!SOC_PORT_VALID(unit, port) || (CMIC_PORT(unit) == port)) {
   2039         return BCM_E_PORT;
   2040     }
   2041 
   2042     index = (((port - 2) & 0x1f) << 3) | (cosq & 7); 
   2043 
   2044     if (index < 0) {
   2045         return BCM_E_PARAM;
   2046     }
   2047 
   2048     BCM_IF_ERROR_RETURN
   2049         (soc_mem_read(unit, MMU_WRED_CONFIGm, SOC_BLOCK_ALL, index, &qentry));
   2050     
   2051     old_profile_index = 0xffffffff;
   2052 
   2053     if (flags & BCM_COSQ_DISCARD_NONTCP) {
   2054         /* Greyhound doesnot support non-responsive dropping */ 
   2055         return BCM_E_UNAVAIL;
   2056     }
   2057     
   2058     if (flags & (BCM_COSQ_DISCARD_TCP | BCM_COSQ_DISCARD_COLOR_ALL |
   2059                 BCM_COSQ_DISCARD_MARK_CONGESTION)) {
   2060             old_profile_index = soc_mem_field32_get(unit, MMU_WRED_CONFIGm, 
   2061                                                     &qentry, PROFILE_INDEXf);
   2062         entries[0] = &entry_tcp_green;
   2063         entries[1] = &entry_tcp_yellow;
   2064         entries[2] = &entry_tcp_red;
   2065         entries[3] = &entry_mark_green;
   2066         entries[4] = &entry_mark_yellow;
   2067         entries[5] = &entry_mark_red;
   2068         BCM_IF_ERROR_RETURN
   2069             (soc_profile_mem_get(unit, _bcm_gh_wred_profile[unit],
   2070                                  old_profile_index, 1, entries));
   2071         for (i = 0; i < 6; i++) {
   2072             mems[i] = INVALIDm;
   2073         }
   2074         if ((flags & BCM_COSQ_DISCARD_TCP) || 
   2075                   !(flags & BCM_COSQ_DISCARD_MARK_CONGESTION)) {
   2076             if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   2077                 mems[0] = MMU_WRED_DROP_PROFILE_GREENm;
   2078             }
   2079             if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) { 
   2080                 mems[1] = MMU_WRED_DROP_PROFILE_YELLOWm;
   2081             }
   2082             if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2083                 mems[2] = MMU_WRED_DROP_PROFILE_REDm;
   2084             }
   2085         }
   2086         if (flags & BCM_COSQ_DISCARD_MARK_CONGESTION) {
   2087             if (flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   2088                 mems[3] = MMU_WRED_MARK_PROFILE_GREENm;
   2089             }
   2090             if (flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2091                 mems[4] = MMU_WRED_MARK_PROFILE_YELLOWm;
   2092             }
   2093             if (flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2094                 mems[5] = MMU_WRED_MARK_PROFILE_REDm;
   2095             }
   2096         }
   2097         rate = _bcm_gh_percent_to_drop_prob(drop_probability); 
   2098         for (i = 0; i < 6; i++) {
   2099             exists = 0;
   2100             if ((soc_mem_field32_get(unit, wred_mems[i], entries[i], 
   2101                     MIN_THDf) != GH_CELL_FIELD_MAX) && (mems[i] == INVALIDm)) {
   2102                 mems[i] = wred_mems[i];
   2103                 exists = 1;
   2104             } else {
   2105                 soc_mem_field32_set(unit, wred_mems[i], entries[i], 
   2106                         MIN_THDf, (mems[i] == INVALIDm) ? 
   2107                         GH_CELL_FIELD_MAX : min_thresh); 
   2108             }
   2109 
   2110             if ((soc_mem_field32_get(unit, wred_mems[i], entries[i], 
   2111                         MAX_THDf) != GH_CELL_FIELD_MAX) && 
   2112                         ((mems[i] == INVALIDm) || exists)) {
   2113                 mems[i] = wred_mems[i];
   2114                 exists = 1;
   2115             } else {
   2116                 soc_mem_field32_set(unit, wred_mems[i], entries[i], 
   2117                         MAX_THDf, (mems[i] == INVALIDm) ? 
   2118                         GH_CELL_FIELD_MAX :max_thresh);
   2119             }
   2120 
   2121             if (!exists) {
   2122                 if (soc_mem_field_valid(unit, wred_mems[i], 
   2123                                                         MAX_DROP_RATEf)) {
   2124                     soc_mem_field32_set(unit, wred_mems[i], entries[i], 
   2125                         MAX_DROP_RATEf, (mems[i] == INVALIDm) ? 0 : rate);
   2126                 } else if (soc_mem_field_valid(unit, wred_mems[i], 
   2127                                                         MAX_MARK_RATEf)) {
   2128                     soc_mem_field32_set(unit, wred_mems[i], entries[i], 
   2129                         MAX_MARK_RATEf, (mems[i] == INVALIDm) ? 0 : rate);
   2130                 }
   2131             }
   2132         }
   2133         BCM_IF_ERROR_RETURN
   2134             (soc_profile_mem_add(unit, _bcm_gh_wred_profile[unit], 
   2135                                              entries, 1, &profile_index));
   2136         soc_mem_field32_set(unit, MMU_WRED_CONFIGm, 
   2137                     &qentry, PROFILE_INDEXf, profile_index);
   2138         soc_mem_field32_set(unit, MMU_WRED_CONFIGm, &qentry, WEIGHTf, gain);
   2139     }
   2140     /* Some APIs only modify profiles */
   2141     if (!ignore_enable_flags) {
   2142         soc_mem_field32_set(unit, MMU_WRED_CONFIGm, &qentry, CAP_AVGf,
   2143                           flags & BCM_COSQ_DISCARD_CAP_AVERAGE ? 1 : 0);
   2144         soc_mem_field32_set(unit, MMU_WRED_CONFIGm, &qentry, WRED_ENf,
   2145                           flags & BCM_COSQ_DISCARD_ENABLE ? 1 : 0);
   2146         soc_mem_field32_set(unit, MMU_WRED_CONFIGm, &qentry, ECN_MARKING_ENf,
   2147                           flags & BCM_COSQ_DISCARD_MARK_CONGESTION ?  1 : 0);
   2148     }
   2149 
   2150     BCM_IF_ERROR_RETURN(
   2151           soc_mem_write(unit, MMU_WRED_CONFIGm, MEM_BLOCK_ALL, index, &qentry));
   2152 
   2153     if (old_profile_index != 0xffffffff) {
   2154         SOC_IF_ERROR_RETURN
   2155             (soc_profile_mem_delete(unit, _bcm_gh_wred_profile[unit],
   2156                                     old_profile_index));
   2157     }
   2158 
   2159     return BCM_E_NONE;
   2160 }
   2161 
   2162 /*
   2163  * Function:
   2164  *     _bcm_gh_cosq_wred_get
   2165  * Purpose:
   2166  *     Get queue WRED setting
   2167  * Parameters:
   2168  *     unit                - (IN) unit number
   2169  *     port                - (IN) port number or GPORT identifier
   2170  *     cosq                - (IN) COS queue number
   2171  *     flags               - (IN/OUT) BCM_COSQ_DISCARD_XXX
   2172  *     min_thresh          - (OUT)
   2173  *     max_thresh          - (OUT)
   2174  *     drop_probablity     - (OUT)
   2175  *     gain                - (OUT)
   2176  * Returns:
   2177  *     BCM_E_XXX
   2178  * Notes:
   2179  *     If port is any form of local port, cosq is the hardware queue index.
   2180  */
   2181 STATIC int
   2182 _bcm_gh_cosq_wred_get(int unit, bcm_port_t port, bcm_cos_queue_t cosq,
   2183                       uint32 *flags, uint32 *min_thresh, uint32 *max_thresh,
   2184                       int *drop_probability, int *gain, uint32 lflags)
   2185 {
   2186     int index, profile_index;
   2187     mmu_wred_drop_profile_green_entry_t entry_tcp_green;
   2188     mmu_wred_drop_profile_yellow_entry_t entry_tcp_yellow;
   2189     mmu_wred_drop_profile_red_entry_t entry_tcp_red;
   2190     mmu_wred_mark_profile_green_entry_t entry_mark_green;
   2191     mmu_wred_mark_profile_yellow_entry_t entry_mark_yellow;
   2192     mmu_wred_mark_profile_red_entry_t entry_mark_red;
   2193     void *entries[6];
   2194     void *entry_p = NULL;
   2195     soc_mem_t mem = INVALIDm;
   2196     mmu_wred_config_entry_t qentry;
   2197     int rate = 0;
   2198 
   2199      /*  
   2200      * MEM_ADDR[7:0]={PORT_ID[4:0], QUEUE_ID[2:0]}
   2201      * PORT_ID[4:0] = 0, PORT 2,
   2202      * PORT_ID[4:0] = 1, PORT 3,
   2203      * ...
   2204      * PORT_ID[4:0] = 27, PORT 29,
   2205      * PORT_ID[4:0] = 28, Invalid,
   2206      */
   2207     if (!SOC_PORT_VALID(unit, port) || (CMIC_PORT(unit) == port)) {
   2208         return BCM_E_PORT;
   2209     }
   2210     index = (((port - 2) & 0x1f) << 3) | (cosq & 7);
   2211 
   2212 
   2213     BCM_IF_ERROR_RETURN
   2214         (soc_mem_read(unit, MMU_WRED_CONFIGm, MEM_BLOCK_ALL, index, &qentry));
   2215     profile_index = soc_mem_field32_get(unit, MMU_WRED_CONFIGm,
   2216                                         &qentry, PROFILE_INDEXf);
   2217 
   2218     if (*flags & BCM_COSQ_DISCARD_MARK_CONGESTION) {
   2219         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   2220             mem = MMU_WRED_MARK_PROFILE_GREENm;
   2221             entry_p = &entry_mark_green;
   2222         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2223             mem = MMU_WRED_MARK_PROFILE_YELLOWm;
   2224             entry_p = &entry_mark_yellow;
   2225         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2226             mem = MMU_WRED_MARK_PROFILE_REDm;
   2227             entry_p = &entry_mark_red;
   2228         } else {
   2229             mem = MMU_WRED_MARK_PROFILE_GREENm;
   2230             entry_p = &entry_mark_green;
   2231         }
   2232     } else {
   2233         if (*flags & BCM_COSQ_DISCARD_COLOR_GREEN) {
   2234             mem = MMU_WRED_DROP_PROFILE_GREENm;
   2235             entry_p = &entry_tcp_green;
   2236         } else if (*flags & BCM_COSQ_DISCARD_COLOR_YELLOW) {
   2237             mem = MMU_WRED_DROP_PROFILE_YELLOWm;
   2238             entry_p = &entry_tcp_yellow;
   2239         } else if (*flags & BCM_COSQ_DISCARD_COLOR_RED) {
   2240             mem = MMU_WRED_DROP_PROFILE_REDm;
   2241             entry_p = &entry_tcp_red;
   2242         } else {
   2243             mem = MMU_WRED_DROP_PROFILE_GREENm;
   2244             entry_p = &entry_tcp_green;
   2245         }
   2246     }
   2247 
   2248     entries[0] = &entry_tcp_green;
   2249     entries[1] = &entry_tcp_yellow;
   2250     entries[2] = &entry_tcp_red;
   2251     entries[3] = &entry_mark_green;
   2252     entries[4] = &entry_mark_yellow;
   2253     entries[5] = &entry_mark_red;
   2254     BCM_IF_ERROR_RETURN
   2255         (soc_profile_mem_get(unit, _bcm_gh_wred_profile[unit],
   2256                              profile_index, 1, entries));
   2257     if (min_thresh != NULL) {
   2258         *min_thresh = soc_mem_field32_get(unit, mem, entry_p, MIN_THDf);
   2259     }
   2260     if (max_thresh != NULL) {
   2261         *max_thresh = soc_mem_field32_get(unit, mem, entry_p, MAX_THDf);
   2262     }
   2263     if (drop_probability != NULL) {
   2264         if (soc_mem_field_valid(unit, mem, MAX_DROP_RATEf)) {
   2265             rate = soc_mem_field32_get(unit, mem, entry_p, MAX_DROP_RATEf);
   2266         } else if (soc_mem_field_valid(unit, mem, MAX_MARK_RATEf)) {
   2267             rate = soc_mem_field32_get(unit, mem, entry_p, MAX_MARK_RATEf);
   2268         }
   2269         *drop_probability = _bcm_gh_drop_prob_to_percent(rate);
   2270     }
   2271 
   2272     if (gain) {
   2273         *gain = soc_mem_field32_get(unit, MMU_WRED_CONFIGm, &qentry, WEIGHTf);
   2274     }
   2275 
   2276     *flags &= ~(BCM_COSQ_DISCARD_CAP_AVERAGE | BCM_COSQ_DISCARD_ENABLE);
   2277     if (soc_mem_field32_get(unit, MMU_WRED_CONFIGm, &qentry, CAP_AVGf)) {
   2278         *flags |= BCM_COSQ_DISCARD_CAP_AVERAGE;
   2279     }
   2280     if (soc_mem_field32_get(unit, MMU_WRED_CONFIGm, &qentry, WRED_ENf)) {
   2281         *flags |= BCM_COSQ_DISCARD_ENABLE;
   2282     }
   2283     if (soc_mem_field32_get(unit, MMU_WRED_CONFIGm, &qentry, ECN_MARKING_ENf)) {
   2284         *flags |= BCM_COSQ_DISCARD_MARK_CONGESTION;
   2285     }
   2286     return BCM_E_NONE;
   2287 }
   2288 
   2289 
   2290 int
   2291 bcm_gh_cosq_discard_set(int unit, uint32 flags)
   2292 {
   2293     bcm_port_t port;
   2294     int numq, i;
   2295     
   2296     if (!soc_feature(unit, soc_feature_discard_ability)) {
   2297         return BCM_E_UNAVAIL;
   2298     }
   2299 
   2300     flags &= ~(BCM_COSQ_DISCARD_NONTCP | BCM_COSQ_DISCARD_COLOR_ALL);
   2301 
   2302     numq = _hu_num_cosq[unit];
   2303     PBMP_PORT_ITER(unit, port) {
   2304         for (i = 0; i < numq; i++) {
   2305             BCM_IF_ERROR_RETURN
   2306                 (_bcm_gh_cosq_wred_set(unit, port, i, flags, 0, 0, 0, 0,
   2307                                         FALSE, BCM_COSQ_DISCARD_PORT));
   2308         }
   2309     }
   2310 
   2311     return BCM_E_NONE;
   2312 }
   2313 
   2314 int
   2315 bcm_gh_cosq_discard_get(int unit, uint32 *flags)
   2316 {
   2317     bcm_port_t port;
   2318 
   2319     if (!soc_feature(unit, soc_feature_discard_ability)) {
   2320         return BCM_E_UNAVAIL;
   2321     }
   2322 
   2323     PBMP_PORT_ITER(unit, port) {
   2324         *flags = 0;
   2325         return _bcm_gh_cosq_wred_get(unit, port, 0, flags, NULL, NULL, NULL,
   2326                                      NULL, BCM_COSQ_DISCARD_PORT);
   2327     }
   2328 
   2329     return BCM_E_NOT_FOUND;
   2330 }
   2331 
   2332 
   2333 /*
   2334  * Function:
   2335  *     bcm_gh_cosq_gport_discard_set
   2336  * Purpose:
   2337  *     Configure port WRED setting
   2338  * Parameters:
   2339  *     unit    - (IN) unit number
   2340  *     port    - (IN) GPORT identifier
   2341  *     cosq    - (IN) COS queue to configure, -1 for all COS queues
   2342  *     discard - (IN) discard settings
   2343  * Returns:
   2344  *     BCM_E_XXX
   2345  */
   2346 
   2347 int
   2348 bcm_gh_cosq_gport_discard_set(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   2349                               bcm_cosq_gport_discard_t *discard)
   2350 {
   2351     int numq, i;
   2352     uint32 min_thresh, max_thresh;
   2353     int cell_size, cell_field_max;
   2354     bcm_port_t local_port;
   2355     bcm_pbmp_t pbmp;
   2356     
   2357     if (!soc_feature(unit, soc_feature_discard_ability)) {
   2358         return BCM_E_UNAVAIL;
   2359     }
   2360 
   2361     if (discard == NULL ||
   2362         discard->gain < 0 || discard->gain > 15 ||
   2363         discard->drop_probability < 0 || discard->drop_probability > 100) {
   2364         return BCM_E_PARAM;
   2365     }
   2366 
   2367     if ((discard->min_thresh < 0) || (discard->max_thresh < 0) ||
   2368                         (discard->min_thresh > discard->max_thresh)) {
   2369         return BCM_E_PARAM;
   2370     }
   2371 
   2372     cell_size = _BCM_GH_BYTES_PER_CELL;
   2373     cell_field_max = GH_CELL_FIELD_MAX;
   2374 
   2375     min_thresh = discard->min_thresh;
   2376     max_thresh = discard->max_thresh;
   2377     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   2378         /* Convert bytes to cells */
   2379         min_thresh += (cell_size - 1);
   2380         min_thresh /= cell_size;
   2381 
   2382         max_thresh += (cell_size - 1);
   2383         max_thresh /= cell_size;
   2384 
   2385         if ((min_thresh > cell_field_max) ||
   2386             (max_thresh > cell_field_max)) {
   2387             return BCM_E_PARAM;
   2388         }
   2389     } else { /* BCM_COSQ_DISCARD_PACKETS */
   2390         if ((min_thresh > GH_CELL_FIELD_MAX) ||
   2391             (max_thresh > GH_CELL_FIELD_MAX)) {
   2392             return BCM_E_PARAM;
   2393         }
   2394     }
   2395 
   2396     if (BCM_GPORT_IS_SET(port)) {
   2397         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &local_port));
   2398         BCM_PBMP_PORT_SET(pbmp, local_port);
   2399     } else {
   2400         if (port == -1) {
   2401             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   2402         } else if (!SOC_PORT_VALID(unit, port) || 
   2403                             (CMIC_PORT(unit) == port)) {
   2404             return BCM_E_PORT;
   2405         } else {
   2406             BCM_PBMP_PORT_SET(pbmp, port);
   2407         }
   2408     }
   2409 
   2410     if (cosq < -1 || cosq >= _hu_num_cosq[unit]) {
   2411         return BCM_E_PARAM;
   2412     }
   2413     
   2414     if (cosq == -1) {
   2415         numq = _hu_num_cosq[unit];
   2416         cosq = 0;
   2417     } else {
   2418         numq = 1;
   2419     }
   2420 
   2421     BCM_PBMP_ITER(pbmp, local_port) {
   2422         for (i = 0; i < numq; i++) {
   2423             BCM_IF_ERROR_RETURN
   2424                 (_bcm_gh_cosq_wred_set(unit, local_port, cosq + i, 
   2425                                         discard->flags,
   2426                                         min_thresh, max_thresh,
   2427                                         discard->drop_probability, 
   2428                                         discard->gain,
   2429                                         FALSE, 0));
   2430         }
   2431     }
   2432     
   2433     return BCM_E_NONE;
   2434 }
   2435 
   2436 int
   2437 bcm_gh_cosq_gport_discard_get(int unit, bcm_gport_t port, bcm_cos_queue_t cosq,
   2438                               bcm_cosq_gport_discard_t *discard)
   2439 {
   2440     uint32 min_thresh, max_thresh;
   2441     bcm_port_t local_port;
   2442     bcm_pbmp_t pbmp;
   2443 
   2444     if (!soc_feature(unit, soc_feature_discard_ability)) {
   2445         return BCM_E_UNAVAIL;
   2446     }
   2447 
   2448     if (discard == NULL) {
   2449         return BCM_E_PARAM;
   2450     }
   2451 
   2452     if (BCM_GPORT_IS_SET(port)) {
   2453         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &local_port));
   2454     } else {
   2455         if (port == -1) {
   2456             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   2457         } else if (!SOC_PORT_VALID(unit, port) || 
   2458                             (CMIC_PORT(unit) == port)) {
   2459             return BCM_E_PORT;
   2460         } else {
   2461             /* coverity[overrun-local] */
   2462             BCM_PBMP_PORT_SET(pbmp, port);
   2463         }
   2464         BCM_PBMP_ITER(pbmp, local_port) {
   2465             break;
   2466         }
   2467     }
   2468 
   2469     if (cosq < -1 || cosq >= _hu_num_cosq[unit]) {
   2470         return BCM_E_PARAM;
   2471     }
   2472     
   2473     BCM_IF_ERROR_RETURN
   2474         (_bcm_gh_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq,
   2475                                &discard->flags, &min_thresh, &max_thresh,
   2476                                &discard->drop_probability, &discard->gain, 0));
   2477 
   2478     if (discard->flags & BCM_COSQ_DISCARD_BYTES) {
   2479         /* Convert number of cells to number of bytes */
   2480         min_thresh *= _BCM_GH_BYTES_PER_CELL;
   2481         max_thresh *= _BCM_GH_BYTES_PER_CELL;
   2482     }
   2483     discard->min_thresh = min_thresh;
   2484     discard->max_thresh = max_thresh;
   2485 
   2486     return BCM_E_NONE;
   2487 }                              
   2488 
   2489 
   2490 int
   2491 bcm_gh_cosq_discard_port_set(int unit, bcm_port_t port,
   2492                              bcm_cos_queue_t cosq,
   2493                              uint32 color,
   2494                              int drop_start,
   2495                              int drop_slope,
   2496                              int average_time)
   2497 {
   2498     bcm_port_t local_port;
   2499     bcm_pbmp_t pbmp;
   2500     int gain;
   2501     uint32 min_thresh, max_thresh, n;
   2502     uint32 rval, bits;
   2503     int numq, i, cosq_start;
   2504 
   2505     if (!soc_feature(unit, soc_feature_discard_ability)) {
   2506         return BCM_E_UNAVAIL;
   2507     }
   2508 
   2509     if (drop_start < 0 || drop_start > 100 ||
   2510         drop_slope < 0 || drop_slope > 90) {
   2511         return BCM_E_PARAM;
   2512     }
   2513 
   2514     if (BCM_GPORT_IS_SET(port)) {
   2515         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &local_port));
   2516         BCM_PBMP_PORT_SET(pbmp, local_port);
   2517     } else {
   2518         if (port == -1) {
   2519             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   2520         } else if (!SOC_PORT_VALID(unit, port) || (CMIC_PORT(unit) == port)) {
   2521             return BCM_E_PORT;
   2522         } else {
   2523             BCM_PBMP_PORT_SET(pbmp, port);
   2524         }
   2525     }
   2526 
   2527     if (cosq < -1 || cosq >= _hu_num_cosq[unit]) {
   2528         return BCM_E_PARAM;
   2529     } else if (cosq == -1) {
   2530         cosq_start = 0;
   2531         numq = _hu_num_cosq[unit];
   2532     } else {
   2533         cosq_start = cosq;
   2534         numq = 1;
   2535     }
   2536 
   2537     /*
   2538      * average queue size is reculated every 2us, the formula is
   2539      * avg_qsize(t + 1) =
   2540      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   2541      * gain = log2(average_time / 2)
   2542      */
   2543     bits = (average_time / _bcm_gh_wred_update_interval[unit]) & 0xffff;
   2544     if (bits != 0) {
   2545         bits |= bits >> 1;
   2546         bits |= bits >> 2;
   2547         bits |= bits >> 4;
   2548         bits |= bits >> 8;
   2549         gain = _shr_popcount(bits) - 1;
   2550     } else {
   2551         gain = 0;
   2552     }
   2553  
   2554     BCM_PBMP_ITER(pbmp, local_port) {
   2555         for (i = cosq_start; i < (cosq_start + numq); i++) { 
   2556             /* Get the start point as a function of the HOL limit */
   2557             SOC_IF_ERROR_RETURN
   2558                 (READ_HOLCOSPKTSETLIMITr(unit, local_port, i, &rval));
   2559             n = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, rval,
   2560                                   PKTSETLIMITf);    
   2561             min_thresh = drop_start * n / 100;
   2562 
   2563             /* Calculate the max threshold. For a given slope (angle in
   2564                  * degrees), determine how many packets are in the range from
   2565                  * 0% drop probability to 100% drop probability. Add that
   2566                  * number to the min_treshold to the the max_threshold.
   2567                  */
   2568             max_thresh = min_thresh + _bcm_gh_angle_to_cells(drop_slope);
   2569             if (max_thresh > GH_CELL_FIELD_MAX) {
   2570                 max_thresh = GH_CELL_FIELD_MAX;
   2571             }
   2572             BCM_IF_ERROR_RETURN
   2573                 (_bcm_gh_cosq_wred_set(unit, local_port, i,
   2574                                        (color | BCM_COSQ_DISCARD_TCP), 
   2575                                        min_thresh, max_thresh, 100,
   2576                                        gain, TRUE, 0)); 
   2577         }
   2578     }
   2579     
   2580     return BCM_E_NONE;
   2581 }
   2582 
   2583 int
   2584 bcm_gh_cosq_discard_port_get(int unit, bcm_port_t port,
   2585                              bcm_cos_queue_t cosq,
   2586                              uint32 color,
   2587                              int *drop_start,
   2588                              int *drop_slope,
   2589                              int *average_time)
   2590 {
   2591     bcm_port_t local_port;
   2592     bcm_pbmp_t pbmp;
   2593     int gain, drop_prob;
   2594     uint32 min_thresh, max_thresh, pkt_limit;
   2595     uint32 rval;
   2596 
   2597     if (!soc_feature(unit, soc_feature_discard_ability)) {
   2598         return BCM_E_UNAVAIL;
   2599     }
   2600 
   2601     if (drop_start == NULL || drop_slope == NULL || average_time == NULL) {
   2602         return BCM_E_PARAM;
   2603     }
   2604 
   2605     if (BCM_GPORT_IS_SET(port)) {
   2606         local_port = port;
   2607     } else {
   2608         if (port == -1) {
   2609             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   2610         } else if (!SOC_PORT_VALID(unit, port) || (CMIC_PORT(unit) == port)) {
   2611             return BCM_E_PORT;
   2612         } else {
   2613             /* coverity[overrun-local] */
   2614             BCM_PBMP_PORT_SET(pbmp, port);
   2615         }
   2616         BCM_PBMP_ITER(pbmp, local_port) {
   2617             break;
   2618         }
   2619     }
   2620 
   2621     if (cosq < -1 || cosq >= _hu_num_cosq[unit]) {
   2622         return BCM_E_PARAM;
   2623     }
   2624 
   2625     color |= BCM_COSQ_DISCARD_TCP;
   2626     BCM_IF_ERROR_RETURN
   2627         (_bcm_gh_cosq_wred_get(unit, local_port, cosq == -1 ? 0 : cosq,
   2628                                &color, &min_thresh, &max_thresh, &drop_prob,
   2629                                &gain, 0));
   2630 
   2631     /*
   2632      * average queue size is reculated every 2(or 1)us, the formula is
   2633      * avg_qsize(t + 1) =
   2634      *     avg_qsize(t) + (cur_qsize - avg_qsize(t)) / (2 ** gain)
   2635      */
   2636     *average_time = (1 << gain) * _bcm_gh_wred_update_interval[unit];
   2637 
   2638     /* Get the total HOL limit first */
   2639     BCM_IF_ERROR_RETURN
   2640         (READ_HOLCOSPKTSETLIMITr(unit, local_port, 
   2641                                     cosq == -1 ? 0 : cosq, &rval));
   2642     pkt_limit = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, rval, PKTSETLIMITf);
   2643     if (min_thresh > pkt_limit) {
   2644         min_thresh = pkt_limit;
   2645     }
   2646 
   2647     if (max_thresh > pkt_limit) {
   2648         max_thresh = pkt_limit;
   2649     }
   2650 
   2651     *drop_start = (min_thresh * 100 + pkt_limit - 1) / pkt_limit;
   2652 
   2653     /* Calculate the slope using the min and max threshold.
   2654      * The angle is calculated knowing drop probability at min
   2655      * threshold is 0% and drop probability at max threshold is 100%.
   2656      */
   2657     *drop_slope = _bcm_gh_cells_to_angle(max_thresh - min_thresh);
   2658     return BCM_E_NONE;
   2659 }
   2660 
   2661 
   2662 #endif /* BCM_GREYHOUND_SUPPORT */
   2663 
   2664 
   2665 STATIC int
   2666 _bcm_hu_cosq_config_set(int unit, int numq)
   2667 {
   2668     int         ncells, nports, xq_per_port, cos;
   2669     int         n, nreset, used_cells;
   2670     int		scells, sreset;
   2671     soc_port_t  port;
   2672     uint32      val, limit_red, limit_yel;
   2673     soc_mem_t   xq_mem;
   2674     int		mmu_flow_percent;
   2675     int		mmu_red_drop_percent;
   2676     int		mmu_yellow_drop_percent;
   2677     int		mmu_static_bytes;
   2678     int		mmu_static_cells;
   2679     int		mmu_static_percent;
   2680     int		mmu_reset_bytes;
   2681     int		mmu_reset_cells = 0;
   2682     int		mmu_overcommit;
   2683     int		mmu_overcommit_stack;
   2684     uint16      dev_id;
   2685     uint8       rev_id;
   2686 
   2687     ncells = soc_mem_index_count(unit, MMU_CBPDATA0m);
   2688         /* These special variables are for Hawkeye only. 
   2689             Those values are retrieved from HAWKEYE MMU setting document*/
   2690 
   2691     nports = NUM_ALL_PORT(unit) + 1;  /* Include cmic port as well */
   2692 
   2693     /* get mmu control config values */
   2694     mmu_flow_percent = soc_property_get(unit,
   2695 					spn_MMU_FLOW_PERCENT,
   2696 					MMU_FLOW_PERCENT);
   2697     mmu_red_drop_percent = soc_property_get(unit,
   2698 					    spn_MMU_RED_DROP_PERCENT,
   2699 					    MMU_RED_DROP_PERCENT);
   2700     mmu_yellow_drop_percent = soc_property_get(unit,
   2701 					       spn_MMU_YELLOW_DROP_PERCENT,
   2702 					       MMU_YELLOW_DROP_PERCENT);
   2703     mmu_static_bytes = soc_property_get(unit,
   2704 					spn_MMU_STATIC_BYTES,
   2705 					MMU_STATIC_BYTES);
   2706     mmu_static_percent = soc_property_get(unit,
   2707 					  spn_MMU_STATIC_PERCENT,
   2708 					  MMU_STATIC_PERCENT);
   2709     mmu_reset_bytes = soc_property_get(unit,
   2710 				       spn_MMU_RESET_BYTES,
   2711 				       MMU_RESET_BYTES);
   2712     mmu_overcommit = soc_property_get(unit,
   2713 				      spn_MMU_OVERCOMMIT,
   2714 				      MMU_OVERCOMMIT);
   2715     mmu_overcommit_stack = soc_property_get(unit,
   2716 					    spn_MMU_OVERCOMMIT_STACK,
   2717 					    MMU_OVERCOMMIT_STACK);
   2718 
   2719     /* sanity check config values */
   2720     if (mmu_flow_percent <= 0 || mmu_flow_percent > 100) {
   2721 	mmu_flow_percent = 100;
   2722     }
   2723     if (mmu_red_drop_percent <= 0 || mmu_red_drop_percent > 100) {
   2724 	mmu_red_drop_percent = 100;
   2725     }
   2726     if (mmu_yellow_drop_percent <= 0 || mmu_yellow_drop_percent > 100) {
   2727 	mmu_yellow_drop_percent = 100;
   2728     }
   2729     if (mmu_static_percent <= 0 || mmu_static_percent > 100) {
   2730 	mmu_static_percent = MMU_STATIC_PERCENT;
   2731     }
   2732     if (mmu_overcommit <= 0) {
   2733 	mmu_overcommit = 1;
   2734     }
   2735     if (mmu_overcommit_stack <= 0) {
   2736 	mmu_overcommit_stack = mmu_overcommit;
   2737     }
   2738     mmu_static_cells = (mmu_static_bytes + MMU_CELL_SIZE - 1) / MMU_CELL_SIZE;
   2739     mmu_reset_cells = (mmu_reset_bytes + MMU_CELL_SIZE - 1) / MMU_CELL_SIZE;
   2740 
   2741     /* calculate static limits first */
   2742     if (mmu_static_cells > 0) {
   2743 	scells = mmu_static_cells;
   2744 	sreset = scells;		/* 100% */
   2745     } else {
   2746 	scells = (ncells / nports / numq) * mmu_static_percent / 100;
   2747 	sreset = scells * 75 / 100;	/* 75% */
   2748     }
   2749     
   2750     soc_cm_get_id(unit, &dev_id, &rev_id);
   2751     if (dev_id == BCM56147_DEVICE_ID) {
   2752         scells += 4;
   2753         sreset = scells;
   2754     }
   2755 
   2756     used_cells = scells * numq * nports;
   2757 
   2758     /* remaining cells are dynamic */
   2759     n = ncells - used_cells;
   2760     if (n <= 0) {
   2761 	n = 0;
   2762     }
   2763     nreset = n - mmu_reset_cells;
   2764     if (nreset < (n * MMU_RESET_MIN_PERCENT / 100)) {
   2765 	nreset = n * MMU_RESET_MIN_PERCENT / 100;
   2766     }
   2767     if (nreset <= 0) {
   2768 	nreset = 1;
   2769     }
   2770 
   2771     /* device wide dynamic limits */
   2772 
   2773     SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLSETLIMITr(unit, &val));
   2774     soc_reg_field_set(unit, TOTALDYNCELLSETLIMITr,
   2775                       &val, TOTALDYNCELLSETLIMITf, n);
   2776     SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLSETLIMITr(unit, val));
   2777     SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLRESETLIMITr(unit, &val));
   2778     soc_reg_field_set(unit, TOTALDYNCELLRESETLIMITr,
   2779                       &val, TOTALDYNCELLRESETLIMITf, nreset);
   2780     SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLRESETLIMITr(unit, val));
   2781  
   2782     /* per-port dynamic limits */
   2783     PBMP_ALL_ITER(unit, port) {
   2784 
   2785          if (dev_id == BCM56147_DEVICE_ID) {
   2786          /* For Hurricane(56147 variant), the value of field DYNCELLLIMIT 
   2787          * of register DYNCELLLIMIT is 8448 and DYNCELLRESETLIMIT is 8424, 
   2788          * refer hurricane_mmu_init for detailed computation */
   2789         
   2790             SOC_IF_ERROR_RETURN(READ_DYNCELLLIMITr(unit, port, &val));
   2791             if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLLIMITf)) {
   2792                 soc_reg_field_set(unit, DYNCELLLIMITr, &val,
   2793                                   DYNCELLLIMITf, 8448);
   2794             }
   2795 
   2796             if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLRESETLIMITf)) {
   2797                 soc_reg_field_set(unit, DYNCELLLIMITr, &val,
   2798                                   DYNCELLRESETLIMITf, 8424);
   2799             }
   2800         }
   2801 	else {
   2802         /* For other variants use 6040 and 6016 */
   2803             SOC_IF_ERROR_RETURN(READ_DYNCELLLIMITr(unit, port, &val));
   2804             if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLLIMITf)) {
   2805                 soc_reg_field_set(unit, DYNCELLLIMITr, &val,
   2806                                   DYNCELLLIMITf, 6040);
   2807             }
   2808 
   2809             if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLRESETLIMITf)) {
   2810                 soc_reg_field_set(unit, DYNCELLLIMITr, &val,
   2811                                   DYNCELLRESETLIMITf, 6016);
   2812             }
   2813 	}
   2814 
   2815 
   2816         SOC_IF_ERROR_RETURN(WRITE_DYNCELLLIMITr(unit, port, val));
   2817 
   2818 
   2819         /*
   2820          * Number of transactions allocated to each port,
   2821          * shared between that port's active cosqs.
   2822          */
   2823         SOC_IF_ERROR_RETURN(soc_hu_xq_mem(unit, port, &xq_mem));
   2824         xq_per_port = soc_mem_index_count(unit, xq_mem);
   2825 
   2826 
   2827         /*
   2828          * Divide weighted per-port packet limits into each cos.
   2829          * Initialize all COSQs, even the inactive ones.
   2830          */
   2831         for (cos = 0; cos < NUM_COS(unit); cos++) {
   2832 	    /* set per-port static limits (calculated earlier) */
   2833             SOC_IF_ERROR_RETURN
   2834                 (READ_LWMCOSCELLSETLIMITr(unit, port, cos, &val));
   2835             if (soc_reg_field_valid(unit, LWMCOSCELLSETLIMITr,
   2836                                     CELLSETLIMITf)) {
   2837                 soc_reg_field_set(unit, LWMCOSCELLSETLIMITr,
   2838                                   &val, CELLSETLIMITf,
   2839 				  cos < numq ? scells : 0);
   2840             }
   2841 
   2842             if (soc_reg_field_valid(unit, LWMCOSCELLSETLIMITr,
   2843                                     CELLRESETLIMITf)) {
   2844                 soc_reg_field_set(unit, LWMCOSCELLSETLIMITr,
   2845                                   &val, CELLRESETLIMITf,
   2846 				  cos < numq ? sreset : 0);
   2847             }
   2848             SOC_IF_ERROR_RETURN
   2849                 (WRITE_LWMCOSCELLSETLIMITr(unit, port, cos, val));
   2850 
   2851 
   2852 	    /* set red and yellow drop limits */
   2853 	    /* set as a percentage of the green drop (HOL) limit */
   2854 
   2855             SOC_IF_ERROR_RETURN
   2856 		(READ_HOLCOSPKTSETLIMITr(unit, port, cos, &val));
   2857             n = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, val,
   2858                                     PKTSETLIMITf);
   2859 
   2860             /* Make sure numq will work with the cosq weighting. */
   2861             if ((cos < numq) && (n == 4)) {
   2862                 /*
   2863                  * This means that this COSQ has been
   2864                  * disabled due to XQ weighting, but
   2865                  * has been selected as active. Config error.
   2866                  */
   2867                 return BCM_E_PARAM;
   2868             }
   2869 
   2870 	    /* per-queue packet red and yellow drop */
   2871             if (cos < numq) {
   2872                 limit_red = n * mmu_red_drop_percent / 100;
   2873                 limit_yel = n * mmu_yellow_drop_percent / 100;
   2874             } else {
   2875                 limit_red = xq_per_port - 1; /* Max limit (disabled) */
   2876                 limit_yel = xq_per_port - 1; /* Max limit (disabled) */
   2877             }
   2878 
   2879  /* Granularity limitation */
   2880                 limit_red /= BCM_HU_CNG_PKT_LIMIT_GRANULARITY;
   2881                 limit_yel /= BCM_HU_CNG_PKT_LIMIT_GRANULARITY;
   2882             
   2883 
   2884             val = 0;
   2885             soc_reg_field_set(unit, CNGCOSPKTLIMIT0r, &val,
   2886                               CNGPKTSETLIMIT0f, limit_red);
   2887 	    SOC_IF_ERROR_RETURN(WRITE_CNGCOSPKTLIMIT0r(unit, port, cos, val));
   2888 
   2889             val = 0;
   2890             soc_reg_field_set(unit, CNGCOSPKTLIMIT1r, &val,
   2891                               CNGPKTSETLIMIT1f, limit_yel);
   2892 	    SOC_IF_ERROR_RETURN(WRITE_CNGCOSPKTLIMIT1r(unit, port, cos, val));
   2893 
   2894 
   2895         }
   2896 
   2897 
   2898         if (dev_id == BCM56147_DEVICE_ID) {
   2899             SOC_IF_ERROR_RETURN(READ_IBPCELLSETLIMITr(unit, port, &val));
   2900 
   2901             /* set cell limit = 36 as recommended by design team */
   2902             soc_reg_field_set(unit, IBPCELLSETLIMITr, &val,
   2903                               CELLSETLIMITf, 36);
   2904             SOC_IF_ERROR_RETURN(WRITE_IBPCELLSETLIMITr(unit, port, val));
   2905 
   2906             SOC_IF_ERROR_RETURN(READ_IBPPKTSETLIMITr(unit, port, &val));
   2907             /* set pkt set limit = 33 as recommended by design team */  
   2908             soc_reg_field_set(unit, IBPPKTSETLIMITr, &val,
   2909                               PKTSETLIMITf, 33);
   2910             soc_reg_field_set(unit, IBPPKTSETLIMITr, &val,
   2911                               RESETLIMITSELf, 0);	
   2912             SOC_IF_ERROR_RETURN(WRITE_IBPPKTSETLIMITr(unit, port, val));
   2913         }
   2914         else {
   2915             SOC_IF_ERROR_RETURN(READ_IBPCELLSETLIMITr(unit, port, &val));
   2916 
   2917             /* set cell limit = 80 (9728/128 +4); 9728 is max pkt size and 128 is cell size ; 
   2918              * as recommended by design team */
   2919             soc_reg_field_set(unit, IBPCELLSETLIMITr, &val,
   2920                               CELLSETLIMITf, 80);
   2921             SOC_IF_ERROR_RETURN(WRITE_IBPCELLSETLIMITr(unit, port, val));
   2922 
   2923             SOC_IF_ERROR_RETURN(READ_IBPPKTSETLIMITr(unit, port, &val));
   2924             /* set pkt set limit = 12 as recommended by design team */  
   2925             soc_reg_field_set(unit, IBPPKTSETLIMITr, &val,
   2926                               PKTSETLIMITf, 12);
   2927             soc_reg_field_set(unit, IBPPKTSETLIMITr, &val,
   2928                               RESETLIMITSELf, 0);	
   2929             SOC_IF_ERROR_RETURN(WRITE_IBPPKTSETLIMITr(unit, port, val));
   2930         }
   2931 
   2932         SOC_IF_ERROR_RETURN(READ_IBPDISCARDSETLIMITr(unit, port, &val));
   2933         soc_reg_field_set(unit, IBPDISCARDSETLIMITr, &val,
   2934                           DISCARDSETLIMITf, ncells-1);
   2935         SOC_IF_ERROR_RETURN(WRITE_IBPDISCARDSETLIMITr(unit, port, val));
   2936 
   2937     }
   2938 
   2939     /* Overall MMU controls */
   2940     SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &val));
   2941     soc_reg_field_set(unit, MISCCONFIGr, &val, DYNAMIC_MEMORY_ENf, 1);
   2942 
   2943     /* set skidmarker to 3 */
   2944     soc_reg_field_set(unit, MISCCONFIGr, &val, SKIDMARKERf, 3);
   2945 
   2946 
   2947     if (soc_reg_field_valid(unit, MISCCONFIGr, HOL_CELL_SOP_DROP_ENf)) {
   2948         soc_reg_field_set(unit, MISCCONFIGr, &val, HOL_CELL_SOP_DROP_ENf, 1);
   2949     }
   2950 
   2951 
   2952     SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, val));
   2953 
   2954     return BCM_E_NONE;
   2955 }
   2956 
   2957 /*
   2958  * Function:
   2959  *      bcm_cosq_mapping_set
   2960  * Purpose:
   2961  *      Set which cosq a given priority should fall into
   2962  * Parameters:
   2963  *      unit - StrataSwitch unit number.
   2964  *      priority - Priority value to map
   2965  *      cosq - COS queue to map to
   2966  * Returns:
   2967  *      BCM_E_XXX
   2968  */
   2969 
   2970 int
   2971 bcm_hu_cosq_mapping_set(int unit, bcm_port_t port,
   2972                         bcm_cos_t priority, bcm_cos_queue_t cosq)
   2973 {
   2974     uint32 val, old_index, new_index;
   2975     int i;
   2976     port_cos_map_entry_t cos_map_array[HU_COS_MAP_ENTRIES_PER_SET], *entry_p;
   2977     void *entries[HU_COS_MAP_ENTRIES_PER_SET];
   2978     bcm_pbmp_t ports;
   2979     bcm_port_t local_port;
   2980 
   2981     if (priority < 0 || priority >= 16) {
   2982         return (BCM_E_PARAM);
   2983     }
   2984 
   2985     if (cosq < 0 || cosq >= _hu_num_cosq[unit]) {
   2986         return (BCM_E_PARAM);
   2987     }
   2988 
   2989     if (port == -1) {	/* all ports */
   2990         BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
   2991     } else {
   2992         if (BCM_GPORT_IS_SET(port)) {
   2993             BCM_IF_ERROR_RETURN(
   2994                 bcm_esw_port_local_get(unit, port, &local_port)); 
   2995         } else {
   2996             local_port = port;
   2997         }
   2998 
   2999         if (!SOC_PORT_VALID(unit, local_port) || !IS_ALL_PORT(unit, local_port)) {
   3000             return BCM_E_PORT;
   3001         }
   3002         BCM_PBMP_CLEAR(ports);
   3003         BCM_PBMP_PORT_ADD(ports, local_port);
   3004     }
   3005 
   3006     PBMP_ITER(ports, local_port) {
   3007         SOC_IF_ERROR_RETURN(READ_COS_MAP_SELr(unit, local_port, &val));
   3008         old_index = soc_reg_field_get(unit, COS_MAP_SELr, val, SELECTf);
   3009         old_index *= HU_COS_MAP_ENTRIES_PER_SET;
   3010 
   3011         /* get current mapping profile values */
   3012         for (i = 0; i < HU_COS_MAP_ENTRIES_PER_SET; i++) {
   3013             entry_p = SOC_PROFILE_MEM_ENTRY(unit, _hu_cos_map_profile[unit],
   3014                                             port_cos_map_entry_t *, (old_index + i));
   3015             memcpy(&cos_map_array[i], entry_p, sizeof(*entry_p));
   3016             entries[i] = (void *) &cos_map_array[i];
   3017         }
   3018         soc_mem_field32_set(unit, PORT_COS_MAPm,
   3019                             &cos_map_array[priority], COSf, cosq);
   3020         SOC_IF_ERROR_RETURN
   3021             (soc_profile_mem_add(unit, _hu_cos_map_profile[unit],
   3022                                  (void *) &entries,
   3023                                  HU_COS_MAP_ENTRIES_PER_SET, &new_index));
   3024         SOC_IF_ERROR_RETURN
   3025             (soc_reg_field32_modify(unit, COS_MAP_SELr, local_port, 
   3026                                     SELECTf,
   3027                                     new_index / HU_COS_MAP_ENTRIES_PER_SET));
   3028         SOC_IF_ERROR_RETURN
   3029             (soc_profile_mem_delete(unit, _hu_cos_map_profile[unit], old_index));
   3030 
   3031 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   3032         if (IS_HG_PORT(unit, local_port) || local_port == CMIC_PORT(unit)) {
   3033             SOC_IF_ERROR_RETURN
   3034                 (soc_profile_mem_add(unit, _hu_cos_map_profile[unit],
   3035                                      (void *) &entries,
   3036                                      HU_COS_MAP_ENTRIES_PER_SET, &new_index));
   3037             SOC_IF_ERROR_RETURN
   3038                 (soc_reg_field32_modify(unit, ICOS_MAP_SELr, local_port, 
   3039                                         SELECTf,
   3040                                         new_index / HU_COS_MAP_ENTRIES_PER_SET));
   3041             SOC_IF_ERROR_RETURN
   3042                 (soc_profile_mem_delete(unit, _hu_cos_map_profile[unit], old_index));
   3043         }
   3044 #endif
   3045     }
   3046     return BCM_E_NONE;
   3047 }
   3048 
   3049 /*
   3050  * Function:
   3051  *      bcm_cosq_mapping_get
   3052  * Purpose:
   3053  *      Determine which COS queue a given priority currently maps to.
   3054  * Parameters:
   3055  *      unit - StrataSwitch unit number.
   3056  *      priority - Priority value
   3057  *      cosq - (Output) COS queue number
   3058  * Returns:
   3059  *      BCM_E_XXX
   3060  */
   3061 
   3062 int
   3063 bcm_hu_cosq_mapping_get(int unit, bcm_port_t port,
   3064                         bcm_cos_t priority, bcm_cos_queue_t *cosq)
   3065 {
   3066     uint32 val;
   3067     int index;
   3068     port_cos_map_entry_t *entry_p;
   3069     bcm_port_t local_port;
   3070 
   3071     if (priority < 0 || priority >= 16) {
   3072         return (BCM_E_PARAM);
   3073     }
   3074 
   3075     if (port == -1) {
   3076         local_port = REG_PORT_ANY;
   3077     } else {
   3078         if (BCM_GPORT_IS_SET(port)) {
   3079             BCM_IF_ERROR_RETURN(
   3080                 bcm_esw_port_local_get(unit, port, &local_port)); 
   3081         } else {
   3082             local_port = port;
   3083         }
   3084 
   3085         if (!SOC_PORT_VALID(unit, local_port) || !IS_ALL_PORT(unit, local_port)) {
   3086             return BCM_E_PORT;
   3087         }
   3088     }
   3089 
   3090     SOC_IF_ERROR_RETURN(READ_COS_MAP_SELr(unit, local_port, &val));
   3091     index = soc_reg_field_get(unit, COS_MAP_SELr, val, SELECTf);
   3092     index *= HU_COS_MAP_ENTRIES_PER_SET;
   3093 
   3094     entry_p = SOC_PROFILE_MEM_ENTRY(unit, _hu_cos_map_profile[unit],
   3095                                     port_cos_map_entry_t *, 
   3096                                     (index + priority));
   3097     *cosq = soc_mem_field32_get(unit, PORT_COS_MAPm, entry_p, COSf);
   3098     return BCM_E_NONE;
   3099 }
   3100 
   3101 STATIC int
   3102 _bcm_hu_cosq_gport_bandwidth_port_resolve(int unit, bcm_gport_t gport,
   3103                                           bcm_cos_queue_t cosq,
   3104                                           bcm_port_t *local_port,
   3105                                           bcm_cos_queue_t *cosq_start,
   3106                                           bcm_cos_queue_t *cosq_end)
   3107 {
   3108     bcm_module_t modid;
   3109     bcm_trunk_t trunk_id;	
   3110     int is_local;
   3111 
   3112     if (BCM_GPORT_IS_SET(gport)) {
   3113         BCM_IF_ERROR_RETURN
   3114             (_bcm_hu_cosq_resolve_mod_port(unit, gport, &modid,
   3115                                            local_port, &trunk_id, &is_local));
   3116     } else {
   3117         *local_port = gport;
   3118         if (!SOC_PORT_VALID(unit, gport)) {
   3119             return BCM_E_PORT;
   3120         }
   3121     }
   3122 
   3123     if (cosq < -1) {
   3124         return BCM_E_PARAM;
   3125     }
   3126 
   3127     /* hurricane does not have vlan queues and S1 scheduler*/
   3128     if (cosq >= _hu_num_cosq[unit]) {
   3129         return BCM_E_PARAM;
   3130     } else if (cosq < 0) {
   3131         *cosq_start = 0;
   3132         *cosq_end = _hu_num_cosq[unit] - 1;
   3133     } else {
   3134         *cosq_start = *cosq_end = cosq;
   3135     }
   3136 
   3137     return BCM_E_NONE;
   3138 }
   3139 
   3140 
   3141 /*
   3142  * Function:
   3143  *      bcm_hu_cosq_gport_bandwidth_burst_get
   3144  * Purpose:
   3145  *
   3146  * Parameters:
   3147  *      unit - (IN) Unit number.
   3148  *      gport - (IN) GPORT ID.
   3149  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   3150  *      kbits_burst - (OUT) maximum burst, kbits.
   3151  * Returns:
   3152  *      BCM_E_XXX
   3153  */
   3154 int
   3155 bcm_hu_cosq_gport_bandwidth_burst_get(int unit, bcm_gport_t gport,
   3156                                       bcm_cos_queue_t cosq,
   3157                                       uint32 *kbits_burst)
   3158 {
   3159     bcm_port_t local_port, port;
   3160     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
   3161     uint32 kbits_sec_min, kbits_sec_max, flags;    /* Dummy variables */
   3162 
   3163     if (gport < 0) {
   3164         port = SOC_PORT_MIN(unit,all);
   3165 
   3166         BCM_IF_ERROR_RETURN
   3167             (_bcm_hu_cosq_gport_bandwidth_port_resolve(unit, port, cosq,
   3168                                                        &local_port,
   3169                                                        &cosq_start, &cosq_end));
   3170     } else {
   3171         BCM_IF_ERROR_RETURN
   3172             (_bcm_hu_cosq_gport_bandwidth_port_resolve(unit, gport, cosq,
   3173                                                        &local_port,
   3174                                                        &cosq_start, &cosq_end));
   3175     }
   3176 
   3177     kbits_sec_min = kbits_sec_max = flags = 0;
   3178 
   3179     BCM_IF_ERROR_RETURN
   3180         (bcm_hu_cosq_port_bandwidth_get(unit, local_port, cosq_start,
   3181                                         &kbits_sec_min, &kbits_sec_max,
   3182                                         kbits_burst, &flags));
   3183     return BCM_E_NONE;
   3184 }
   3185 
   3186 /*  
   3187  * Function:
   3188  *      bcm_hu_cosq_gport_bandwidth_burst_set
   3189  * Purpose:
   3190  *       
   3191  * Parameters:
   3192  *      unit - (IN) Unit number.
   3193  *      gport - (IN) GPORT ID.
   3194  *      cosq - (IN) COS queue to configure, -1 for all COS queues.
   3195  *      kbits_burst - (IN) maximum burst, kbits.
   3196  * Returns:
   3197  *      BCM_E_XXX 
   3198  */ 
   3199 int
   3200 bcm_hu_cosq_gport_bandwidth_burst_set(int unit, bcm_gport_t gport,
   3201                                       bcm_cos_queue_t cosq,
   3202                                       uint32 kbits_burst)
   3203 {
   3204     bcm_port_t local_port, port;
   3205     int i;
   3206     bcm_cos_queue_t cosq_start = 0, cosq_end = 0;
   3207     uint32 kbits_sec_min, kbits_sec_max, flags;
   3208     uint32 kbits_sec_burst; /* Dummy variable */
   3209 
   3210     if (gport < 0) {
   3211         PBMP_ALL_ITER(unit, port) {
   3212             BCM_IF_ERROR_RETURN
   3213                 (_bcm_hu_cosq_gport_bandwidth_port_resolve(unit, port, cosq,
   3214                                                            &local_port,
   3215                                                            &cosq_start, &cosq_end));
   3216             for (i = cosq_start; i <= cosq_end; i++) {
   3217                 BCM_IF_ERROR_RETURN
   3218                     (bcm_hu_cosq_port_bandwidth_get(unit, local_port, i,
   3219                                                     &kbits_sec_min, &kbits_sec_max,
   3220                                                     &kbits_sec_burst, &flags));
   3221                 BCM_IF_ERROR_RETURN
   3222                     (bcm_hu_cosq_port_bandwidth_set(unit, local_port, i,
   3223                                                     kbits_sec_min,
   3224                                                     kbits_sec_max,
   3225                                                     kbits_burst,
   3226                                                     flags));
   3227             }
   3228         }
   3229         return BCM_E_NONE;
   3230     }
   3231 
   3232     BCM_IF_ERROR_RETURN
   3233         (_bcm_hu_cosq_gport_bandwidth_port_resolve(unit, gport, cosq,
   3234                                                    &local_port,
   3235                                                    &cosq_start, &cosq_end));
   3236 
   3237     for (i = cosq_start; i <= cosq_end; i++) {
   3238         BCM_IF_ERROR_RETURN
   3239             (bcm_hu_cosq_port_bandwidth_get(unit, local_port, cosq_start,
   3240                                             &kbits_sec_min, &kbits_sec_max,
   3241                                             &kbits_sec_burst, &flags));
   3242         BCM_IF_ERROR_RETURN
   3243             (bcm_hu_cosq_port_bandwidth_set(unit, local_port, i,
   3244                                             kbits_sec_min,
   3245                                             kbits_sec_max,
   3246                                             kbits_burst,
   3247                                             flags));
   3248     }
   3249     return BCM_E_NONE;
   3250 }
   3251 
   3252 /*
   3253  * Function:
   3254  *      bcm_hu_cosq_sched_weight_max_get
   3255  * Purpose:
   3256  *      Retrieve maximum weights for given COS policy.
   3257  * Parameters:
   3258  *      unit - StrataSwitch unit number.
   3259  *      mode - Scheduling mode, one of BCM_COSQ_xxx
   3260  *      weight_max - (output) Maximum weight for COS queue.
   3261  *              For DRR mode Weight is specified in Kbytes
   3262  *              0 if mode is BCM_COSQ_STRICT.
   3263  *              1 if mode is BCM_COSQ_ROUND_ROBIN.
   3264  *              -1 if not applicable to mode.
   3265  * Returns:
   3266  *      BCM_E_XXX
   3267  */
   3268 
   3269 int
   3270 bcm_hu_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   3271 {
   3272     switch (mode) {
   3273     case BCM_COSQ_STRICT:
   3274         *weight_max = BCM_COSQ_WEIGHT_STRICT;
   3275         break;
   3276     case BCM_COSQ_ROUND_ROBIN:
   3277         *weight_max = BCM_COSQ_WEIGHT_MIN;
   3278         break;
   3279     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   3280         *weight_max = HU_WRR_WEIGHT_MAX;
   3281         break;
   3282     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   3283         /*max weight in kb will be
   3284         max weight * max value of MTU quanta sel */
   3285         *weight_max = HU_DRR_WEIGHT_MAX * MTU_HU_Quanta[BCM_HU_MTU_QUANTA_ID_COUNT-1]; 
   3286         break;
   3287     default:
   3288         *weight_max = BCM_COSQ_WEIGHT_UNLIMITED;
   3289         return BCM_E_PARAM;
   3290     }
   3291 
   3292     return BCM_E_NONE;
   3293 }
   3294 
   3295 #ifndef BCM_SW_STATE_DUMP_DISABLE
   3296 /*
   3297  * Function:
   3298  *     bcm_hu_cosq_sw_dump
   3299  * Purpose:
   3300  *     Displays COS Queue information maintained by software.
   3301  * Parameters:
   3302  *     unit - Device unit number
   3303  * Returns:
   3304  *     None
   3305  */
   3306 void
   3307 bcm_hu_cosq_sw_dump(int unit)
   3308 {
   3309     int  i;
   3310 
   3311     LOG_CLI((BSL_META_U(unit,
   3312                         "\nSW Information COSQ - Unit %d\n"), unit));
   3313 
   3314     /* Number COSQ */
   3315     LOG_CLI((BSL_META_U(unit,
   3316                         "    Number: %d\n"), _hu_num_cosq[unit]));
   3317 
   3318     /* COSQ Map profile */
   3319     /* Display those entries with reference count > 0 */
   3320     LOG_CLI((BSL_META_U(unit,
   3321                         "    COSQ Map Profile:\n")));
   3322     if (_hu_cos_map_profile[unit] != NULL) {
   3323         int     num_entries;
   3324         int     ref_count;
   3325         int     entries_per_set;
   3326         uint32  index;
   3327         port_cos_map_entry_t *entry_p;
   3328         uint32  cosq, hg_cosq;
   3329 
   3330         num_entries = soc_mem_index_count
   3331             (unit, _hu_cos_map_profile[unit]->tables[0].mem);
   3332         LOG_CLI((BSL_META_U(unit,
   3333                             "        Number of entries: %d\n"), num_entries));
   3334         LOG_CLI((BSL_META_U(unit,
   3335                             "        Index RefCount EntriesPerSet - "
   3336                  "COS HG_COS\n")));
   3337 
   3338         for (index = 0; index < num_entries;
   3339              index += HU_COS_MAP_ENTRIES_PER_SET) {
   3340             if (SOC_FAILURE
   3341                 (soc_profile_mem_ref_count_get(unit,
   3342                                                _hu_cos_map_profile[unit],
   3343                                                index, &ref_count))) {
   3344                 break;
   3345             }
   3346 
   3347             if (ref_count <= 0) {
   3348                 continue;
   3349             }
   3350 
   3351             for (i = 0; i < HU_COS_MAP_ENTRIES_PER_SET; i++) {
   3352                 entries_per_set =
   3353                     _hu_cos_map_profile[unit]->tables[0].entries[index+i].entries_per_set;
   3354                 LOG_CLI((BSL_META_U(unit,
   3355                                     "       %5d %8d %13d    "),
   3356                          index + i, ref_count, entries_per_set));
   3357 
   3358                 entry_p = SOC_PROFILE_MEM_ENTRY(unit,
   3359                                                 _hu_cos_map_profile[unit],
   3360                                                 port_cos_map_entry_t *,
   3361                                                 index + i);
   3362                 cosq = soc_mem_field32_get(unit,
   3363                                            PORT_COS_MAPm,
   3364                                            entry_p,
   3365                                            COSf);
   3366                 LOG_CLI((BSL_META_U(unit,
   3367                                     "%2d "), cosq));
   3368                 if (soc_mem_field_valid(unit, PORT_COS_MAPm, HG_COSf)) {
   3369                     hg_cosq = soc_mem_field32_get(unit, PORT_COS_MAPm,
   3370                                                   entry_p,
   3371                                                   HG_COSf);
   3372                     LOG_CLI((BSL_META_U(unit,
   3373                                         "   %2d"), hg_cosq));
   3374                 }
   3375                 LOG_CLI((BSL_META_U(unit,
   3376                                     "\n")));
   3377             }
   3378         }
   3379     }
   3380 
   3381     return;
   3382 }
   3383 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   3384 
   3385 #if defined(BCM_GREYHOUND_SUPPORT)
   3386 int
   3387 _bcm_gh_cosq_pfc_class_resolve(bcm_switch_control_t sctype, int *class)
   3388 {
   3389     switch (sctype) {
   3390     case bcmSwitchPFCClass7Queue:
   3391         *class = 7;
   3392         break;
   3393     case bcmSwitchPFCClass6Queue:
   3394         *class = 6;
   3395         break;
   3396     case bcmSwitchPFCClass5Queue:
   3397         *class = 5;
   3398         break;
   3399     case bcmSwitchPFCClass4Queue:
   3400         *class = 4;
   3401         break;
   3402     case bcmSwitchPFCClass3Queue:
   3403         *class = 3;
   3404         break;
   3405     case bcmSwitchPFCClass2Queue:
   3406         *class = 2;
   3407         break;
   3408     case bcmSwitchPFCClass1Queue:
   3409         *class = 1;
   3410         break;
   3411     case bcmSwitchPFCClass0Queue:
   3412         *class = 0;
   3413         break;
   3414     default:
   3415         return BCM_E_UNAVAIL;
   3416     }
   3417 
   3418     return BCM_E_NONE;
   3419 }
   3420 
   3421 int
   3422 bcm_gh_cosq_port_pfc_op(int unit, bcm_port_t port,
   3423                         bcm_switch_control_t sctype, _bcm_cosq_op_t op,
   3424                         bcm_cos_queue_t cosq)
   3425 {
   3426     int class;
   3427     uint32 class_bmp;
   3428     int i;
   3429 
   3430     BCM_IF_ERROR_RETURN(_bcm_gh_cosq_pfc_class_resolve(sctype, &class));
   3431     
   3432     if (op == _BCM_COSQ_OP_CLEAR) {
   3433         for (i = 0; i < 8; i++) {
   3434             BCM_IF_ERROR_RETURN(READ_PRI2COS_PFCr(unit, port, 
   3435                                 i, &class_bmp));
   3436             class_bmp &= ~(1 << class);
   3437             BCM_IF_ERROR_RETURN(WRITE_PRI2COS_PFCr(unit, port, 
   3438                                 i, class_bmp));
   3439         }
   3440     } else if (op == _BCM_COSQ_OP_ADD) {
   3441         if ((cosq < 0) || cosq > NUM_COS(unit)) {
   3442             return BCM_E_PARAM;
   3443         }
   3444 
   3445         BCM_IF_ERROR_RETURN(READ_PRI2COS_PFCr(unit, port, cosq, &class_bmp));
   3446         class_bmp |= (1 << class);
   3447         BCM_IF_ERROR_RETURN(WRITE_PRI2COS_PFCr(unit, port, cosq, class_bmp));
   3448     } else {
   3449         return BCM_E_PARAM;
   3450     }
   3451 
   3452     return BCM_E_NONE;
   3453 }
   3454 
   3455 int
   3456 bcm_gh_cosq_port_pfc_get(int unit, bcm_port_t port,
   3457                         bcm_switch_control_t sctype, 
   3458                         bcm_cos_queue_t *cosq)
   3459 {
   3460     int class;
   3461     uint32 class_bmp;
   3462     int i;
   3463 
   3464     BCM_IF_ERROR_RETURN(_bcm_gh_cosq_pfc_class_resolve(sctype, &class));
   3465     
   3466     for (i = 0; i < 8; i++) {
   3467         BCM_IF_ERROR_RETURN(READ_PRI2COS_PFCr(unit, port, i, &class_bmp));
   3468         if (class_bmp & (1 << class)) {
   3469             break;
   3470         }
   3471     }
   3472 
   3473     if (i >= 8) {
   3474         return BCM_E_NOT_FOUND;
   3475     }
   3476 
   3477     *cosq = i;
   3478 
   3479     return BCM_E_NONE;
   3480 }
   3481 #endif /* BCM_GREYHOUND_SUPPORT */
   3482 
   3483 int
   3484 bcm_hr3_cosq_drop_status_enable_set(int unit, bcm_port_t port, int enable)
   3485 {
   3486     uint32 rval;
   3487     bcm_port_t local_port;
   3488 
   3489     COMPILER_REFERENCE(port);
   3490     PBMP_E_ITER (unit, local_port) {
   3491         BCM_IF_ERROR_RETURN(READ_E2ECC_PORT_CONFIGr(unit, local_port, &rval));
   3492         soc_reg_field_set(unit, E2ECC_PORT_CONFIGr, &rval, 
   3493                           COS_CELL_ENf,  enable ? 0xFF : 0x0);
   3494         soc_reg_field_set(unit, E2ECC_PORT_CONFIGr, &rval, 
   3495                           COS_PKT_ENf, enable ? 0xFF : 0x0);
   3496         BCM_IF_ERROR_RETURN(WRITE_E2ECC_PORT_CONFIGr(unit, local_port, rval));
   3497     }
   3498 
   3499     BCM_IF_ERROR_RETURN(READ_E2ECC_MODEr(unit, &rval));
   3500     soc_reg_field_set(unit, E2ECC_MODEr, &rval, ENf,
   3501                       enable ? 1 : 0);
   3502     BCM_IF_ERROR_RETURN(WRITE_E2ECC_MODEr(unit, rval));
   3503 
   3504     PBMP_E_ITER (unit, local_port) {
   3505         BCM_IF_ERROR_RETURN(READ_COLOR_DROP_ENr(unit, local_port, &rval));
   3506         soc_reg_field_set(unit, COLOR_DROP_ENr, &rval, 
   3507                           COLOR_DROP_ENf,  enable ? 0x0 : 0xff);
   3508         BCM_IF_ERROR_RETURN(WRITE_COLOR_DROP_ENr(unit, local_port, rval));
   3509     }
   3510 
   3511     return BCM_E_NONE;
   3512 }
   3513 
   3514 #else /* BCM_HURRICANE_SUPPORT */
   3515 int _hu_cosq_not_empty;
   3516 #endif  /* BCM_HURRICANE_SUPPORT */
   3517 
   3518