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


      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  * Based on Draco/Draco 1.5 code
     10  */
     11 
     12 #include <sal/core/libc.h>
     13 #include <shared/bsl.h>
     14 #include <soc/drv.h>
     15 #include <soc/scache.h>
     16 #include <soc/firebolt.h>
     17 
     18 #include <bcm/error.h>
     19 #include <bcm/cosq.h>
     20 
     21 #include <bcm_int/esw/cosq.h>
     22 #include <bcm_int/esw/mbcm.h>
     23 #include <bcm_int/esw/firebolt.h>
     24 
     25 #include <bcm_int/esw_dispatch.h>
     26 
     27 #ifdef BCM_WARM_BOOT_SUPPORT
     28 #include <bcm_int/esw/switch.h>
     29 #endif /* BCM_WARM_BOOT_SUPPORT */
     30 
     31 /*
     32  * MMU Configuration default settings.
     33  * These can be overridden at runtime using config properties.
     34  * Also see soc/esw/firebolt.c (soc_firebolt_mmu_init) for
     35  * one-time XQ settings (HOLCOSPKTSETLIMIT)
     36  */
     37 #define	MMU_CELL_SIZE		128	/* not overrideable */
     38 #define MMU_FLOW_PERCENT	90
     39 #define MMU_FLOW_FANIN		4
     40 #define MMU_FLOW_PKTMIN		8	/* not overrideable */
     41 #define	MMU_RED_DROP_PERCENT	60
     42 #define	MMU_YELLOW_DROP_PERCENT	80
     43 #define	MMU_STATIC_BYTES	(1536 * 1)
     44 #define	MMU_STATIC_PERCENT	50	/* not used if STATIC_BYTES set */
     45 #define	MMU_RESET_BYTES		(1536 * 2)
     46 #define	MMU_RESET_MIN_PERCENT	50	/* not overrideable */
     47 #define	MMU_OVERCOMMIT		1	/* non-stack dynamic cell overcommit */
     48 #define	MMU_OVERCOMMIT_STACK	2	/* stack dynamic cell overcommit */
     49 
     50 #if defined(BCM_FIREBOLT_SUPPORT)
     51 
     52 static int _num_cosq[SOC_MAX_NUM_DEVICES];
     53 
     54 #define FB_DRR_KBYTES   (1)
     55 #define FB_DRR_MBYTES   (1024)
     56 #define FB_DRR_WEIGHT_MAX 0xf
     57 #define FB_WRR_WEIGHT_MAX 0xf
     58 
     59 static int drr_weight_to_kbytes[FB_DRR_WEIGHT_MAX + 1] = {
     60     /* Weight         Kbytes    */
     61     /*  0 */    0 * FB_DRR_KBYTES,  /*    0K bytes - pure priority scheduling */
     62     /*  1 */   10 * FB_DRR_KBYTES,  /*   10K bytes */
     63     /*  2 */   20 * FB_DRR_KBYTES,  /*   20K bytes */
     64     /*  3 */   40 * FB_DRR_KBYTES,  /*   40K bytes */
     65     /*  4 */   80 * FB_DRR_KBYTES,  /*   80K bytes */
     66     /*  5 */  160 * FB_DRR_KBYTES,  /*  160K bytes */
     67     /*  6 */  320 * FB_DRR_KBYTES,  /*  320K bytes */
     68     /*  7 */  640 * FB_DRR_KBYTES,  /*  640K bytes */
     69     /*  8 */ 1280 * FB_DRR_KBYTES,  /* 1280K bytes */
     70     /*  9 */ 2560 * FB_DRR_KBYTES,  /* 2560K bytes */
     71     /* 10 */ 5120 * FB_DRR_KBYTES,  /* 5120K bytes */
     72     /* 11 */   10 * FB_DRR_MBYTES,  /*   10M bytes */
     73     /* 12 */   20 * FB_DRR_MBYTES,  /*   20M bytes */
     74     /* 13 */   40 * FB_DRR_MBYTES,  /*   40M bytes */
     75     /* 14 */   80 * FB_DRR_MBYTES,  /*   80M bytes */
     76     /* 15 */  160 * FB_DRR_MBYTES   /*  160M bytes */
     77 };
     78 
     79 #if defined(BCM_RAPTOR_SUPPORT)
     80 
     81 #define BCM_MTU_QUANTA_ID_COUNT 4
     82 
     83 static int MTU_Quanta[BCM_MTU_QUANTA_ID_COUNT] = {
     84     2 *  FB_DRR_KBYTES,     /* Quanta of 2048 bytes */
     85     4 *  FB_DRR_KBYTES,     /* Quanta of 4096 bytes */
     86     8 *  FB_DRR_KBYTES,     /* Quanta of 8192 bytes */
     87    16 *  FB_DRR_KBYTES      /* Quanta of 16384 bytes */
     88 };
     89 
     90 #endif /* defined(BCM_RAPTOR_SUPPORT) */
     91 
     92 #if defined(BCM_FIREBOLT2_SUPPORT)
     93 #define BCM_FB2_MTU_QUANTA_SMALL                2
     94 #define BCM_FB2_MTU_QUANTA_LARGE                16
     95 #define BCM_FB2_COS_WEIGHT_MAX                  0xff
     96 #define BCM_FB2_CNG_CELL_LIMIT_GRANULARITY      8
     97 #define BCM_FB2_CNG_CELL_LIMIT_MAX              0x1ffc
     98 #endif
     99 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT)
    100 #define BCM_FB2_CNG_PKT_LIMIT_GRANULARITY       4
    101 #endif
    102 
    103 #undef FB_DRR_KBYTES
    104 #undef FB_DRR_MBYTES
    105 
    106 /*
    107  * Convert the number of kbytes (1024 bytes) that can transmtted in one run
    108  * to weight encoding as per table above
    109  */
    110 static int
    111 _bcm_fb_cos_drr_kbytes_to_weight(int kbytes)
    112 {
    113     int weight;
    114     for (weight = 0; weight <= FB_DRR_WEIGHT_MAX; weight++) {
    115         if (kbytes <= drr_weight_to_kbytes[weight]) {
    116             break;
    117         }
    118     }
    119 
    120     if (weight > FB_DRR_WEIGHT_MAX) {
    121         weight = FB_DRR_WEIGHT_MAX;
    122     }
    123 
    124     return weight;
    125 }
    126 
    127 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT)
    128 #define BCM_COS_WEIGHT_MAX      0x7f
    129 
    130 static int
    131 _bcm_cos_max_weight(const int weight[])
    132 {
    133     int i, max_weight = 0;
    134 
    135     /* find max weight */
    136     for (i = 0; i < 8; i++ ) {
    137         if (max_weight < weight[i]) {
    138             max_weight = weight[i];
    139         }
    140     }
    141 
    142     return max_weight;
    143 }
    144 #endif
    145 
    146 #if defined(BCM_RAPTOR_SUPPORT)
    147 /*
    148  * Calculates the Quanta needed for COS according to its weight
    149  */
    150 static int
    151 _bcm_rp_cos_drr_weights_to_quanta(const int weight[])
    152 {
    153     int i, max_weight = 0;
    154 
    155     max_weight = _bcm_cos_max_weight(weight);
    156 
    157     /* Search for the right quanta for max_wight*/
    158     for (i = 0; i < BCM_MTU_QUANTA_ID_COUNT; i++ ) {
    159         if (max_weight <= MTU_Quanta[i] * BCM_COS_WEIGHT_MAX) {
    160             return i;   /* Right Quanta was found */
    161         }
    162     }
    163 
    164     return -1;  /* In case of too big weight return negative value */
    165 }
    166 
    167 /*
    168  * Convert the number of kbytes (1024 bytes) that can transmtted in one run
    169  * to weight encoding for Raptor
    170  */
    171 static int
    172 _bcm_rp_cos_drr_kbytes_to_weight(int kbytes, int MTUQuantaSel)
    173 {
    174     int cos_weight = 0;
    175     int weight_found = FALSE, low_weight_boundary, hi_weight_boundary;
    176 
    177     /* Search for right weight */
    178     low_weight_boundary = 1;
    179     hi_weight_boundary = BCM_COS_WEIGHT_MAX;
    180 
    181     /* Boundary conditions */
    182     if (kbytes >= hi_weight_boundary * MTU_Quanta[MTUQuantaSel]) {
    183         cos_weight = hi_weight_boundary;
    184         weight_found = TRUE;
    185     }
    186     if (kbytes <= low_weight_boundary * MTU_Quanta[MTUQuantaSel]) {
    187         cos_weight = low_weight_boundary;
    188         weight_found = TRUE;
    189     }
    190 
    191     while (!weight_found) {
    192         cos_weight =  (hi_weight_boundary + low_weight_boundary) / 2;
    193         if (kbytes <= cos_weight * MTU_Quanta[MTUQuantaSel]) {
    194            if (kbytes > ((cos_weight - 1) * MTU_Quanta[MTUQuantaSel])) {
    195                weight_found = TRUE;
    196            } else {
    197                hi_weight_boundary = cos_weight;
    198            }
    199         } else {
    200             if (kbytes <= ((cos_weight + 1) * MTU_Quanta[MTUQuantaSel])) {
    201                 cos_weight++;
    202                 weight_found = TRUE;
    203             } else {
    204                 low_weight_boundary = cos_weight;
    205             }
    206         }
    207     } /* Here weight should be found */
    208 
    209     return cos_weight;
    210 }
    211 
    212 /*
    213  * Convert the encoded weights to number of kbytes that can transmtted
    214  * in one run.
    215  */
    216 static int
    217 _bcm_rp_cos_drr_weight_to_kbytes(int weight, int MTUQuantaSel)
    218 {
    219     return (weight * MTU_Quanta[MTUQuantaSel]);
    220 }
    221 #endif     /* defined(BCM_RAPTOR_SUPPORT) */
    222 
    223 /*
    224  * Convert the encoded weights to number of kbytes that can transmtted
    225  * in one run.
    226  */
    227 static int
    228 _bcm_fb_cos_drr_weight_to_kbytes(int weight)
    229 {
    230     assert(weight <= FB_DRR_WEIGHT_MAX);
    231 
    232     return(drr_weight_to_kbytes[weight]);
    233 }
    234 
    235 #if defined(BCM_FIREBOLT2_SUPPORT)
    236 /*
    237  * Calculates the Quanta needed for COS according to its weight
    238  */
    239 static int
    240 _bcm_fb2_cos_drr_weights_to_quanta(const int weight[])
    241 {
    242     int max_weight = 0;
    243 
    244     max_weight = _bcm_cos_max_weight(weight);
    245 
    246     /* Search for the right quanta for max_weight*/
    247     if (max_weight <= (BCM_FB2_MTU_QUANTA_SMALL * BCM_FB2_COS_WEIGHT_MAX)) {
    248         return BCM_FB2_MTU_QUANTA_SMALL;
    249     } else if (max_weight <=
    250                (BCM_FB2_MTU_QUANTA_LARGE * BCM_FB2_COS_WEIGHT_MAX)) {
    251         return BCM_FB2_MTU_QUANTA_LARGE;
    252     }
    253 
    254     return -1;  /* In case of too big weight return negative value */
    255 }
    256 
    257 /*
    258  * Convert the number of kbytes (1024 bytes) that can transmtted in one run
    259  * to weight encoding for Firebolt2
    260  */
    261 static int
    262 _bcm_fb2_cos_drr_kbytes_to_weight(int kbytes, int MTUQuanta)
    263 {
    264     int cos_weight = 0;
    265     int weight_found = FALSE, low_weight_boundary, hi_weight_boundary;
    266 
    267     /* Search for right weight */
    268     low_weight_boundary = 1;
    269     hi_weight_boundary = BCM_FB2_COS_WEIGHT_MAX;
    270 
    271     /* Boundary conditions */
    272     if (kbytes >= hi_weight_boundary * MTUQuanta) {
    273         cos_weight = hi_weight_boundary;
    274         weight_found = TRUE;
    275     }
    276     if (kbytes <= low_weight_boundary * MTUQuanta) {
    277         cos_weight = low_weight_boundary;
    278         weight_found = TRUE;
    279     }
    280 
    281     while (!weight_found) {
    282         cos_weight =  (hi_weight_boundary + low_weight_boundary) / 2;
    283         if (kbytes <= cos_weight * MTUQuanta) {
    284            if (kbytes > ((cos_weight - 1) * MTUQuanta)) {
    285                weight_found = TRUE;
    286            } else {
    287                hi_weight_boundary = cos_weight;
    288            }
    289         } else {
    290             if (kbytes <= ((cos_weight + 1) * MTUQuanta)) {
    291                 cos_weight++;
    292                 weight_found = TRUE;
    293             } else {
    294                 low_weight_boundary = cos_weight;
    295             }
    296         }
    297     } /* Here weight should be found */
    298 
    299     return cos_weight;
    300 }
    301 #endif     /* defined(BCM_FIREBOLT2_SUPPORT) */
    302 
    303 
    304 #ifdef BCM_WARM_BOOT_SUPPORT
    305 
    306 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    307 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
    308 
    309 /*
    310  * Function:
    311  *      bcm_fb_cosq_sync
    312  * Purpose:
    313  *      Record COSQ module persistent info for Level 2 Warm Boot.
    314  * Parameters:
    315  *      unit - Unit number.
    316  * Returns:
    317  *      BCM_E_XXX
    318  */
    319 int
    320 bcm_fb_cosq_sync(int unit)
    321 {
    322     soc_scache_handle_t scache_handle;
    323     uint8               *cosq_scache_ptr;
    324     uint32              num_cosq;
    325 
    326     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    327     BCM_IF_ERROR_RETURN
    328         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    329                                  0, &cosq_scache_ptr, 
    330                                  BCM_WB_DEFAULT_VERSION, NULL));
    331     
    332     /* Number COSQ */
    333     num_cosq = _num_cosq[unit];
    334     sal_memcpy(cosq_scache_ptr, &num_cosq, sizeof(num_cosq));
    335         
    336     return BCM_E_NONE;
    337 }
    338 
    339 /*
    340  * Function:
    341  *      _bcm_fb_cosq_reinit
    342  * Purpose:
    343  *      Recover COSQ software state.
    344  * Parameters:
    345  *      unit - Unit number.
    346  * Returns:
    347  *      BCM_E_XXX
    348  */
    349 STATIC int
    350 _bcm_fb_cosq_reinit(int unit)
    351 {
    352     int                 rv;
    353     soc_scache_handle_t scache_handle;
    354     uint8               *cosq_scache_ptr;
    355     uint32              num_cosq;
    356  	 
    357     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    358     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    359                                  0, &cosq_scache_ptr, 
    360                                  BCM_WB_DEFAULT_VERSION, NULL);
    361 
    362     if (rv == BCM_E_NOT_FOUND) {
    363         cosq_scache_ptr = NULL;
    364     } else if (BCM_FAILURE(rv)) {
    365         return rv;
    366     }
    367 
    368     if (cosq_scache_ptr != NULL) {
    369         /* Number COSQ */
    370         sal_memcpy(&num_cosq, cosq_scache_ptr, sizeof(num_cosq));
    371         _num_cosq[unit] = num_cosq;
    372 
    373     } else {
    374         int cos;
    375         uint32 val, csl;
    376 
    377         /* Make best guess */
    378         if (soc_reg_field_valid(unit, LWMCOSCELLSETLIMITr,
    379                                 CELLSETLIMITf)) {
    380             for (cos = 0; cos < NUM_COS(unit); cos++) {
    381                 SOC_IF_ERROR_RETURN
    382                     (READ_LWMCOSCELLSETLIMITr(unit, REG_PORT_ANY, cos, &val));
    383                 csl = soc_reg_field_get(unit, LWMCOSCELLSETLIMITr,
    384                                         val, CELLSETLIMITf);
    385                 if (csl == 0) {
    386                     /* No more COSq info for this COS value, so we're done */
    387                     break;
    388                 }
    389             }
    390         } else {
    391             cos = _bcm_esw_cosq_config_property_get(unit);
    392         }
    393 
    394         _num_cosq[unit] = cos;
    395     }
    396 
    397     return BCM_E_NONE;
    398 }
    399 #endif /* BCM_WARM_BOOT_SUPPORT */
    400 
    401 /*
    402  * Function:
    403  *      bcm_fb_cosq_init
    404  * Purpose:
    405  *      Initialize (clear) all COS schedule/mapping state.
    406  * Parameters:
    407  *      unit - StrataSwitch unit number.
    408  * Returns:
    409  *      BCM_E_XXX
    410  */
    411 
    412 int
    413 bcm_fb_cosq_init(int unit)
    414 {
    415     int         num_cos;
    416 #ifdef BCM_WARM_BOOT_SUPPORT
    417     int                 rv;
    418     soc_scache_handle_t scache_handle;
    419     uint32              cosq_scache_size;
    420     uint8               *cosq_scache_ptr;
    421 #endif /* BCM_WARM_BOOT_SUPPORT */
    422 
    423 #ifdef BCM_WARM_BOOT_SUPPORT
    424     /* Warm boot level 2 cache size */
    425     cosq_scache_size = sizeof(uint32); /* Number COSQ */
    426 
    427     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    428     rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
    429                                  (0 == SOC_WARM_BOOT(unit)),
    430                                  cosq_scache_size, &cosq_scache_ptr, 
    431                                  BCM_WB_DEFAULT_VERSION, NULL);
    432     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    433         return rv;
    434     }
    435 
    436     if (SOC_WARM_BOOT(unit)) {
    437         return _bcm_fb_cosq_reinit(unit);
    438     }
    439 #endif /* BCM_WARM_BOOT_SUPPORT */
    440 
    441     num_cos = _bcm_esw_cosq_config_property_get(unit);
    442 
    443     return bcm_fb_cosq_config_set(unit, num_cos);
    444 }
    445 
    446 /*
    447  * MMU Programming for 56500 style memory managers.
    448  * Includes 56100, 56300, 56200 devices.
    449  *
    450  * The MMU is always configured for dynamic mode.
    451  *
    452  * Per-port/per-cos limits are programmed in soc_firebolt_mmu_init
    453  * based on the mmu_xq_weight config parameters.  This has to happen
    454  * one time during initialization.  The remaining parameters can be
    455  * updated multiple times after initialization.
    456  *
    457  * Default MMU xq (packet) controls allow for 8 queues to be used
    458  * even less than 8 are currently configured.  If less than 8 queues
    459  * will ever be used then the remaining queues mmu_xq_weight_cosN
    460  * values should be set to 0.  A 4 queue configuration should set
    461  * mmu_xq_weight_cosN=0 for N=4, 5, 6, 7.
    462  *
    463  * MMU Controls used here have defaults based on the defines at the
    464  * top of this file.  Each of those defaults can be overridden using
    465  * config properties.
    466  *
    467  * mmu_flow_percent=90		percentage of per-port cells useable
    468  *				before flow control starts
    469  * mmu_flow_fanin=4		number of simulteneous senders to each
    470  *				port for flow control purposes
    471  * mmu_red_drop_percent=60
    472  * mmu_yellow_drop_percent=80	percentage of per-port/per-cos packets
    473  *				used before red or yellow packets will
    474  *				be dropped
    475  * mmu_static_bytes=1536	per-port/per-cos static reserved limit.
    476  *				Rounded up from bytes to next cell size.
    477  *				Remaining cells are put in dynamic pool.
    478  *				If 0, then mmu_static_percent is used.
    479  * mmu_static_percent=50	Percentage of per-port/per-cos cells to
    480  *				use as static reserved limit.
    481  *				Remaining cells are put in dynamic pool.
    482  *				Only used if mmu_static_bytes is 0.
    483  * mmu_reset_bytes=3072		(1536*2)
    484  *				offset from dynamic cell set limits for
    485  *				reset (enable) limits.
    486  *				Rounded up from bytes to next cell size.
    487  * mmu_overcommit=1		non-stack port overcommit factor for
    488  *				dynamic pool
    489  * mmu_overcommit_stack=2	stack port overcommit factor for
    490  *				dynamic pool.  If 0, then use the
    491  *				mmu_overcommit value for stack ports
    492  */
    493 
    494 STATIC int
    495 _bcm_fb_cosq_config_set(int unit, int numq)
    496 {
    497     int         ncells, nports, xq_per_port, cos;
    498     int         n, nreset, used_cells;
    499     int		scells, dcells;
    500     soc_port_t  port;
    501     uint32      val, limit_red, limit_yel;
    502     soc_mem_t   xq_mem;
    503     int		mmu_flow_percent;
    504     int		mmu_flow_fanin;
    505     int		mmu_red_drop_percent;
    506     int		mmu_yellow_drop_percent;
    507     int		mmu_static_bytes;
    508     int		mmu_static_cells;
    509     int		mmu_static_percent;
    510     int		mmu_reset_bytes;
    511     int		mmu_reset_cells = 0;
    512     int		mmu_overcommit;
    513     int		mmu_overcommit_stack;
    514 #if defined (BCM_HAWKEYE_SUPPORT)
    515     int		mmu_dyncellsetlimit = 0;
    516     int		mmu_xoff_pkt_threshold = 0;
    517     int		mmu_xoff_cell_threshold = 0;
    518     int		xq_per_cos = 0;
    519 #endif /* BCM_HAWKEYE_SUPPORT */
    520 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_HELIX_SUPPORT) || \
    521     defined(BCM_FELIX_SUPPORT)  || defined(BCM_FIREBOLT2_SUPPORT)
    522     int		sreset;
    523 #endif
    524 
    525     /* Validate cosq num */
    526     if (numq < 1) {
    527         return BCM_E_PARAM;
    528     }
    529 
    530     ncells = soc_mem_index_count(unit, MMU_CBPDATA0m);
    531 #if defined (BCM_HAWKEYE_SUPPORT)
    532     if(SOC_IS_HAWKEYE(unit)){
    533         nports = NUM_E_PORT(unit);
    534         /* These special variables are for Hawkeye only. 
    535             Those values are retrieved from HAWKEYE MMU setting document*/
    536         mmu_dyncellsetlimit = 2400;
    537         mmu_xoff_pkt_threshold = 12;
    538         mmu_xoff_cell_threshold = 74;
    539         xq_per_cos = 8;
    540     } else 
    541 #endif /* BCM_HAWKEYE_SUPPORT */
    542     {
    543         nports = NUM_ALL_PORT(unit);
    544     }
    545 
    546     /* get mmu control config values */
    547     mmu_flow_percent = soc_property_get(unit,
    548 					spn_MMU_FLOW_PERCENT,
    549 					MMU_FLOW_PERCENT);
    550     mmu_flow_fanin = soc_property_get(unit,
    551 				      spn_MMU_FLOW_FANIN,
    552 				      MMU_FLOW_FANIN);
    553     mmu_red_drop_percent = soc_property_get(unit,
    554 					    spn_MMU_RED_DROP_PERCENT,
    555 					    MMU_RED_DROP_PERCENT);
    556     mmu_yellow_drop_percent = soc_property_get(unit,
    557 					       spn_MMU_YELLOW_DROP_PERCENT,
    558 					       MMU_YELLOW_DROP_PERCENT);
    559     mmu_static_bytes = soc_property_get(unit,
    560 					spn_MMU_STATIC_BYTES,
    561 					MMU_STATIC_BYTES);
    562     mmu_static_percent = soc_property_get(unit,
    563 					  spn_MMU_STATIC_PERCENT,
    564 					  MMU_STATIC_PERCENT);
    565     mmu_reset_bytes = soc_property_get(unit,
    566 				       spn_MMU_RESET_BYTES,
    567 				       MMU_RESET_BYTES);
    568     mmu_overcommit = soc_property_get(unit,
    569 				      spn_MMU_OVERCOMMIT,
    570 				      MMU_OVERCOMMIT);
    571     mmu_overcommit_stack = soc_property_get(unit,
    572 					    spn_MMU_OVERCOMMIT_STACK,
    573 					    MMU_OVERCOMMIT_STACK);
    574 
    575     /* sanity check config values */
    576     if (mmu_flow_percent <= 0 || mmu_flow_percent > 100) {
    577 	mmu_flow_percent = 100;
    578     }
    579     if (mmu_red_drop_percent <= 0 || mmu_red_drop_percent > 100) {
    580 	mmu_red_drop_percent = 100;
    581     }
    582     if (mmu_yellow_drop_percent <= 0 || mmu_yellow_drop_percent > 100) {
    583 	mmu_yellow_drop_percent = 100;
    584     }
    585     if (mmu_static_percent <= 0 || mmu_static_percent > 100) {
    586 	mmu_static_percent = MMU_STATIC_PERCENT;
    587     }
    588     if (mmu_overcommit <= 0) {
    589 	mmu_overcommit = 1;
    590     }
    591     if (mmu_overcommit_stack <= 0) {
    592 	mmu_overcommit_stack = mmu_overcommit;
    593     }
    594     mmu_static_cells = (mmu_static_bytes + MMU_CELL_SIZE - 1) / MMU_CELL_SIZE;
    595     mmu_reset_cells = (mmu_reset_bytes + MMU_CELL_SIZE - 1) / MMU_CELL_SIZE;
    596 
    597     /* calculate static limits first */
    598     if (mmu_static_cells > 0) {
    599 	scells = mmu_static_cells;
    600 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_HELIX_SUPPORT) || \
    601     defined(BCM_FELIX_SUPPORT)  || defined(BCM_FIREBOLT2_SUPPORT)
    602 	sreset = scells;		/* 100% */
    603 #endif
    604     } else {
    605 	scells = (ncells / nports / numq) * mmu_static_percent / 100;
    606 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_HELIX_SUPPORT) || \
    607     defined(BCM_FELIX_SUPPORT)  || defined(BCM_FIREBOLT2_SUPPORT)
    608 	sreset = scells * 75 / 100;	/* 75% */
    609 #endif
    610     }
    611     used_cells = scells * numq * nports;
    612 
    613     /* remaining cells are dynamic */
    614     n = ncells - used_cells;
    615     if (n <= 0) {
    616 	n = 0;
    617     }
    618     dcells = n / nports;
    619     nreset = n - mmu_reset_cells;
    620     if (nreset < (n * MMU_RESET_MIN_PERCENT / 100)) {
    621 	nreset = n * MMU_RESET_MIN_PERCENT / 100;
    622     }
    623     if (nreset <= 0) {
    624 	nreset = 1;
    625     }
    626 
    627     /* device wide dynamic limits */
    628     if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) {
    629 #if defined(BCM_RAPTOR_SUPPORT)
    630         SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLSETLIMITr(unit, &val));
    631         soc_reg_field_set(unit, TOTALDYNCELLSETLIMITr,
    632                           &val, TOTALDYNCELLSETLIMITf, n);
    633         SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLSETLIMITr(unit, val));
    634         SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLRESETLIMITr(unit, &val));
    635         soc_reg_field_set(unit, TOTALDYNCELLRESETLIMITr,
    636                           &val, TOTALDYNCELLRESETLIMITf, nreset);
    637         SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLRESETLIMITr(unit, val));
    638 #endif /* BCM_RAPTOR_SUPPORT*/
    639     } else if (SOC_IS_FIREBOLT2(unit)) {
    640 #if defined(BCM_FIREBOLT2_SUPPORT)
    641         SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLLIMITr(unit, &val));
    642         soc_reg_field_set(unit, TOTALDYNCELLLIMITr,
    643                           &val, SETLIMITf, n);
    644         SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLLIMITr(unit, val));
    645         SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLRESETLIMITr(unit, &val));
    646         soc_reg_field_set(unit, TOTALDYNCELLRESETLIMITr,
    647                           &val, RESETLIMITf, nreset);
    648         SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLRESETLIMITr(unit, val));
    649 
    650 	/* red and yellow drop limits for total dynamic cells */
    651 	limit_red = n * mmu_red_drop_percent / 100;
    652 	limit_yel = n * mmu_yellow_drop_percent / 100;
    653 	limit_red /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY;
    654 	limit_yel /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY;
    655 
    656         val = 0;
    657         soc_reg_field_set(unit, CNGTOTALDYNCELLLIMIT0r,
    658                           &val, CNGTOTALDYNCELLLIMITf, limit_red);
    659         SOC_IF_ERROR_RETURN(WRITE_CNGTOTALDYNCELLLIMIT0r(unit, val));
    660 
    661         val = 0;
    662         soc_reg_field_set(unit, CNGTOTALDYNCELLLIMIT1r,
    663                           &val, CNGTOTALDYNCELLLIMITf, limit_yel);
    664         SOC_IF_ERROR_RETURN(WRITE_CNGTOTALDYNCELLLIMIT1r(unit, val));
    665 #endif /* BCM_FIREBOLT2_SUPPORT */
    666     } else {
    667         SOC_IF_ERROR_RETURN(READ_TOTALDYNCELLLIMITr(unit, &val));
    668         soc_reg_field_set(unit, TOTALDYNCELLLIMITr,
    669                           &val, TOTALDYNCELLLIMITf, n);
    670 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FELIX15_SUPPORT) || \
    671     defined(BCM_HELIX15_SUPPORT) 
    672         if (soc_reg_field_valid(unit, TOTALDYNCELLLIMITr,
    673                                 TOTALDYNCELLRESETLIMITf)) {
    674             soc_reg_field_set(unit, TOTALDYNCELLLIMITr,
    675                               &val, TOTALDYNCELLRESETLIMITf, nreset);
    676         }
    677 #endif /* RAPTOR || FELIX1.5 || HELIX1.5 */
    678         SOC_IF_ERROR_RETURN(WRITE_TOTALDYNCELLLIMITr(unit, val));
    679     }
    680 
    681     /* per-port dynamic limits */
    682     PBMP_ALL_ITER(unit, port) {
    683         if (IS_ST_PORT(unit, port)) {
    684             n = dcells * mmu_overcommit_stack;
    685         } else {
    686 	    n = dcells * mmu_overcommit;
    687 	}
    688 	if (n >= ncells) {
    689 	    n = ncells - 1;
    690 	}
    691 
    692 #if defined (BCM_HAWKEYE_SUPPORT)
    693 	/* For Hawkeye, the value of field DYNCELLLIMIT of register DYNCELLLIMIT is 
    694 	 * min((ncells - used_cells) ,mmu_dyncellsetlimit). */
    695 	if (SOC_IS_HAWKEYE(unit)) {
    696 		if((ncells - used_cells) > mmu_dyncellsetlimit) {
    697 			n = mmu_dyncellsetlimit;
    698 		} else {
    699 			n = ncells - used_cells;
    700 		}
    701 	}
    702 #endif /* BCM_HAWKEYE_SUPPORT */
    703         
    704 	nreset = n - mmu_reset_cells;
    705 	if (nreset < (n * MMU_RESET_MIN_PERCENT / 100)) {
    706 	    nreset = n * MMU_RESET_MIN_PERCENT / 100;
    707 	}
    708 	if (nreset <= 0) {
    709 	    nreset = 1;
    710 	}
    711 
    712         SOC_IF_ERROR_RETURN(READ_DYNCELLLIMITr(unit, port, &val));
    713         if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLLIMITf)) {
    714             soc_reg_field_set(unit, DYNCELLLIMITr, &val,
    715                               DYNCELLLIMITf, n);
    716         }
    717 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_HELIX_SUPPORT) || \
    718     defined(BCM_FELIX_SUPPORT)  || defined(BCM_FIREBOLT2_SUPPORT)
    719         if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLSETLIMITf)) {
    720             soc_reg_field_set(unit, DYNCELLLIMITr, &val,
    721                               DYNCELLSETLIMITf, n);
    722         }
    723         if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLRESETLIMITf)) {
    724             soc_reg_field_set(unit, DYNCELLLIMITr, &val,
    725                               DYNCELLRESETLIMITf, nreset);
    726         }
    727 #endif /* RAPTOR || HELIX || FELIX || FB2  */
    728         if (soc_reg_field_valid(unit, DYNCELLLIMITr, DYNCELLRESETLIMITSELf)) {
    729             soc_reg_field_set(unit, DYNCELLLIMITr, &val,
    730                               DYNCELLRESETLIMITSELf, 0);    /* 75% */
    731         }
    732 
    733         SOC_IF_ERROR_RETURN(WRITE_DYNCELLLIMITr(unit, port, val));
    734 
    735 #if defined(BCM_FIREBOLT2_SUPPORT)
    736         if (SOC_IS_FIREBOLT2(unit)) {
    737 	    /* red and yellow drop limits for per-port dynamic cells */
    738 	    limit_red = n * mmu_red_drop_percent / 100;
    739 	    limit_yel = n * mmu_yellow_drop_percent / 100;
    740 	    limit_red /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY;
    741 	    limit_yel /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY;
    742 
    743             val = 0;
    744             soc_reg_field_set(unit, CNGDYNCELLLIMIT0r, &val,
    745                               CNGDYNCELLLIMITf, limit_red);
    746 	    SOC_IF_ERROR_RETURN(WRITE_CNGDYNCELLLIMIT0r(unit, port, val));
    747 
    748             val = 0;
    749             soc_reg_field_set(unit, CNGDYNCELLLIMIT1r, &val,
    750                               CNGDYNCELLLIMITf, limit_yel);
    751             SOC_IF_ERROR_RETURN(WRITE_CNGDYNCELLLIMIT1r(unit, port, val));
    752         }
    753 #endif
    754 
    755         /*
    756          * Number of transactions allocated to each port,
    757          * shared between that port's active cosqs.
    758          */
    759         SOC_IF_ERROR_RETURN(soc_fb_xq_mem(unit, port, &xq_mem));
    760         xq_per_port = soc_mem_index_count(unit, xq_mem);
    761 
    762 #if defined (BCM_HAWKEYE_SUPPORT)
    763         if(SOC_IS_HAWKEYE(unit)) {
    764             SOC_IF_ERROR_RETURN(WRITE_HOLCOS0MINXQCNTr(unit, port, xq_per_cos));
    765             SOC_IF_ERROR_RETURN(WRITE_HOLCOS1MINXQCNTr(unit, port, xq_per_cos));
    766             SOC_IF_ERROR_RETURN(WRITE_HOLCOS2MINXQCNTr(unit, port, xq_per_cos));
    767             SOC_IF_ERROR_RETURN(WRITE_HOLCOS3MINXQCNTr(unit, port, xq_per_cos));
    768             n = xq_per_port - (xq_per_cos * numq) -4 -5;
    769             SOC_IF_ERROR_RETURN(WRITE_DYNXQCNTPORTr(unit, port, n));
    770             n = n + 8;
    771             for (cos = 0; cos < NUM_COS(unit); cos++) {
    772                 SOC_IF_ERROR_RETURN
    773                     (WRITE_HOLCOSPKTSETLIMITr(unit, port, cos, n));
    774                 SOC_IF_ERROR_RETURN
    775                     (WRITE_HOLCOSPKTRESETLIMITr(unit, port, cos, (n - 4)));
    776             }
    777         }
    778 #endif /* BCM_HAWKEYE_SUPPORT */
    779 
    780         /*
    781          * Divide weighted per-port packet limits into each cos.
    782          * Initialize all COSQs, even the inactive ones.
    783          */
    784         for (cos = 0; cos < NUM_COS(unit); cos++) {
    785 	    /* set per-port static limits (calculated earlier) */
    786             SOC_IF_ERROR_RETURN
    787                 (READ_LWMCOSCELLSETLIMITr(unit, port, cos, &val));
    788             if (soc_reg_field_valid(unit, LWMCOSCELLSETLIMITr,
    789                                     CELLSETLIMITf)) {
    790                 soc_reg_field_set(unit, LWMCOSCELLSETLIMITr,
    791                                   &val, CELLSETLIMITf,
    792 				  cos < numq ? scells : 0);
    793             }
    794 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_HELIX_SUPPORT) || \
    795     defined(BCM_FELIX_SUPPORT)  || defined(BCM_FIREBOLT2_SUPPORT)
    796             if (soc_reg_field_valid(unit, LWMCOSCELLSETLIMITr,
    797                                     CELLRESETLIMITf)) {
    798                 soc_reg_field_set(unit, LWMCOSCELLSETLIMITr,
    799                                   &val, CELLRESETLIMITf,
    800 				  cos < numq ? sreset : 0);
    801             }
    802 #endif /* RAPTOR || HELIX || FELIX || FB2  */
    803             SOC_IF_ERROR_RETURN
    804                 (WRITE_LWMCOSCELLSETLIMITr(unit, port, cos, val));
    805 
    806 
    807 	    /* set red and yellow drop limits */
    808 	    /* set as a percentage of the green drop (HOL) limit */
    809 
    810             SOC_IF_ERROR_RETURN
    811 		(READ_HOLCOSPKTSETLIMITr(unit, port, cos, &val));
    812             n = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, val,
    813                                     PKTSETLIMITf);
    814 
    815             /* Make sure numq will work with the cosq weighting. */
    816             if ((cos < numq) && (n == 4)) {
    817                 /*
    818                  * This means that this COSQ has been
    819                  * disabled due to XQ weighting, but
    820                  * has been selected as active. Config error.
    821                  */
    822                 return BCM_E_PARAM;
    823             }
    824 
    825 	    /* per-queue packet red and yellow drop */
    826             if (cos < numq) {
    827                 limit_red = n * mmu_red_drop_percent / 100;
    828                 limit_yel = n * mmu_yellow_drop_percent / 100;
    829             } else {
    830                 limit_red = xq_per_port - 1; /* Max limit (disabled) */
    831                 limit_yel = xq_per_port - 1; /* Max limit (disabled) */
    832             }
    833 
    834 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT)
    835             /* CNG limit for FB2 is set at 4 packet granularity */
    836             /* CNG limit for Raven and Hawkeye is set at packet granularity */
    837             if (SOC_IS_FIREBOLT2(unit)) { /* Granularity limitation */
    838                 limit_red /= BCM_FB2_CNG_PKT_LIMIT_GRANULARITY;
    839                 limit_yel /= BCM_FB2_CNG_PKT_LIMIT_GRANULARITY;
    840             }
    841 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAPTOR_SUPPORT */
    842 
    843             val = 0;
    844             soc_reg_field_set(unit, CNGCOSPKTLIMIT0r, &val,
    845                               CNGPKTSETLIMIT0f, limit_red);
    846 	    SOC_IF_ERROR_RETURN(WRITE_CNGCOSPKTLIMIT0r(unit, port, cos, val));
    847 
    848             val = 0;
    849             soc_reg_field_set(unit, CNGCOSPKTLIMIT1r, &val,
    850                               CNGPKTSETLIMIT1f, limit_yel);
    851 	    SOC_IF_ERROR_RETURN(WRITE_CNGCOSPKTLIMIT1r(unit, port, cos, val));
    852 
    853 #if defined(BCM_FIREBOLT2_SUPPORT)
    854 	    /* per-queue cell red and yellow drop */
    855             if (SOC_IS_FIREBOLT2(unit)) {
    856 		/* disabled (set to maximum) */
    857 		limit_red = BCM_FB2_CNG_CELL_LIMIT_MAX;
    858 		limit_yel = BCM_FB2_CNG_CELL_LIMIT_MAX;
    859 		limit_red /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY;
    860 		limit_yel /= BCM_FB2_CNG_CELL_LIMIT_GRANULARITY;
    861 
    862                 val = 0;
    863                 soc_reg_field_set(unit, CNGCOSCELLLIMIT0r, &val,
    864                                   CNGCELLSETLIMITf, limit_red);
    865 		SOC_IF_ERROR_RETURN
    866 		    (WRITE_CNGCOSCELLLIMIT0r(unit, port, cos, val));
    867 
    868                 val = 0;
    869                 soc_reg_field_set(unit, CNGCOSCELLLIMIT1r, &val,
    870                                   CNGCELLSETLIMITf, limit_yel);
    871 		SOC_IF_ERROR_RETURN
    872 		    (WRITE_CNGCOSCELLLIMIT1r(unit, port, cos, val));
    873             }
    874 #endif
    875         }
    876 
    877 	/* cell ingress back pressure */
    878         if (port == CMIC_PORT(unit)) {
    879             n = ncells-1;
    880         } else {
    881 	    /* flow control cells (static + dynamic) */
    882 	    n = scells * mmu_flow_percent / 100;
    883 	    n += dcells;
    884 	    if (n < 0 || n >= ncells) {
    885 		n = ncells - 1;
    886 	    }
    887         }
    888 
    889         SOC_IF_ERROR_RETURN(READ_IBPCELLSETLIMITr(unit, port, &val));
    890 #if defined (BCM_HAWKEYE_SUPPORT)
    891         if(SOC_IS_HAWKEYE(unit)) {
    892             n = mmu_xoff_cell_threshold;
    893             soc_reg_field_set(unit, IBPCELLSETLIMITr, &val,
    894                               RESETLIMITSELf, 0); /* 75% */
    895         }
    896 #endif /* BCM_HAWKEYE_SUPPORT */   
    897         soc_reg_field_set(unit, IBPCELLSETLIMITr, &val,
    898                           CELLSETLIMITf, n);
    899         SOC_IF_ERROR_RETURN(WRITE_IBPCELLSETLIMITr(unit, port, val));
    900 
    901         SOC_IF_ERROR_RETURN(READ_IBPDISCARDSETLIMITr(unit, port, &val));
    902         soc_reg_field_set(unit, IBPDISCARDSETLIMITr, &val,
    903                           DISCARDSETLIMITf, ncells-1);
    904         SOC_IF_ERROR_RETURN(WRITE_IBPDISCARDSETLIMITr(unit, port, val));
    905 
    906 	/* packet ingress back pressure */
    907 	if (port == CMIC_PORT(unit) || mmu_flow_fanin <= 0) {
    908 	    n = xq_per_port - 1;
    909 	} else {
    910 	    n = xq_per_port / numq / mmu_flow_fanin;
    911 	    if (n < MMU_FLOW_PKTMIN) {
    912 		n = MMU_FLOW_PKTMIN;
    913 	    }
    914 	}
    915 
    916         SOC_IF_ERROR_RETURN(READ_IBPPKTSETLIMITr(unit, port, &val));
    917 #if defined (BCM_HAWKEYE_SUPPORT)
    918         if(SOC_IS_HAWKEYE(unit)) {
    919             n=mmu_xoff_pkt_threshold;
    920         }
    921 #endif /* BCM_HAWKEYE_SUPPORT */     
    922         soc_reg_field_set(unit, IBPPKTSETLIMITr, &val,
    923                           PKTSETLIMITf, n);
    924         soc_reg_field_set(unit, IBPPKTSETLIMITr, &val,
    925                           RESETLIMITSELf, 0);	/* 75% */
    926         SOC_IF_ERROR_RETURN(WRITE_IBPPKTSETLIMITr(unit, port, val));
    927     }
    928 
    929     /* Overall MMU controls */
    930     SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &val));
    931     soc_reg_field_set(unit, MISCCONFIGr, &val, DYNAMIC_MEMORY_ENf, 1);
    932 #if defined(BCM_FIREBOLT2_SUPPORT)
    933     if (soc_reg_field_valid(unit, MISCCONFIGr, SOP_DROP_ONLY_POLICY_ENf)) {
    934         soc_reg_field_set(unit, MISCCONFIGr, &val, SOP_DROP_ONLY_POLICY_ENf, 1);
    935     }
    936 #endif /* BCM_FIREBOLT2_SUPPORT */
    937 
    938 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FELIX15_SUPPORT) || \
    939     defined(BCM_HELIX15_SUPPORT)
    940     if (soc_reg_field_valid(unit, MISCCONFIGr, HOL_CELL_SOP_DROP_ENf)) {
    941         soc_reg_field_set(unit, MISCCONFIGr, &val, HOL_CELL_SOP_DROP_ENf, 1);
    942     }
    943 #endif /* BCM_RAPTOR_SUPPORT || BCM_FELIX15_SUPPORT || BCM_HELIX15_SUPPORT */
    944 
    945     SOC_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, val));
    946 
    947     return BCM_E_NONE;
    948 }
    949 
    950 
    951 /*
    952  * Function:
    953  *      bcm_fb_cosq_config_set
    954  * Purpose:
    955  *      Set the number of COS queues
    956  * Parameters:
    957  *      unit - Draco unit number.
    958  *      numq - number of COS queues (1-8).
    959  * Returns:
    960  *      BCM_E_XXX
    961  */
    962 
    963 int
    964 bcm_fb_cosq_config_set(int unit, int numq)
    965 {
    966     int         cos, prio, ratio, remain;
    967 
    968     SOC_IF_ERROR_RETURN(_bcm_fb_cosq_config_set(unit, numq));
    969 
    970     /* Map the eight 802.1 priority levels to the active cosqs */
    971     ratio = 8 / numq;
    972     remain = 8 % numq;
    973     cos = 0;
    974     for (prio = 0; prio < 8; prio++) {
    975         BCM_IF_ERROR_RETURN
    976             (bcm_fb_er_cosq_mapping_set(unit, -1, prio, cos));
    977         if ((prio + 1) == (((cos + 1) * ratio) +
    978                            ((remain < (numq - cos)) ? 0 :
    979                             (remain - (numq - cos) + 1)))) {
    980             cos++;
    981         }
    982     }
    983 
    984 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
    985     SOC_IF_ERROR_RETURN(soc_cosq_stack_port_map_disable(unit));
    986 #endif
    987 
    988     /* use identity mapping for CPU priority mapping */
    989     SOC_IF_ERROR_RETURN(soc_cpu_priority_mapping_init(unit));
    990 
    991     _num_cosq[unit] = numq;
    992 
    993 #ifdef BCM_WARM_BOOT_SUPPORT
    994     SOC_CONTROL_LOCK(unit);
    995     SOC_CONTROL(unit)->scache_dirty = 1;
    996     SOC_CONTROL_UNLOCK(unit);
    997 #endif
    998 
    999     return BCM_E_NONE;
   1000 }
   1001 
   1002 /*
   1003  * Function:
   1004  *      bcm_fb_cosq_config_get
   1005  * Purpose:
   1006  *      Get the number of cos queues
   1007  * Parameters:
   1008  *      unit - StrataSwitch unit number.
   1009  *      numq - (Output) number of cosq
   1010  * Returns:
   1011  *      BCM_E_XXX
   1012  */
   1013 
   1014 int
   1015 bcm_fb_cosq_config_get(int unit, int *numq)
   1016 {
   1017     if (_num_cosq[unit] == 0) {
   1018         return BCM_E_INIT;
   1019     }
   1020 
   1021     if (numq != NULL) {
   1022         *numq = _num_cosq[unit];
   1023     }
   1024 
   1025     return (BCM_E_NONE);
   1026 }
   1027 
   1028 /*
   1029  * Function:
   1030  *      bcm_fb_cosq_port_sched_set
   1031  * Purpose:
   1032  *      Set up class-of-service policy and corresponding weights and delay
   1033  * Parameters:
   1034  *      unit - StrataSwitch unit number.
   1035  *      pbm - port bitmap
   1036  *      mode - Scheduling mode, one of BCM_COSQ_xxx
   1037  *      weights - Weights for each COS queue
   1038  *                Only for BCM_COSQ_WEIGHTED_FAIR_ROUND_ROBIN mode.
   1039  *                For DRR Weight is specified in Kbytes
   1040  *      delay - This parameter is not used in 56504
   1041  * Returns:
   1042  *      BCM_E_XXX
   1043  */
   1044 
   1045 int
   1046 bcm_fb_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
   1047                               int mode, const int weights[], int delay)
   1048 {
   1049     uint32              wrr;
   1050     int                 port, t;
   1051     uint32              cosarbsel;
   1052     int                 mbits = 0;
   1053     int                 i;
   1054     int                 enc_weights[8];
   1055 #if defined (BCM_RAPTOR_SUPPORT)
   1056     int                 MTUQuantaSel = 0;
   1057 #endif
   1058 #if defined (BCM_FIREBOLT2_SUPPORT)
   1059     int                 MTUQuanta = 0;
   1060 #endif
   1061 
   1062     COMPILER_REFERENCE(delay);
   1063 
   1064     switch (mode) {
   1065     case BCM_COSQ_STRICT:
   1066         mbits = 0;
   1067         break;
   1068     case BCM_COSQ_ROUND_ROBIN:
   1069         mbits = 1;
   1070         break;
   1071     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   1072         mbits = 2;
   1073         /*
   1074          * All weight values must fit within 4 bits.
   1075          * If weight is 0, this queue is run in strict mode,
   1076          * others run in WRR mode.
   1077          */
   1078 #if defined (BCM_HAWKEYE_SUPPORT)
   1079         if(SOC_IS_HAWKEYE(unit)) {
   1080             t = weights[0] | weights[1] | weights[2] | weights[3];
   1081         } else 
   1082 #endif /* BCM_HAWKEYE_SUPPORT*/
   1083         {
   1084             t = weights[0] | weights[1] | weights[2] | weights[3] |
   1085                 weights[4] | weights[5] | weights[6] | weights[7];
   1086         }
   1087 
   1088 #if defined (BCM_RAPTOR_SUPPORT)
   1089         if ((SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))) {
   1090             if ((t & ~0x7f) != 0) {
   1091                 return BCM_E_PARAM;
   1092             }
   1093         } else 
   1094 #endif 
   1095 #if defined (BCM_FIREBOLT2_SUPPORT)
   1096         if (SOC_IS_FIREBOLT2(unit)) {
   1097             if ((t & ~0xff) != 0) {
   1098                 return BCM_E_PARAM;
   1099             }
   1100         } else 
   1101 #endif
   1102         if ((t & ~0xf) != 0) {
   1103             return BCM_E_PARAM;
   1104         }
   1105         for(i = 0; i < NUM_COS(unit); i++) {
   1106             enc_weights[i] = weights[i];
   1107         }
   1108         break;
   1109     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   1110         mbits = 3;
   1111         if (soc_feature(unit, soc_feature_linear_drr_weight)) {
   1112             if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) ||
   1113                 SOC_IS_HAWKEYE(unit)) {
   1114 #if defined (BCM_RAPTOR_SUPPORT)
   1115                 MTUQuantaSel = _bcm_rp_cos_drr_weights_to_quanta(weights);
   1116                 if (MTUQuantaSel < 0) {
   1117                     return BCM_E_PARAM;
   1118                 }
   1119                 for (i = 0; i < NUM_COS(unit); i++) {
   1120                     if (weights[i]) {
   1121                         enc_weights[i] =
   1122                             _bcm_rp_cos_drr_kbytes_to_weight(weights[i],
   1123                                                              MTUQuantaSel);
   1124                     } else {
   1125                         enc_weights[i] = weights[i];
   1126                     }
   1127                 }
   1128 #endif
   1129             } else if (SOC_IS_FIREBOLT2(unit)) {
   1130 #if defined (BCM_FIREBOLT2_SUPPORT)
   1131                 MTUQuanta = _bcm_fb2_cos_drr_weights_to_quanta(weights);
   1132                 if (MTUQuanta < 0) {
   1133                     return BCM_E_PARAM;
   1134                 }
   1135                 for (i = 0; i < 8; i++) {
   1136                     if (weights[i]) {
   1137                         enc_weights[i] =
   1138                             _bcm_fb2_cos_drr_kbytes_to_weight(weights[i],
   1139                                                              MTUQuanta);
   1140                     } else {
   1141                         enc_weights[i] = weights[i];
   1142                     }
   1143 
   1144                 }
   1145 #endif
   1146             }
   1147         } else {
   1148             for(i = 0; i < 8; i++) {
   1149                 enc_weights[i] = _bcm_fb_cos_drr_kbytes_to_weight(weights[i]);
   1150             }
   1151         }
   1152 
   1153         break;
   1154     case BCM_COSQ_BOUNDED_DELAY:        /* not supported in xgs */
   1155     default:
   1156         return BCM_E_PARAM;
   1157     }
   1158 
   1159     PBMP_ITER(pbm, port) {
   1160         cosarbsel = 0;
   1161         soc_reg_field_set(unit, XQCOSARBSELr, &cosarbsel, COSARBf, mbits);
   1162         if ((mode == BCM_COSQ_DEFICIT_ROUND_ROBIN) &&
   1163             (soc_feature(unit, soc_feature_linear_drr_weight))) {
   1164 
   1165             if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit)) {
   1166 #if defined (BCM_RAPTOR_SUPPORT)
   1167                 soc_reg_field_set(unit, XQCOSARBSELr, &cosarbsel,
   1168                                   MTU_QUANTA_SELECTf, MTUQuantaSel);
   1169 #endif
   1170             } else if (SOC_IS_FIREBOLT2(unit)) {
   1171 #if defined (BCM_FIREBOLT2_SUPPORT)
   1172                 soc_reg_field_set(unit, XQCOSARBSELr, &cosarbsel,
   1173                                   MTU_QUANTAf, (MTUQuanta ==
   1174                                       BCM_FB2_MTU_QUANTA_LARGE) ? 1 : 0);
   1175 #endif
   1176             }
   1177         }
   1178         SOC_IF_ERROR_RETURN(WRITE_XQCOSARBSELr(unit, port, cosarbsel));
   1179     }
   1180 
   1181     if ((mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) ||
   1182         (mode == BCM_COSQ_DEFICIT_ROUND_ROBIN)) {
   1183         /*
   1184          * Weighted Fair Queueing scheduling among vaild COSs
   1185          */
   1186         PBMP_ITER(pbm, port) {
   1187 #if defined (BCM_RAPTOR_SUPPORT) || defined (BCM_FIREBOLT2_SUPPORT)
   1188             if (soc_feature(unit, soc_feature_linear_drr_weight)) {
   1189                 for (i = 0; i < NUM_COS(unit); i++) {
   1190                     SOC_IF_ERROR_RETURN(READ_WRRWEIGHT_COSr(unit, port,
   1191                                                             i, &wrr));
   1192     /*    coverity[uninit_use_in_call : FALSE]    */
   1193                     soc_reg_field_set(unit, WRRWEIGHT_COSr, &wrr,
   1194                                       WEIGHTf, enc_weights[i]);
   1195                     SOC_IF_ERROR_RETURN(WRITE_WRRWEIGHT_COSr(unit, port,
   1196                                                              i, wrr));
   1197                 }
   1198             } else
   1199 #endif
   1200             { /* Firebolt and Helix */
   1201                 SOC_IF_ERROR_RETURN(READ_WRRWEIGHTSr(unit, port, &wrr));
   1202                 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr,
   1203                                   COS0WEIGHTf, enc_weights[0]);
   1204                 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr,
   1205                                   COS1WEIGHTf, enc_weights[1]);
   1206                 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr,
   1207                                   COS2WEIGHTf, enc_weights[2]);
   1208                 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr,
   1209                                   COS3WEIGHTf, enc_weights[3]);
   1210                 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr,
   1211                                   COS4WEIGHTf, enc_weights[4]);
   1212                 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr,
   1213                                   COS5WEIGHTf, enc_weights[5]);
   1214                 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr,
   1215                                   COS6WEIGHTf, enc_weights[6]);
   1216                 soc_reg_field_set(unit, WRRWEIGHTSr, &wrr,
   1217                                   COS7WEIGHTf, enc_weights[7]);
   1218                 SOC_IF_ERROR_RETURN(WRITE_WRRWEIGHTSr(unit, port, wrr));
   1219             }
   1220         }
   1221     }
   1222 
   1223     return BCM_E_NONE;
   1224 }
   1225 
   1226 /*
   1227  * Function:
   1228  *      bcm_fb_cosq_port_sched_get
   1229  * Purpose:
   1230  *      Retrieve class-of-service policy and corresponding weights and delay
   1231  * Parameters:
   1232  *      unit     - StrataSwitch unit number.
   1233  *      pbm      - port bitmap
   1234  *      mode     - (output) Scheduling mode, one of BCM_COSQ_xxx
   1235  *      weights  - (output) Weights for each COS queue
   1236  *                          Only for BCM_COSQ_WEIGHTED_ROUND_ROBIN and
   1237  *                          BCM_COSQ_DEFICIT_ROUND_ROBIN mode.
   1238  *                 For DRR Weight is specified in Kbytes
   1239  *      delay    - This parameter is not used in 56504
   1240  * Returns:
   1241  *      BCM_E_XXX
   1242  * Notes:
   1243  *      Actually just returns data for the first port in the bitmap
   1244  */
   1245 
   1246 int
   1247 bcm_fb_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
   1248                               int *mode, int weights[], int *delay)
   1249 {
   1250     uint32              cosarbsel, wrr;
   1251     int                 mbits, port;
   1252 #if defined (BCM_RAPTOR_SUPPORT)
   1253     int                 MTUQuantaSel = -1;
   1254 #endif
   1255 #if defined (BCM_FIREBOLT2_SUPPORT)
   1256     int                 MTUQuanta = -1;
   1257 #endif
   1258 
   1259     mbits = -1;
   1260     PBMP_ITER(pbm, port) {
   1261         SOC_IF_ERROR_RETURN(READ_XQCOSARBSELr(unit, port, &cosarbsel));
   1262         mbits = soc_reg_field_get(unit, XQCOSARBSELr, cosarbsel, COSARBf);
   1263         if (soc_feature(unit, soc_feature_linear_drr_weight)) {
   1264             if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) ||
   1265                 SOC_IS_HAWKEYE(unit)) {
   1266 #if defined (BCM_RAPTOR_SUPPORT)
   1267                 MTUQuantaSel =
   1268                     soc_reg_field_get(unit, XQCOSARBSELr, cosarbsel,
   1269                                       MTU_QUANTA_SELECTf);
   1270 #endif
   1271             } else if (SOC_IS_FIREBOLT2(unit)) {
   1272 #if defined (BCM_FIREBOLT2_SUPPORT)
   1273                 MTUQuanta = soc_reg_field_get(unit, XQCOSARBSELr,
   1274                                               cosarbsel, MTU_QUANTAf) ?
   1275                     BCM_FB2_MTU_QUANTA_LARGE : BCM_FB2_MTU_QUANTA_SMALL;
   1276 #endif
   1277             }
   1278         }
   1279         break;
   1280     }
   1281 
   1282     switch (mbits) {
   1283     case 0:
   1284         *mode = BCM_COSQ_STRICT;
   1285         break;
   1286     case 1:
   1287         *mode = BCM_COSQ_ROUND_ROBIN;
   1288         break;
   1289     case 2:
   1290         *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
   1291         break;
   1292     case 3:
   1293         *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
   1294         break;
   1295     default:
   1296         return BCM_E_INTERNAL;
   1297     }
   1298 
   1299     if ((mbits == 2) || (mbits == 3)) {
   1300         wrr = 0;
   1301 #if defined (BCM_RAPTOR_SUPPORT) || defined (BCM_FIREBOLT2_SUPPORT)
   1302         if (soc_feature(unit, soc_feature_linear_drr_weight)) {
   1303             int i;
   1304 
   1305             PBMP_ITER(pbm, port) {
   1306                 for (i = 0; i < NUM_COS(unit); i++) {
   1307                     SOC_IF_ERROR_RETURN(READ_WRRWEIGHT_COSr(unit, port,
   1308                                                             i, &wrr));
   1309                     weights[i] = soc_reg_field_get(unit, WRRWEIGHT_COSr,
   1310                                                    wrr, WEIGHTf);
   1311                 }
   1312             }
   1313         } else
   1314 #endif
   1315         {
   1316             PBMP_ITER(pbm, port) {
   1317                 SOC_IF_ERROR_RETURN(READ_WRRWEIGHTSr(unit, port, &wrr));
   1318                 break;
   1319             }
   1320             weights[0] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS0WEIGHTf);
   1321             weights[1] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS1WEIGHTf);
   1322             weights[2] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS2WEIGHTf);
   1323             weights[3] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS3WEIGHTf);
   1324             weights[4] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS4WEIGHTf);
   1325             weights[5] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS5WEIGHTf);
   1326             weights[6] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS6WEIGHTf);
   1327             weights[7] = soc_reg_field_get(unit, WRRWEIGHTSr, wrr, COS7WEIGHTf);
   1328         }
   1329         if (mbits == 3) {
   1330             int i;
   1331             for(i = 0; i < NUM_COS(unit); i++) {
   1332                 if (soc_feature(unit, soc_feature_linear_drr_weight)) {
   1333                     if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) ||
   1334                         SOC_IS_HAWKEYE(unit)) {
   1335 #if defined (BCM_RAPTOR_SUPPORT)
   1336                         weights[i] =
   1337                             _bcm_rp_cos_drr_weight_to_kbytes(weights[i],
   1338                                                              MTUQuantaSel);
   1339 #endif
   1340                     } else if (SOC_IS_FIREBOLT2(unit)) {
   1341 #if defined (BCM_FIREBOLT2_SUPPORT)
   1342                         weights[i] *= MTUQuanta;
   1343 #endif
   1344                     }
   1345                 } else {
   1346                     weights[i] =
   1347                         _bcm_fb_cos_drr_weight_to_kbytes(weights[i]);
   1348                 }
   1349             }
   1350         }
   1351     }
   1352 
   1353     if (delay) {
   1354         *delay = 0;
   1355     }
   1356     return BCM_E_NONE;
   1357 }
   1358 
   1359 /*
   1360  * Function:
   1361  *      bcm_fb_cosq_sched_weight_max_get
   1362  * Purpose:
   1363  *      Retrieve maximum weights for given COS policy.
   1364  * Parameters:
   1365  *      unit - StrataSwitch unit number.
   1366  *      mode - Scheduling mode, one of BCM_COSQ_xxx
   1367  *      weight_max - (output) Maximum weight for COS queue.
   1368  *              For DRR mode Weight is specified in Kbytes
   1369  *              0 if mode is BCM_COSQ_STRICT.
   1370  *              1 if mode is BCM_COSQ_ROUND_ROBIN.
   1371  *              -1 if not applicable to mode.
   1372  * Returns:
   1373  *      BCM_E_XXX
   1374  */
   1375 
   1376 int
   1377 bcm_fb_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
   1378 {
   1379     switch (mode) {
   1380     case BCM_COSQ_STRICT:
   1381         *weight_max = BCM_COSQ_WEIGHT_STRICT;
   1382         break;
   1383     case BCM_COSQ_ROUND_ROBIN:
   1384         *weight_max = BCM_COSQ_WEIGHT_MIN;
   1385         break;
   1386     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
   1387         *weight_max = FB_WRR_WEIGHT_MAX;
   1388         break;
   1389     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
   1390         if (soc_feature(unit, soc_feature_linear_drr_weight)) {
   1391             if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) ||
   1392                 SOC_IS_HAWKEYE(unit)) {
   1393 #if defined (BCM_RAPTOR_SUPPORT)
   1394                 *weight_max = BCM_COS_WEIGHT_MAX *
   1395                     MTU_Quanta[BCM_MTU_QUANTA_ID_COUNT - 1];
   1396 #endif
   1397             } else if (SOC_IS_FIREBOLT2(unit)) {
   1398 #if defined (BCM_FIREBOLT2_SUPPORT)
   1399                 *weight_max =
   1400                     BCM_FB2_COS_WEIGHT_MAX * BCM_FB2_MTU_QUANTA_LARGE;
   1401 #endif
   1402             }
   1403         } else {
   1404             *weight_max =
   1405                 _bcm_fb_cos_drr_weight_to_kbytes(FB_DRR_WEIGHT_MAX);
   1406         }
   1407         break;
   1408     default:
   1409         *weight_max = BCM_COSQ_WEIGHT_UNLIMITED;
   1410         return BCM_E_PARAM;
   1411     }
   1412 
   1413     return BCM_E_NONE;
   1414 }
   1415 
   1416 #define FB2_GRANULARITY_NUM      3 
   1417 #define FB_BW_GRANULARITY        64
   1418 #define FB_BW_FIELD_MAX          0x3ffff
   1419 
   1420 int
   1421 bcm_fb_cosq_port_bandwidth_set(int unit, bcm_port_t port,
   1422                                bcm_cos_queue_t cosq,
   1423                                uint32 kbits_sec_min,
   1424                                uint32 kbits_sec_max,
   1425                                uint32 kbits_sec_burst,
   1426                                uint32 flags)
   1427 {
   1428     uint32 refresh_rate;
   1429     uint32 regval;
   1430     uint32 bucket_val, regindex;
   1431 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   1432     int    refresh_bitsize, bucket_bitsize;
   1433     uint32 bucketsize, granularity = 3, meter_flags = 0;
   1434 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1435 
   1436     if (soc_feature(unit,soc_feature_bucket_support)) {
   1437         /*
   1438          * To set the new Bandwidth settings, the procedure adopted is
   1439          * a. reset MAXBUCKETCONFIG, MINBUCKETCONFIG, MAXBUCKET,MINBUCKET
   1440          * b. update MAXBUCKETCONFIG and MINBUCKETCONFIG with new values passed
   1441          * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it.
   1442          */
   1443 
   1444 #if defined (BCM_FIREBOLT2_SUPPORT)
   1445         if (SOC_IS_FIREBOLT2(unit)) {
   1446             BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
   1447             if (soc_reg_field_get(unit, MISCCONFIGr,
   1448                                   regval, ITU_MODE_SELf)) {
   1449                 meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1450             }
   1451         }
   1452 #endif
   1453 
   1454         BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIGr(unit, port, cosq, &regval));
   1455 
   1456         /* Disable egress metering for this port */
   1457         soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval, MAX_REFRESHf, 0);
   1458         soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval, MAX_THD_SELf, 0);
   1459         BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETCONFIGr(unit, port, cosq, regval));
   1460 
   1461 #if defined(BCM_HAWKEYE_SUPPORT)
   1462         if (SOC_IS_HAWKEYE(unit)) {
   1463             switch (cosq) {
   1464                 case 0:	BCM_IF_ERROR_RETURN
   1465                             (WRITE_MINBUCKETCOS0CONFIGr(unit, port, 0));
   1466                         break;
   1467                 case 1:	BCM_IF_ERROR_RETURN
   1468                             (WRITE_MINBUCKETCOS1CONFIGr(unit, port, 0));
   1469                         break;
   1470                 case 2:	BCM_IF_ERROR_RETURN
   1471                             (WRITE_MINBUCKETCOS2CONFIGr(unit, port, 0)); 
   1472                         break;
   1473                 case 3:	BCM_IF_ERROR_RETURN
   1474                             (WRITE_MINBUCKETCOS3CONFIGr(unit, port, 0));
   1475                         break;
   1476                 default:	return BCM_E_PARAM;
   1477             }
   1478         } else
   1479 #endif /* BCM_HAWKEYE_SUPPORT */
   1480         {
   1481             BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIGr(unit, port, cosq, &regval));
   1482             soc_reg_field_set(unit, MINBUCKETCONFIGr, &regval, MIN_REFRESHf, 0);
   1483 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   1484             if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit)) {
   1485                 soc_reg_field_set(unit, MINBUCKETCONFIGr,
   1486                                   &regval, MIN_THD_SELf, 0);
   1487             } else
   1488 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1489             {
   1490                 soc_reg_field_set(unit, MINBUCKETCONFIGr,
   1491                                   &regval, MIN_HI_THD_SELf, 0);
   1492                 soc_reg_field_set(unit, MINBUCKETCONFIGr,
   1493                                   &regval, MIN_LO_THD_SELf, 0);
   1494             }
   1495             BCM_IF_ERROR_RETURN(WRITE_MINBUCKETCONFIGr(unit, port, cosq, regval));
   1496         }
   1497         /*reset the MAXBUCKET register*/
   1498         bucket_val = 0;
   1499         soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, MAX_BUCKETf,0);
   1500         soc_reg_field_set(unit, MAXBUCKETr, &bucket_val, IN_PROFILE_FLAGf,1);
   1501         BCM_IF_ERROR_RETURN(WRITE_MAXBUCKETr(unit, port, cosq, bucket_val));
   1502 
   1503         /*reset the MINBUCKET register value*/
   1504         bucket_val = 0;
   1505         soc_reg_field_set(unit, MINBUCKETr, &bucket_val, MIN_BUCKETf,0);
   1506         soc_reg_field_set(unit, MINBUCKETr, &bucket_val, IN_PROFILE_FLAGf,0);
   1507         BCM_IF_ERROR_RETURN(WRITE_MINBUCKETr(unit, port, cosq, bucket_val));
   1508 
   1509         regval = 0;
   1510 #if defined(BCM_HAWKEYE_SUPPORT)
   1511         if (SOC_IS_HAWKEYE(unit)) {
   1512             switch (cosq) {
   1513                 case 0:	regindex = MINBUCKETCOS0CONFIGr; break;
   1514                 case 1:	regindex = MINBUCKETCOS1CONFIGr; break;
   1515                 case 2:	regindex = MINBUCKETCOS2CONFIGr; break;
   1516                 case 3:	regindex = MINBUCKETCOS3CONFIGr; break;
   1517                 default:	return BCM_E_PARAM;
   1518             }
   1519         } else
   1520 #endif /* BCM_HAWKEYE_SUPPORT */
   1521         {
   1522             regindex = MINBUCKETCONFIGr;
   1523         }
   1524 
   1525         
   1526 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   1527         if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) ||
   1528             SOC_IS_HAWKEYE(unit)) {
   1529             refresh_bitsize =
   1530                 soc_reg_field_length(unit, regindex, MIN_REFRESHf);
   1531             bucket_bitsize =
   1532                 soc_reg_field_length(unit, regindex, MIN_THD_SELf);
   1533 
   1534             BCM_IF_ERROR_RETURN
   1535                 (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_min,
   1536                                                    kbits_sec_min,
   1537                           meter_flags, refresh_bitsize, bucket_bitsize,
   1538                           &refresh_rate, &bucketsize, &granularity));
   1539 
   1540             /* regval has MINBUCKETCONFIGr value */
   1541             soc_reg_field_set(unit, regindex, &regval,
   1542                               MIN_REFRESHf, refresh_rate);
   1543             soc_reg_field_set(unit, regindex,
   1544                               &regval, MIN_THD_SELf, bucketsize);
   1545             if (soc_reg_field_valid(unit, regindex, METER_GRANf)) {
   1546                 soc_reg_field_set(unit, regindex, &regval,
   1547                                   METER_GRANf, granularity);
   1548             }
   1549         } else
   1550 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1551         {
   1552             /* Check kbits_sec_min upper limit prior to "granularization" */
   1553             if (kbits_sec_min > (0xFFFFFFFF - (FB_BW_GRANULARITY - 1)) ) {
   1554                 kbits_sec_min = (0xFFFFFFFF - (FB_BW_GRANULARITY - 1));
   1555             }
   1556 
   1557             refresh_rate =
   1558                 (kbits_sec_min + (FB_BW_GRANULARITY - 1)) /
   1559                 FB_BW_GRANULARITY;
   1560             if (refresh_rate > FB_BW_FIELD_MAX) {
   1561                 refresh_rate = FB_BW_FIELD_MAX;
   1562             }
   1563 
   1564             /* regval has MINBUCKETCONFIGr value */
   1565             soc_reg_field_set(unit, regindex, &regval,
   1566                               MIN_REFRESHf, refresh_rate);
   1567             soc_reg_field_set(unit, regindex,
   1568                               &regval, MIN_HI_THD_SELf,
   1569                               _bcm_fb_kbits_to_bucketsize(kbits_sec_min));
   1570             soc_reg_field_set(unit, regindex,
   1571                               &regval, MIN_LO_THD_SELf,
   1572                               _bcm_fb_kbits_to_bucketsize(kbits_sec_min/2));
   1573         }
   1574 #if defined(BCM_HAWKEYE_SUPPORT)
   1575         if (SOC_IS_HAWKEYE(unit)) {
   1576             switch (cosq) {
   1577                 case 0:	BCM_IF_ERROR_RETURN
   1578                             (WRITE_MINBUCKETCOS0CONFIGr(unit, port, regval));
   1579                         break;
   1580                 case 1:	BCM_IF_ERROR_RETURN
   1581                             (WRITE_MINBUCKETCOS1CONFIGr(unit, port, regval));
   1582                         break;
   1583                 case 2:	BCM_IF_ERROR_RETURN
   1584                             (WRITE_MINBUCKETCOS2CONFIGr(unit, port, regval)); 
   1585                         break;
   1586                 case 3:	BCM_IF_ERROR_RETURN
   1587                             (WRITE_MINBUCKETCOS3CONFIGr(unit, port, regval));
   1588                         break;
   1589                 default:	return BCM_E_PARAM;
   1590             }
   1591 	} else
   1592 #endif /* BCM_HAWKEYE_SUPPORT */
   1593 	{
   1594             BCM_IF_ERROR_RETURN
   1595                 (WRITE_MINBUCKETCONFIGr(unit, port, cosq, regval));
   1596         }
   1597         regval=0;
   1598 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   1599         if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) ||
   1600             SOC_IS_HAWKEYE(unit)) {
   1601             refresh_bitsize =
   1602                 soc_reg_field_length(unit, MAXBUCKETCONFIGr, MAX_REFRESHf);
   1603             bucket_bitsize =
   1604                 soc_reg_field_length(unit, MAXBUCKETCONFIGr, MAX_THD_SELf);
   1605 
   1606             BCM_IF_ERROR_RETURN
   1607                 (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec_max,
   1608                                                    kbits_sec_burst,
   1609                           meter_flags, refresh_bitsize, bucket_bitsize,
   1610                           &refresh_rate, &bucketsize, &granularity));
   1611 
   1612             /* regval has MAXBUCKETCONFIGr value */
   1613             soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval,
   1614                               MAX_REFRESHf, refresh_rate);
   1615             soc_reg_field_set(unit, MAXBUCKETCONFIGr,
   1616                               &regval, MAX_THD_SELf, bucketsize);
   1617             if (soc_reg_field_valid(unit, MAXBUCKETCONFIGr, METER_GRANf)) {
   1618                 soc_reg_field_set(unit, MAXBUCKETCONFIGr,
   1619                                   &regval, METER_GRANf, granularity);
   1620             }
   1621         } else
   1622 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1623         {
   1624             /* Check kbits_sec_min upper limit prior to "granularization" */
   1625             if (kbits_sec_max > (0xFFFFFFFF - (FB_BW_GRANULARITY - 1)) ) {
   1626                 kbits_sec_max = (0xFFFFFFFF - (FB_BW_GRANULARITY - 1));
   1627             }
   1628 
   1629             refresh_rate =
   1630                 (kbits_sec_max + (FB_BW_GRANULARITY - 1)) /
   1631                 FB_BW_GRANULARITY;
   1632             if (refresh_rate > FB_BW_FIELD_MAX) {
   1633                 refresh_rate = FB_BW_FIELD_MAX;
   1634             }
   1635 
   1636             /* regval has MAXBUCKETCONFIGr value */
   1637             soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval,
   1638                               MAX_REFRESHf, refresh_rate);
   1639             soc_reg_field_set(unit, MAXBUCKETCONFIGr, &regval, MAX_THD_SELf,
   1640                               _bcm_fb_kbits_to_bucketsize(kbits_sec_burst));
   1641         }
   1642         BCM_IF_ERROR_RETURN
   1643             (WRITE_MAXBUCKETCONFIGr(unit, port, cosq, regval));
   1644 
   1645         /* MISCCONFIG.METERING_CLK_EN is set by chip init */
   1646 
   1647         return BCM_E_NONE;
   1648     } else {
   1649         return BCM_E_UNAVAIL;
   1650     }
   1651 
   1652 }
   1653 
   1654 int
   1655 bcm_fb_cosq_port_bandwidth_get(int unit, bcm_port_t port,
   1656                                bcm_cos_queue_t cosq,
   1657                                uint32 *kbits_sec_min,
   1658                                uint32 *kbits_sec_max,
   1659                                uint32 *kbits_sec_burst,
   1660                                uint32 *flags)
   1661 {
   1662     uint32 regval, regindex, refresh_rate;
   1663     uint32 bucketsize = 0;
   1664 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   1665     uint32 kbits_burst, meter_flags = 0;
   1666 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1667 
   1668     if (soc_feature(unit,soc_feature_bucket_support)){
   1669 
   1670         if (!kbits_sec_min || !kbits_sec_max || !flags) {
   1671             return (BCM_E_PARAM);
   1672         }
   1673 
   1674 #if defined (BCM_FIREBOLT2_SUPPORT)
   1675         if (SOC_IS_FIREBOLT2(unit)) {
   1676             BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &regval));
   1677             if (soc_reg_field_get(unit, MISCCONFIGr,
   1678                                   regval, ITU_MODE_SELf)) {
   1679                 meter_flags |= _BCM_XGS_METER_FLAG_NON_LINEAR;
   1680             }
   1681         }
   1682 #endif
   1683 
   1684         BCM_IF_ERROR_RETURN(READ_MAXBUCKETCONFIGr(unit, port, cosq, &regval));
   1685         refresh_rate =
   1686             soc_reg_field_get(unit, MAXBUCKETCONFIGr, regval, MAX_REFRESHf);
   1687 
   1688 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   1689         if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) ||
   1690             SOC_IS_HAWKEYE(unit)) {
   1691             bucketsize =
   1692                 soc_reg_field_get(unit, MAXBUCKETCONFIGr,
   1693                                   regval, MAX_THD_SELf);
   1694             BCM_IF_ERROR_RETURN
   1695                 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize,
   1696                                                    FB2_GRANULARITY_NUM,
   1697                                                    meter_flags,
   1698                                                    kbits_sec_max,
   1699                                                    kbits_sec_burst));
   1700         } else
   1701 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1702         {
   1703             bucketsize =
   1704                 soc_reg_field_get(unit, MAXBUCKETCONFIGr,
   1705                                   regval, MAX_THD_SELf);
   1706             /* Convert the REFRESH field to kbits/sec (1000 bits/sec). */
   1707             *kbits_sec_max = FB_BW_GRANULARITY * refresh_rate;
   1708             *kbits_sec_burst = _bcm_fb_bucketsize_to_kbits(bucketsize);
   1709         }
   1710 
   1711 #if defined(BCM_HAWKEYE_SUPPORT)
   1712         if (SOC_IS_HAWKEYE(unit)) {
   1713             switch (cosq) {
   1714                 case 0:	regindex = MINBUCKETCOS0CONFIGr;
   1715                         BCM_IF_ERROR_RETURN
   1716                             (READ_MINBUCKETCOS0CONFIGr(unit, port, &regval));
   1717                         break;
   1718                 case 1:	regindex = MINBUCKETCOS1CONFIGr;
   1719                         BCM_IF_ERROR_RETURN
   1720                             (READ_MINBUCKETCOS1CONFIGr(unit, port, &regval));
   1721                         break;
   1722                 case 2:	regindex = MINBUCKETCOS2CONFIGr;
   1723                         BCM_IF_ERROR_RETURN
   1724                             (READ_MINBUCKETCOS2CONFIGr(unit, port, &regval)); 
   1725                         break;
   1726                 case 3:	regindex = MINBUCKETCOS3CONFIGr;
   1727                         BCM_IF_ERROR_RETURN
   1728                             (READ_MINBUCKETCOS3CONFIGr(unit, port, &regval));
   1729                         break;
   1730                 default:	return BCM_E_PARAM;
   1731             }
   1732         } else
   1733 #endif /* BCM_HAWKEYE_SUPPORT */
   1734         {
   1735             regindex = MINBUCKETCONFIGr;
   1736             BCM_IF_ERROR_RETURN(READ_MINBUCKETCONFIGr(unit, port, cosq, &regval));
   1737         }
   1738 
   1739         refresh_rate =
   1740             soc_reg_field_get(unit, regindex, regval, MIN_REFRESHf);
   1741 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   1742         if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) ||
   1743             SOC_IS_HAWKEYE(unit)) {
   1744             BCM_IF_ERROR_RETURN
   1745                 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, 0,
   1746                                                    FB2_GRANULARITY_NUM,
   1747                                                    meter_flags,
   1748                                                    kbits_sec_min,
   1749                                                    &kbits_burst));
   1750         } else
   1751 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */
   1752         {
   1753         /* Convert the REFRESH field to kbits/sec (1000 bits/sec). */
   1754             *kbits_sec_min = FB_BW_GRANULARITY * refresh_rate;
   1755         }
   1756 
   1757         *flags = 0;
   1758 
   1759         return BCM_E_NONE;
   1760     } else {
   1761         return BCM_E_UNAVAIL;
   1762     }
   1763 }
   1764 
   1765 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT)
   1766 /*      
   1767  *  Convert HW drop probability to percent value
   1768  */     
   1769 STATIC int       
   1770 _bcm_rv_hw_drop_prob_to_api_val[] = {
   1771     1000,  /* 0  */
   1772     125,   /* 1  */
   1773     63,    /* 2  */
   1774     31,    /* 3  */
   1775     16,    /* 4  */
   1776     8,     /* 5  */
   1777     4,     /* 6  */
   1778     2,     /* 7  */
   1779 };
   1780 
   1781 STATIC int
   1782 _bcm_rv_api_val_to_hw_drop_prob(int api_val) {
   1783    int i;
   1784    for (i = 7; i > 0 ; i--) {
   1785       if (api_val <= _bcm_rv_hw_drop_prob_to_api_val[i]) {
   1786           break;
   1787       }
   1788    }
   1789    return i;
   1790 }
   1791 
   1792 STATIC soc_field_t
   1793 _cosfld[] = {
   1794                 COS0THDMODEf,
   1795                 COS1THDMODEf,
   1796                 COS2THDMODEf,
   1797                 COS3THDMODEf,
   1798                 COS4THDMODEf,
   1799                 COS5THDMODEf,
   1800                 COS6THDMODEf,
   1801                 COS7THDMODEf,
   1802             };
   1803 
   1804 STATIC int
   1805 bcm_rv_cosq_discard_port_set(int unit, bcm_port_t port,
   1806                              bcm_cos_queue_t cosq,
   1807                              uint32 color,
   1808                              int drop_start,
   1809                              int drop_slope)
   1810 {
   1811     bcm_port_t local_port;
   1812     bcm_pbmp_t pbmp;
   1813     int i, cosq_start, num_cosq;
   1814     uint32 min_thresh, n;
   1815     uint32 rval, encoding;
   1816     soc_reg_t reg;
   1817     soc_field_t fld;
   1818 
   1819     if (drop_start < 0 || drop_start > 100 || drop_slope > 0) {
   1820         return BCM_E_PARAM;
   1821     }
   1822 
   1823     if (BCM_GPORT_IS_SET(port)) {
   1824         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &local_port));
   1825         BCM_PBMP_PORT_SET(pbmp, local_port);
   1826     } else {
   1827         if (port == -1) {
   1828             BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
   1829         } else if (!SOC_PORT_VALID(unit, port)) {
   1830             return BCM_E_PORT;
   1831         } else {
   1832             BCM_PBMP_PORT_SET(pbmp, port);
   1833         }
   1834     }
   1835 
   1836     if (cosq < -1 || cosq >= _num_cosq[unit]) {
   1837         return BCM_E_PARAM;
   1838     } else if (cosq == -1) {
   1839         cosq_start = 0;
   1840         num_cosq = _num_cosq[unit];
   1841     } else {
   1842         cosq_start = cosq;
   1843         num_cosq = 1;
   1844     }
   1845 
   1846     BCM_PBMP_ITER(pbmp, local_port) {
   1847         for (i = cosq_start; i < (cosq_start + num_cosq); i++) {
   1848             /* Get the start point as a function of the HOL limit */
   1849             SOC_IF_ERROR_RETURN
   1850                 (READ_HOLCOSPKTSETLIMITr(unit, local_port, i, &rval));
   1851             n = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, rval,
   1852                                   PKTSETLIMITf);
   1853             min_thresh = drop_start * n / 100;
   1854 
   1855             /* Set the drop rate depending on the color */
   1856             if (color == BCM_COSQ_DISCARD_COLOR_GREEN) {
   1857                 reg = CNG1COSDROPRATEr;
   1858             } else {
   1859                 reg = CNG0COSDROPRATEr;
   1860             }
   1861             BCM_IF_ERROR_RETURN
   1862                 (soc_reg32_read(unit, soc_reg_addr
   1863                                 (unit, reg, local_port, i), &rval));
   1864             encoding = _bcm_rv_api_val_to_hw_drop_prob(-1 * drop_slope);
   1865             soc_reg_field_set(unit, reg, &rval, DROPRATEf, encoding);
   1866             BCM_IF_ERROR_RETURN
   1867                 (soc_reg32_write(unit, soc_reg_addr
   1868                                  (unit, reg, local_port, i), rval));
   1869             /* Enable simple RED for the (port, cos) pair */
   1870             BCM_IF_ERROR_RETURN
   1871                 (soc_reg_field32_modify(unit, SIMPLEREDCONFIGr, local_port,
   1872                                         _cosfld[i], 1));
   1873 
   1874             /* Set the drop threshold depending on the color */
   1875             if (color == BCM_COSQ_DISCARD_COLOR_GREEN) {
   1876                 reg = CNGCOSPKTLIMIT1r;
   1877                 fld = CNGPKTSETLIMIT1f;
   1878             } else {
   1879                 reg = CNGCOSPKTLIMIT0r;
   1880                 fld = CNGPKTSETLIMIT0f;
   1881             }
   1882             soc_reg_field_set(unit, reg, &rval, fld, min_thresh);
   1883             BCM_IF_ERROR_RETURN
   1884                 (soc_reg32_write(unit, soc_reg_addr
   1885                                  (unit, reg, local_port, i), rval));
   1886         }
   1887         /* For Firebolt 2, also match the cell limits to the drop percentage.
   1888          * Dynamic cell usage is enabled by default */
   1889 #if defined(BCM_FIREBOLT2_SUPPORT)
   1890         if (SOC_IS_FIREBOLT2(unit)) {
   1891             /* Fraction of per-port DYNCELLLIMIT */
   1892             BCM_IF_ERROR_RETURN(READ_DYNCELLLIMITr(unit, local_port, &rval));
   1893             n = soc_reg_field_get(unit, DYNCELLLIMITr, rval, DYNCELLSETLIMITf);
   1894             min_thresh = drop_start * n / 100;
   1895             /* Set the drop threshold depending on the color */
   1896             if (color == BCM_COSQ_DISCARD_COLOR_GREEN) {
   1897                 reg = CNGDYNCELLLIMIT1r;
   1898                 fld = CNGDYNCELLLIMITf;
   1899             } else {
   1900                 reg = CNGDYNCELLLIMIT0r;
   1901                 fld = CNGDYNCELLLIMITf;
   1902             }
   1903             soc_reg_field_set(unit, reg, &rval, fld, min_thresh);
   1904             BCM_IF_ERROR_RETURN
   1905                 (soc_reg32_write(unit, soc_reg_addr
   1906                                  (unit, reg, local_port, 0), rval));
   1907         }
   1908 #endif
   1909     }
   1910     return BCM_E_NONE;
   1911 }
   1912 
   1913 STATIC int
   1914 bcm_rv_cosq_discard_port_get(int unit, bcm_port_t port,
   1915                              bcm_cos_queue_t cosq,
   1916                              uint32 color,
   1917                              int *drop_start,
   1918                              int *drop_slope)
   1919 {
   1920     bcm_port_t local_port;
   1921     bcm_pbmp_t pbmp;
   1922     uint32 rval, n;
   1923 
   1924     if (drop_start == NULL || drop_slope == NULL) {
   1925         return BCM_E_PARAM;
   1926     }
   1927 
   1928     if (BCM_GPORT_IS_SET(port)) {
   1929         BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, port, &local_port));
   1930         BCM_PBMP_PORT_SET(pbmp, local_port);
   1931     } else {
   1932         if (port == -1) {
   1933             BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
   1934         } else if (!SOC_PORT_VALID(unit, port)) {
   1935             return BCM_E_PORT;
   1936         } else {
   1937             BCM_PBMP_PORT_SET(pbmp, port);
   1938         }
   1939     }
   1940     if (cosq < -1 || cosq >= _num_cosq[unit]) {
   1941         return BCM_E_PARAM;
   1942     } else if (cosq == -1) {
   1943         cosq = 0;
   1944     }
   1945    
   1946     BCM_PBMP_ITER(pbmp, local_port) {
   1947         /* Get the total HOL limit first */
   1948         BCM_IF_ERROR_RETURN
   1949             (READ_HOLCOSPKTSETLIMITr(unit, local_port, cosq, &rval));
   1950         n = soc_reg_field_get(unit, HOLCOSPKTSETLIMITr, rval, PKTSETLIMITf);
   1951 
   1952         /* Get the simple RED mode */
   1953         BCM_IF_ERROR_RETURN(READ_SIMPLEREDCONFIGr(unit, local_port, &rval));
   1954         if (soc_reg_field_get(unit, SIMPLEREDCONFIGr, rval, _cosfld[cosq])) {
   1955             if (color == BCM_COSQ_DISCARD_COLOR_GREEN) {
   1956                 BCM_IF_ERROR_RETURN
   1957                     (READ_CNGCOSPKTLIMIT1r(unit, local_port, cosq, &rval));
   1958                 *drop_start = soc_reg_field_get(unit, CNGCOSPKTLIMIT1r, rval, 
   1959                                                 CNGPKTSETLIMIT1f) * 100 / n; 
   1960                 BCM_IF_ERROR_RETURN
   1961                     (READ_CNG1COSDROPRATEr(unit, local_port, cosq, &rval));
   1962                 *drop_slope = -1 * _bcm_rv_hw_drop_prob_to_api_val[rval];
   1963             } else {
   1964                 BCM_IF_ERROR_RETURN
   1965                     (READ_CNGCOSPKTLIMIT0r(unit, local_port, cosq, &rval));
   1966                 *drop_start = soc_reg_field_get(unit, CNGCOSPKTLIMIT0r, rval, 
   1967                                                 CNGPKTSETLIMIT0f) * 100 / n; 
   1968                 BCM_IF_ERROR_RETURN
   1969                     (READ_CNG0COSDROPRATEr(unit, local_port, cosq, &rval));
   1970                 *drop_slope = -1 * _bcm_rv_hw_drop_prob_to_api_val[rval];
   1971             }
   1972         }
   1973         break;
   1974     }
   1975     return BCM_E_NONE;
   1976 }
   1977 #endif
   1978 
   1979 int
   1980 bcm_fb_cosq_discard_set(int unit, uint32 flags)
   1981 {
   1982     return BCM_E_UNAVAIL;
   1983 }
   1984 
   1985 int
   1986 bcm_fb_cosq_discard_get(int unit, uint32 *flags)
   1987 {
   1988     return BCM_E_UNAVAIL;
   1989 }
   1990 
   1991 int
   1992 bcm_fb_cosq_discard_port_set(int unit, bcm_port_t port,
   1993                              bcm_cos_queue_t cosq,
   1994                              uint32 color,
   1995                              int drop_start,
   1996                              int drop_slope,
   1997                              int average_time)
   1998 {
   1999     int rv = BCM_E_UNAVAIL;
   2000 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT)
   2001     if (SOC_IS_RAVEN(unit) || SOC_IS_FIREBOLT2(unit)) {
   2002         rv = bcm_rv_cosq_discard_port_set(unit, port, cosq, color, 
   2003                                           drop_start, drop_slope);
   2004     }
   2005 #if defined(BCM_FIREBOLT2_SUPPORT)
   2006     /* For Firebolt 2, also match the cell limits to the drop percentage. 
   2007      * Dynamic cell usage is enabled by default. */
   2008     if (BCM_SUCCESS(rv) && SOC_IS_FIREBOLT2(unit)) {
   2009         uint32 min_thresh, n, rval;
   2010         soc_reg_t reg;
   2011         soc_field_t fld;
   2012         /* Fraction of TOTALDYNCELLLIMIT */
   2013         BCM_IF_ERROR_RETURN(READ_TOTALDYNCELLLIMITr(unit, &rval));
   2014         n = soc_reg_field_get(unit, TOTALDYNCELLLIMITr, rval, SETLIMITf);
   2015         min_thresh = drop_start * n / 100;                  
   2016         /* Set the drop threshold depending on the color */ 
   2017         if (color == BCM_COSQ_DISCARD_COLOR_GREEN) {
   2018             reg = CNGTOTALDYNCELLLIMIT1r;
   2019             fld = CNGTOTALDYNCELLLIMITf;
   2020         } else {
   2021             reg = CNGTOTALDYNCELLLIMIT0r;
   2022             fld = CNGTOTALDYNCELLLIMITf;
   2023         }
   2024         soc_reg_field_set(unit, reg, &rval, fld, min_thresh);
   2025         BCM_IF_ERROR_RETURN
   2026             (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));     
   2027     }
   2028 #endif
   2029 #endif
   2030     return rv;
   2031 }
   2032 
   2033 int
   2034 bcm_fb_cosq_discard_port_get(int unit, bcm_port_t port,
   2035                              bcm_cos_queue_t cosq,
   2036                              uint32 color,
   2037                              int *drop_start,
   2038                              int *drop_slope,
   2039                              int *average_time)
   2040 {
   2041     int rv = BCM_E_UNAVAIL;
   2042 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT)
   2043     if (SOC_IS_RAVEN(unit) || SOC_IS_FIREBOLT2(unit)) {
   2044         rv = bcm_rv_cosq_discard_port_get(unit, port, cosq, color, 
   2045                                           drop_start, drop_slope);
   2046     }
   2047 #endif
   2048     return rv;
   2049 }
   2050 
   2051 int
   2052 bcm_fb_cosq_detach(int unit, int software_state_only)
   2053 {
   2054     return BCM_E_NONE;
   2055 }
   2056 #endif /* BCM_FIREBOLT_SUPPORT */
   2057 
   2058 /*
   2059  * Function:
   2060  *      bcm_fb_er_cosq_mapping_set
   2061  * Purpose:
   2062  *      Set which cosq a given priority should fall into
   2063  * Parameters:
   2064  *      unit - StrataSwitch unit number.
   2065  *      priority - Priority value to map
   2066  *      cosq - COS queue to map to
   2067  * Returns:
   2068  *      BCM_E_XXX
   2069  */
   2070 
   2071 int
   2072 bcm_fb_er_cosq_mapping_set(int unit, bcm_port_t port,
   2073                            bcm_cos_t priority, bcm_cos_queue_t cosq)
   2074 {
   2075     uint32 cval32, oval32;
   2076     soc_field_t f;
   2077     bcm_pbmp_t ports;
   2078 
   2079     switch (priority) {
   2080     case 0:	f = COS0f; break;
   2081     case 1:	f = COS1f; break;
   2082     case 2:	f = COS2f; break;
   2083     case 3:	f = COS3f; break;
   2084     case 4:	f = COS4f; break;
   2085     case 5:	f = COS5f; break;
   2086     case 6:	f = COS6f; break;
   2087     case 7:	f = COS7f; break;
   2088     default:	return BCM_E_PARAM;
   2089     }
   2090 
   2091     if (cosq < 0 || cosq >= NUM_COS(unit)) {
   2092         return (BCM_E_PARAM);
   2093     }
   2094 
   2095     if (port == -1) {	/* all ports */
   2096 	BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
   2097     } else if (SOC_PORT_VALID(unit, port) && IS_ALL_PORT(unit, port)) {
   2098 	BCM_PBMP_CLEAR(ports);
   2099 	BCM_PBMP_PORT_ADD(ports, port);
   2100     } else {
   2101 	return BCM_E_PORT;
   2102     }
   2103 
   2104     PBMP_ITER(ports, port) {
   2105 	SOC_IF_ERROR_RETURN(READ_COS_SELr(unit, port, &cval32));
   2106 	oval32 = cval32;
   2107 	soc_reg_field_set(unit, COS_SELr, &cval32, f, cosq);
   2108 	if (cval32 != oval32) {
   2109 	    SOC_IF_ERROR_RETURN(WRITE_COS_SELr(unit, port, cval32));
   2110 	}
   2111 	if (port == CMIC_PORT(unit)) {
   2112 	    SOC_IF_ERROR_RETURN(READ_CPU_COS_SELr(unit, &cval32));
   2113 	    oval32 = cval32;
   2114 	    soc_reg_field_set(unit, CPU_COS_SELr, &cval32, f, cosq);
   2115 	    if (cval32 != oval32) {
   2116 		SOC_IF_ERROR_RETURN(WRITE_CPU_COS_SELr(unit, cval32));
   2117 	    }
   2118 	}
   2119 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
   2120 	if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
   2121 	    SOC_IF_ERROR_RETURN(READ_ICOS_SELr(unit, port, &cval32));
   2122 	    oval32 = cval32;
   2123 	    soc_reg_field_set(unit, ICOS_SELr, &cval32, f, cosq);
   2124 	    if (cval32 != oval32) {
   2125 		SOC_IF_ERROR_RETURN(WRITE_ICOS_SELr(unit, port, cval32));
   2126 	    }
   2127 	}
   2128 #endif
   2129     }
   2130 
   2131     return BCM_E_NONE;
   2132 }
   2133 
   2134 /*
   2135  * Function:
   2136  *      bcm_fb_er_cosq_mapping_get
   2137  * Purpose:
   2138  *      Determine which COS queue a given priority currently maps to.
   2139  * Parameters:
   2140  *      unit - StrataSwitch unit number.
   2141  *      priority - Priority value
   2142  *      cosq - (Output) COS queue number
   2143  * Returns:
   2144  *      BCM_E_XXX
   2145  */
   2146 
   2147 int
   2148 bcm_fb_er_cosq_mapping_get(int unit, bcm_port_t port,
   2149                            bcm_cos_t priority, bcm_cos_queue_t *cosq)
   2150 {
   2151     uint32 cval32;
   2152     soc_field_t f;
   2153 
   2154     switch (priority) {
   2155     case 0:	f = COS0f; break;
   2156     case 1:	f = COS1f; break;
   2157     case 2:	f = COS2f; break;
   2158     case 3:	f = COS3f; break;
   2159     case 4:	f = COS4f; break;
   2160     case 5:	f = COS5f; break;
   2161     case 6:	f = COS6f; break;
   2162     case 7:	f = COS7f; break;
   2163     default:	return BCM_E_PARAM;
   2164     }
   2165 
   2166     if (port == -1) {
   2167 	port = REG_PORT_ANY;
   2168     } else if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) {
   2169 	return BCM_E_PORT;
   2170     }
   2171 
   2172     SOC_IF_ERROR_RETURN(READ_COS_SELr(unit, port, &cval32));
   2173     *cosq = soc_reg_field_get(unit, COS_SELr, cval32, f);
   2174 
   2175     return BCM_E_NONE;
   2176 }
   2177 
   2178 #ifdef BCM_FIREBOLT2_SUPPORT
   2179 
   2180 #define FB2_PKT_REFRESH_MAX      0xfffff
   2181 #define FB2_PKT_THD_MAX          0xfff
   2182 
   2183 STATIC int
   2184 _bcm_fb2_cosq_port_packet_bandwidth_set(int unit, bcm_port_t port,
   2185                                         bcm_cos_queue_t cosq,
   2186                                         int pps, int burst)
   2187 {
   2188     uint32 regval;
   2189     soc_reg_t maxbucket_config_reg, maxbucket_reg;
   2190     soc_field_t refresh_f, thd_sel_f, bucket_f;
   2191 
   2192     if (cosq < 0) {
   2193         maxbucket_config_reg = PKTPORTMAXBUCKETCONFIGr;
   2194         maxbucket_reg = PKTPORTMAXBUCKETr;
   2195         refresh_f = PKT_PORT_MAX_REFRESHf;
   2196         thd_sel_f = PKT_PORT_MAX_THD_SELf;
   2197         bucket_f = PKT_PORT_MAX_BUCKETf;
   2198         cosq = 0;
   2199     } else {
   2200         maxbucket_config_reg = PKTMAXBUCKETCONFIGr;
   2201         maxbucket_reg = PKTMAXBUCKETr;
   2202         refresh_f = PKT_MAX_REFRESHf;
   2203         thd_sel_f = PKT_MAX_THD_SELf;
   2204         bucket_f = PKT_MAX_BUCKETf;
   2205     }
   2206 
   2207     /*
   2208      * To set the new Bandwidth settings, the procedure adopted is
   2209      * a. reset MAXBUCKETCONFIG and MAXBUCKET
   2210      * b. update MAXBUCKETCONFIG with new values passed
   2211      * c. if MISCCONFIG.METERING_CLK_EN not set before, enable it.
   2212      */
   2213 
   2214     /* Disable egress metering */
   2215     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, maxbucket_config_reg, port, cosq, &regval));
   2216     soc_reg_field_set(unit, maxbucket_config_reg, &regval, refresh_f, 0);
   2217     soc_reg_field_set(unit, maxbucket_config_reg, &regval, thd_sel_f, 0);
   2218     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, maxbucket_config_reg, port, cosq, regval));
   2219 
   2220     /* reset the MAXBUCKET register*/
   2221     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, maxbucket_reg, port, cosq, &regval));
   2222     soc_reg_field_set(unit, maxbucket_reg, &regval, bucket_f, 0);
   2223     soc_reg_field_set(unit, maxbucket_reg, &regval,IN_PROFILE_FLAGf, 0);
   2224     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, maxbucket_reg, port, cosq, regval));
   2225 
   2226     /* Check packets-per second upper limit */
   2227     if (pps > FB2_PKT_REFRESH_MAX) {
   2228        pps = FB2_PKT_REFRESH_MAX;
   2229     }
   2230 
   2231     /* Check burst upper limit */
   2232     if (burst > FB2_PKT_THD_MAX) {
   2233        burst = FB2_PKT_THD_MAX;
   2234     }
   2235 
   2236     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, maxbucket_config_reg, port, cosq, &regval));
   2237     soc_reg_field_set(unit, maxbucket_config_reg, &regval, refresh_f, pps);
   2238     soc_reg_field_set(unit, maxbucket_config_reg, &regval, thd_sel_f, burst);
   2239     BCM_IF_ERROR_RETURN(soc_reg32_set(unit, maxbucket_config_reg, port, cosq, regval));
   2240 
   2241     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
   2242 
   2243     return BCM_E_NONE;
   2244 }
   2245 
   2246 STATIC int
   2247 _bcm_fb2_cosq_port_packet_bandwidth_get(int unit, bcm_port_t port,
   2248                                         bcm_cos_queue_t cosq,
   2249                                         int *pps, int *burst)
   2250 {
   2251     uint32 regval;
   2252     soc_reg_t maxbucket_config_reg;
   2253     soc_field_t refresh_f, thd_sel_f;
   2254 
   2255     if (cosq < 0) {
   2256         maxbucket_config_reg = PKTPORTMAXBUCKETCONFIGr;
   2257         refresh_f = PKT_PORT_MAX_REFRESHf;
   2258         thd_sel_f = PKT_PORT_MAX_THD_SELf;
   2259         cosq = 0;
   2260     } else {
   2261         maxbucket_config_reg = PKTMAXBUCKETCONFIGr;
   2262         refresh_f = PKT_MAX_REFRESHf;
   2263         thd_sel_f = PKT_MAX_THD_SELf;
   2264     }
   2265 
   2266     /* Disable egress metering */
   2267     BCM_IF_ERROR_RETURN(soc_reg32_get(unit, maxbucket_config_reg, port, cosq, &regval));
   2268     *pps = soc_reg_field_get(unit, maxbucket_config_reg, regval, refresh_f);
   2269     *burst = soc_reg_field_get(unit, maxbucket_config_reg, regval, thd_sel_f);
   2270 
   2271     return BCM_E_NONE;
   2272 }
   2273 
   2274 int
   2275 bcm_fb2_cosq_port_pps_set(int unit, bcm_port_t port,
   2276                           bcm_cos_queue_t cosq, int pps)
   2277 {
   2278     int temp_pps, burst;
   2279 
   2280     if (!IS_CPU_PORT(unit, port)) {
   2281         return BCM_E_PORT;
   2282     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   2283         return BCM_E_PARAM;
   2284     }
   2285 
   2286     /* Get the current PPS and BURST settings */
   2287     BCM_IF_ERROR_RETURN
   2288         (_bcm_fb2_cosq_port_packet_bandwidth_get(unit, port, cosq,
   2289                                                  &temp_pps, &burst));
   2290 
   2291     /* Replace the current PPS setting, keep BURST the same */
   2292     return _bcm_fb2_cosq_port_packet_bandwidth_set(unit, port, cosq,
   2293                                                    pps, burst);
   2294 }
   2295 
   2296 int
   2297 bcm_fb2_cosq_port_pps_get(int unit, bcm_port_t port,
   2298                           bcm_cos_queue_t cosq, int *pps)
   2299 {
   2300     int burst;
   2301 
   2302     if (!IS_CPU_PORT(unit, port)) {
   2303         return BCM_E_PORT;
   2304     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   2305         return BCM_E_PARAM;
   2306     }
   2307 
   2308     return _bcm_fb2_cosq_port_packet_bandwidth_get(unit, port, cosq,
   2309                                                    pps, &burst);
   2310 }
   2311 
   2312 int
   2313 bcm_fb2_cosq_port_burst_set(int unit, bcm_port_t port,
   2314                             bcm_cos_queue_t cosq, int burst)
   2315 {
   2316     int pps, temp_burst;
   2317 
   2318     if (!IS_CPU_PORT(unit, port)) {
   2319         return BCM_E_PORT;
   2320     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   2321         return BCM_E_PARAM;
   2322     }
   2323 
   2324     /* Get the current PPS and BURST settings */
   2325     BCM_IF_ERROR_RETURN
   2326         (_bcm_fb2_cosq_port_packet_bandwidth_get(unit, port, cosq,
   2327                                                  &pps, &temp_burst));
   2328 
   2329     /* Replace the current BURST setting, keep PPS the same */
   2330     return _bcm_fb2_cosq_port_packet_bandwidth_set(unit, port, cosq,
   2331                                                    pps, burst);
   2332 }
   2333 
   2334 int
   2335 bcm_fb2_cosq_port_burst_get(int unit, bcm_port_t port,
   2336                             bcm_cos_queue_t cosq, int *burst)
   2337 {
   2338     int pps;
   2339 
   2340     if (!IS_CPU_PORT(unit, port)) {
   2341         return BCM_E_PORT;
   2342     } else if (cosq >= NUM_CPU_COSQ(unit)) {
   2343         return BCM_E_PARAM;
   2344     }
   2345 
   2346     return _bcm_fb2_cosq_port_packet_bandwidth_get(unit, port, cosq,
   2347                                                    &pps, burst);
   2348 }
   2349 #endif /* BCM_FIREBOLT2_SUPPORT */
   2350 
   2351 
   2352 #ifndef BCM_SW_STATE_DUMP_DISABLE
   2353 /*
   2354  * Function:
   2355  *     bcm_fb_cosq_sw_dump
   2356  * Purpose:
   2357  *     Displays COS Queue information maintained by software.
   2358  * Parameters:
   2359  *     unit - Device unit number
   2360  * Returns:
   2361  *     None
   2362  */
   2363 void
   2364 bcm_fb_cosq_sw_dump(int unit)
   2365 {
   2366     LOG_CLI((BSL_META_U(unit,
   2367                         "\nSW Information COSQ - Unit %d\n"), unit));
   2368     LOG_CLI((BSL_META_U(unit,
   2369                         "    Number: %d\n"), _num_cosq[unit]));
   2370 
   2371     return;
   2372 }
   2373 #endif /* BCM_SW_STATE_DUMP_DISABLE */