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


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * COS Queue Management
      8  * Purpose: API to set different cosq, priorities, and scheduler registers.
      9  *
     10  * Bradley supports two additional COS queues for high priority flow 
     11  * control (QM queue) and system control (SC queue.) Currently API
     12  * access to these two queues is blocked since they do not participate
     13  * in regular queue scheduling (they are both always using strict
     14  * priority.) Likewise, internal priorities 14 and 15 are reserved
     15  * for use with these two COS queues. This means that the COS mapping 
     16  * API will allow mapping of 14 internal priorities to the 8 normal 
     17  * COS queues.
     18  */
     19 
     20 #include <sal/core/libc.h>
     21 #include <shared/bsl.h>
     22 #include <soc/defs.h>
     23 #if defined(BCM_BRADLEY_SUPPORT)
     24 #include <soc/drv.h>
     25 #include <soc/scache.h>
     26 #include <soc/debug.h>
     27 
     28 #include <bcm/error.h>
     29 #include <bcm/cosq.h>
     30 
     31 #include <bcm_int/esw/cosq.h>
     32 #include <bcm_int/esw/mbcm.h>
     33 #include <bcm_int/esw/firebolt.h>
     34 #include <bcm_int/esw/bradley.h>
     35 
     36 #include <bcm_int/esw_dispatch.h>
     37 
     38 #ifdef BCM_WARM_BOOT_SUPPORT
     39 #include <bcm_int/esw/switch.h>
     40 #endif /* BCM_WARM_BOOT_SUPPORT */
     41 
     42 #define HB_DRR_WEIGHT_MAX       0x7f
     43 #define HB_WRR_WEIGHT_MAX       0x7f
     44 
     45 #define HB_SC_COS               14
     46 #define HB_QM_COS               15
     47 
     48 static const soc_field_t cpu_prio_field[16] = { 
     49     PRI0f,  PRI1f,  PRI2f,  PRI3f,  PRI4f,  PRI5f,  PRI6f,  PRI7f, 
     50     PRI8f,  PRI9f,  PRI10f, PRI11f, PRI12f, PRI13f, PRI14f, PRI15f
     51 };
     52 
     53 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
     54 
     55 static const soc_field_t cos_field[16] = { 
     56     COS0f,  COS1f,  COS2f,  COS3f,  COS4f,  COS5f,  COS6f,  COS7f, 
     57     COS8f,  COS9f,  COS10f, COS11f, COS12f, COS13f, COS14f, COS15f
     58 };
     59 
     60 static const soc_field_t hg_cos_val[16] = { 
     61     0,      1,      2,      3,      4,      5,      6,      7, 
     62     7,      7,      7,      7,      7,      7,      14,     15
     63 };
     64 
     65 #endif
     66 
     67 
     68 static int _num_cosq[SOC_MAX_NUM_DEVICES];
     69 static int _max_cosq = -1;
     70 
     71 /*
     72  * Convert the number of kbytes (1024 bytes) that can transmtted in one run
     73  * to weight encoding as per table above
     74  */
     75 static int
     76 _bcm_hb_cos_drr_kbytes_to_weight(int kbytes)
     77 {
     78     int weight;
     79 
     80     /* 1 weight-unit ~ 128 bytes */
     81     weight = 8 * kbytes;
     82 
     83     if (weight > HB_DRR_WEIGHT_MAX) {
     84         weight = HB_DRR_WEIGHT_MAX;
     85     }
     86 
     87     return weight;
     88 }
     89 
     90 /*
     91  * Convert the encoded weights to number of kbytes that can transmtted
     92  * in one run.
     93  */
     94 static int
     95 _bcm_hb_cos_drr_weight_to_kbytes(int weight)
     96 {
     97     assert(weight <= HB_DRR_WEIGHT_MAX);
     98 
     99     /* 1 weight-unit ~ 128 bytes */
    100     return (weight / 8);
    101 }
    102 
    103 
    104 #ifdef BCM_WARM_BOOT_SUPPORT
    105 
    106 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
    107 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
    108 
    109 /*
    110  * Function:
    111  *      bcm_bradley_cosq_sync
    112  * Purpose:
    113  *      Record COSQ module persistent info for Level 2 Warm Boot.
    114  * Parameters:
    115  *      unit - Unit number.
    116  * Returns:
    117  *      BCM_E_XXX
    118  */
    119 int
    120 bcm_bradley_cosq_sync(int unit)
    121 {
    122     soc_scache_handle_t scache_handle;
    123     uint8               *cosq_scache_ptr;
    124     uint32              num_cosq;
    125 
    126     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    127     BCM_IF_ERROR_RETURN
    128         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    129                                  0, &cosq_scache_ptr, 
    130                                  BCM_WB_DEFAULT_VERSION, NULL));
    131     
    132     /* Number COSQ */
    133     num_cosq = _num_cosq[unit];
    134     sal_memcpy(cosq_scache_ptr, &num_cosq, sizeof(num_cosq));
    135         
    136     return BCM_E_NONE;
    137 }
    138 
    139 /*
    140  * Function:
    141  *      _bcm_bradley_cosq_reinit
    142  * Purpose:
    143  *      Recover COSQ software state.
    144  * Parameters:
    145  *      unit - Unit number.
    146  * Returns:
    147  *      BCM_E_XXX
    148  */
    149 STATIC int
    150 _bcm_bradley_cosq_reinit(int unit)
    151 {
    152     int                 rv;
    153     soc_scache_handle_t scache_handle;
    154     uint8               *cosq_scache_ptr;
    155     uint32              num_cosq;
    156  	 
    157     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    158     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    159                                  0, &cosq_scache_ptr, 
    160                                  BCM_WB_DEFAULT_VERSION, NULL);
    161 
    162     if (rv == BCM_E_NOT_FOUND) {
    163         cosq_scache_ptr = NULL;
    164     } else if (BCM_FAILURE(rv)) {
    165         return rv;
    166     }
    167 
    168     if (cosq_scache_ptr != NULL) {
    169         /* Number COSQ */
    170         sal_memcpy(&num_cosq, cosq_scache_ptr, sizeof(num_cosq));
    171         _num_cosq[unit] = num_cosq;
    172     } else {
    173         _num_cosq[unit] = _bcm_esw_cosq_config_property_get(unit);
    174     }
    175 
    176     return BCM_E_NONE;
    177 }
    178 #endif /* BCM_WARM_BOOT_SUPPORT */
    179 
    180 /*
    181  * Function:
    182  *      bcm_bradley_cosq_init
    183  * Purpose:
    184  *      Initialize (clear) all COS schedule/mapping state.
    185  * Parameters:
    186  *      unit - StrataSwitch unit number.
    187  * Returns:
    188  *      BCM_E_XXX
    189  */
    190 
    191 int
    192 bcm_bradley_cosq_init(int unit)
    193 {
    194     int         num_cos;
    195 #ifdef BCM_WARM_BOOT_SUPPORT
    196     int                 rv;
    197     soc_scache_handle_t scache_handle;
    198     uint32              cosq_scache_size;
    199     uint8               *cosq_scache_ptr;
    200 #endif /* BCM_WARM_BOOT_SUPPORT */
    201 
    202     if (_max_cosq < 0) {
    203         _max_cosq = NUM_COS(unit);
    204         NUM_COS(unit) = 8;
    205     }
    206 
    207 #ifdef BCM_WARM_BOOT_SUPPORT
    208     /* Warm boot level 2 cache size */
    209     cosq_scache_size = sizeof(uint32); /* Number COSQ */
    210 
    211     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    212     rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
    213                                  (0 == SOC_WARM_BOOT(unit)),
    214                                  cosq_scache_size, &cosq_scache_ptr, 
    215                                  BCM_WB_DEFAULT_VERSION, NULL);
    216     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    217         return rv;
    218     }
    219 
    220     if (SOC_WARM_BOOT(unit)) {
    221         return _bcm_bradley_cosq_reinit(unit);
    222     }
    223 #endif /* BCM_WARM_BOOT_SUPPORT */
    224 
    225     num_cos = _bcm_esw_cosq_config_property_get(unit);
    226 
    227     return bcm_bradley_cosq_config_set(unit, num_cos);
    228 }
    229 
    230 /*
    231  * Function:
    232  *      bcm_cosq_detach
    233  * Purpose:
    234  *      Discard all COS schedule/mapping state.
    235  * Parameters:
    236  *      unit - StrataSwitch unit number.
    237  * Returns:
    238  *      BCM_E_XXX
    239  */
    240 
    241 int
    242 bcm_bradley_cosq_detach(int unit, int software_state_only)
    243 {
    244     return BCM_E_NONE;
    245 }
    246 
    247 /*
    248  * Function:
    249  *      bcm_bradley_cosq_config_set
    250  * Purpose:
    251  *      Set the number of COS queues
    252  * Parameters:
    253  *      unit - Draco unit number.
    254  *      numq - number of COS queues (1-8).
    255  * Returns:
    256  *      BCM_E_XXX
    257  */
    258 
    259 int
    260 bcm_bradley_cosq_config_set(int unit, int numq)
    261 {
    262     int         cos, prio, ratio, remain;
    263     uint32      val32;
    264 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
    265     soc_port_t  port;
    266     uint64      val64;
    267 #endif
    268 
    269     /* Validate cosq num */
    270     if (numq < 1) {
    271         return BCM_E_PARAM;
    272     }
    273 
    274     if (SOC_WARM_BOOT(unit)) {
    275         _num_cosq[unit] = numq;
    276         return BCM_E_NONE;
    277     }
    278 
    279     /* Map the eight 802.1 priority levels to the active cosqs */
    280     if (numq > 8) {
    281         numq = 8;
    282     }
    283     ratio = 8 / numq;
    284     remain = 8 % numq;
    285     cos = 0;
    286     for (prio = 0; prio < 8; prio++) {
    287         BCM_IF_ERROR_RETURN
    288             (bcm_bradley_cosq_mapping_set(unit, -1, prio, cos));
    289         if ((prio + 1) == (((cos + 1) * ratio) +
    290                            ((remain < (numq - cos)) ? 0 :
    291                             (remain - (numq - cos) + 1)))) {
    292             cos++;
    293         }
    294     }
    295 
    296     /* Map remaining internal priority levels to highest priority cosq */
    297     cos = numq - 1;
    298     for (prio = 8; prio < 14; prio++) {
    299         BCM_IF_ERROR_RETURN
    300             (bcm_bradley_cosq_mapping_set(unit, -1, prio, cos));
    301     }
    302 
    303     /* Map SC COS queue */
    304     BCM_IF_ERROR_RETURN
    305         (bcm_bradley_cosq_mapping_set(unit, -1, 14, HB_SC_COS));
    306 
    307     /* Map QM COS queue */
    308     BCM_IF_ERROR_RETURN
    309         (bcm_bradley_cosq_mapping_set(unit, -1, 15, HB_QM_COS));
    310 
    311 #ifdef BCM_COSQ_HIGIG_MAP_DISABLE
    312     /* identity mapping for higig ports */
    313 
    314     if (SOC_IS_HB_GW(unit)) {
    315         /* map prio0->cos0, prio1->cos1, ... , prio7->cos7 */
    316         COMPILER_64_ZERO(val64);
    317         for (prio = 0; prio < 8; prio++) {
    318             soc_reg64_field32_set(unit, ICOS_SELr, &val64, 
    319                                   cos_field[prio], hg_cos_val[prio]);
    320         }
    321         PBMP_HG_ITER(unit, port) {
    322             SOC_IF_ERROR_RETURN(WRITE_ICOS_SELr(unit, port, val64));
    323         }
    324         SOC_IF_ERROR_RETURN(WRITE_ICOS_SELr(unit, (CMIC_PORT(unit)), val64));
    325     }
    326 #endif
    327 
    328     if (SOC_REG_IS_VALID(unit, CPU_PRIORITY_SELr)) {
    329         /* use 1:1 CPU priority mapping */
    330         val32 = 0;
    331         for (prio = 0; prio < 8; prio++) {
    332             soc_reg_field_set(unit, CPU_PRIORITY_SELr, &val32, 
    333                               cpu_prio_field[prio], prio);
    334         }
    335         SOC_IF_ERROR_RETURN(WRITE_CPU_PRIORITY_SELr(unit, val32));
    336         val32 = 0;
    337         for (prio = 8; prio < 16; prio++) {
    338             soc_reg_field_set(unit, CPU_PRIORITY_SEL_2r, &val32, 
    339                               cpu_prio_field[prio], prio);
    340         }
    341         SOC_IF_ERROR_RETURN(WRITE_CPU_PRIORITY_SEL_2r(unit, val32));
    342     }
    343 
    344     _num_cosq[unit] = numq;
    345 
    346     return BCM_E_NONE;
    347 }
    348 
    349 /*
    350  * Function:
    351  *      bcm_bradley_cosq_mapping_set
    352  * Purpose:
    353  *      Set which cosq a given priority should fall into
    354  * Parameters:
    355  *      unit - StrataSwitch unit number.
    356  *      priority - Priority value to map
    357  *      cosq - COS queue to map to
    358  * Returns:
    359  *      BCM_E_XXX
    360  * Notes:
    361  *      Priorities 14 and 15 are blocked unless used in
    362  *      conjunction with the SC and QM COS queues.
    363  */
    364 
    365 int
    366 bcm_bradley_cosq_mapping_set(int unit, bcm_port_t port,
    367                              bcm_cos_t priority, bcm_cos_queue_t cosq)
    368 {
    369     uint32 cval32, oval32;
    370     soc_field_t f;
    371     bcm_pbmp_t ports;
    372 
    373     switch (priority) {
    374     case 0:	f = COS0f; break;
    375     case 1:	f = COS1f; break;
    376     case 2:	f = COS2f; break;
    377     case 3:	f = COS3f; break;
    378     case 4:	f = COS4f; break;
    379     case 5:	f = COS5f; break;
    380     case 6:	f = COS6f; break;
    381     case 7:	f = COS7f; break;
    382     case 8:	f = COS8f; break;
    383     case 9:	f = COS9f; break;
    384     case 10:	f = COS10f; break;
    385     case 11:	f = COS11f; break;
    386     case 12:	f = COS12f; break;
    387     case 13:	f = COS13f; break;
    388     case 14:	f = COS14f; break;
    389     case 15:	f = COS15f; break;
    390     default:	return BCM_E_PARAM;
    391     }
    392 
    393     if ((cosq < 0 || cosq >= 8) && cosq != HB_SC_COS && cosq != HB_QM_COS) {
    394         return (BCM_E_PARAM);
    395     }
    396 
    397     if (port == -1) {	/* all ports */
    398 	BCM_PBMP_ASSIGN(ports, PBMP_ALL(unit));
    399     } else if (SOC_PORT_VALID(unit, port) && IS_ALL_PORT(unit, port)) {
    400 	BCM_PBMP_CLEAR(ports);
    401 	BCM_PBMP_PORT_ADD(ports, port);
    402     } else {
    403 	return BCM_E_PORT;
    404     }
    405 
    406     PBMP_ITER(ports, port) {
    407 	if (priority < 8) {
    408 	    SOC_IF_ERROR_RETURN(READ_COS_SELr(unit, port, &cval32));
    409 	    oval32 = cval32;
    410 	    soc_reg_field_set(unit, COS_SELr, &cval32, f, cosq);
    411 	    if (cval32 != oval32) {
    412 		SOC_IF_ERROR_RETURN(WRITE_COS_SELr(unit, port, cval32));
    413 	    }
    414 	    if (port == CMIC_PORT(unit) &&
    415                 SOC_REG_IS_VALID(unit, CPU_COS_SELr)) {
    416 		SOC_IF_ERROR_RETURN(READ_CPU_COS_SELr(unit, &cval32));
    417 		oval32 = cval32;
    418 		soc_reg_field_set(unit, CPU_COS_SELr, &cval32, f, cosq);
    419 		if (cval32 != oval32) {
    420 		    SOC_IF_ERROR_RETURN(WRITE_CPU_COS_SELr(unit, cval32));
    421 		}
    422 	    }
    423 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
    424 	    if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
    425 		SOC_IF_ERROR_RETURN(READ_ICOS_SELr(unit, port, &cval32));
    426 		oval32 = cval32;
    427 		soc_reg_field_set(unit, ICOS_SELr, &cval32, f, cosq);
    428 		if (cval32 != oval32) {
    429 		    SOC_IF_ERROR_RETURN(WRITE_ICOS_SELr(unit, port, cval32));
    430 		}
    431 	    }
    432 #endif
    433 	} else {
    434 	    SOC_IF_ERROR_RETURN(READ_COS_SEL_2r(unit, port, &cval32));
    435 	    oval32 = cval32;
    436 	    soc_reg_field_set(unit, COS_SEL_2r, &cval32, f, cosq);
    437 	    if (cval32 != oval32) {
    438 		SOC_IF_ERROR_RETURN(WRITE_COS_SEL_2r(unit, port, cval32));
    439 	    }
    440 
    441 	    if (port == CMIC_PORT(unit) &&
    442                 SOC_REG_IS_VALID(unit, CPU_COS_SEL_2r)) {
    443 		SOC_IF_ERROR_RETURN(READ_CPU_COS_SEL_2r(unit, &cval32));
    444 		oval32 = cval32;
    445 		soc_reg_field_set(unit, CPU_COS_SEL_2r, &cval32, f, cosq);
    446 		if (cval32 != oval32) {
    447 		    SOC_IF_ERROR_RETURN(WRITE_CPU_COS_SEL_2r(unit, cval32));
    448 		}
    449 	    }
    450 #ifndef BCM_COSQ_HIGIG_MAP_DISABLE
    451 	    if (IS_HG_PORT(unit, port) || port == CMIC_PORT(unit)) {
    452 		SOC_IF_ERROR_RETURN(READ_ICOS_SEL_2r(unit, port, &cval32));
    453 		oval32 = cval32;
    454 		soc_reg_field_set(unit, ICOS_SEL_2r, &cval32, f, cosq);
    455 		if (cval32 != oval32) {
    456 		    SOC_IF_ERROR_RETURN(WRITE_ICOS_SEL_2r(unit, port, cval32));
    457 		}
    458 	    }
    459 #endif
    460 	}
    461     }
    462 
    463     return BCM_E_NONE;
    464 }
    465 
    466 /*
    467  * Function:
    468  *      bcm_bradley_cosq_mapping_get
    469  * Purpose:
    470  *      Determine which COS queue a given priority currently maps to.
    471  * Parameters:
    472  *      unit - StrataSwitch unit number.
    473  *      priority - Priority value
    474  *      cosq - (Output) COS queue number
    475  * Returns:
    476  *      BCM_E_XXX
    477  */
    478 
    479 int
    480 bcm_bradley_cosq_mapping_get(int unit, bcm_port_t port,
    481                              bcm_cos_t priority, bcm_cos_queue_t *cosq)
    482 {
    483     uint32 cval32;
    484     soc_field_t f;
    485 
    486     switch (priority) {
    487     case 0:	f = COS0f; break;
    488     case 1:	f = COS1f; break;
    489     case 2:	f = COS2f; break;
    490     case 3:	f = COS3f; break;
    491     case 4:	f = COS4f; break;
    492     case 5:	f = COS5f; break;
    493     case 6:	f = COS6f; break;
    494     case 7:	f = COS7f; break;
    495     case 8:	f = COS8f; break;
    496     case 9:	f = COS9f; break;
    497     case 10:	f = COS10f; break;
    498     case 11:	f = COS11f; break;
    499     case 12:	f = COS12f; break;
    500     case 13:	f = COS13f; break;
    501     case 14:	f = COS14f; break;
    502     case 15:	f = COS15f; break;
    503     default:	return BCM_E_PARAM;
    504     }
    505 
    506     if (port == -1) {
    507 	port = REG_PORT_ANY;
    508     } else if (!SOC_PORT_VALID(unit, port) || !IS_ALL_PORT(unit, port)) {
    509 	return BCM_E_PORT;
    510     }
    511 
    512     if (priority < 8) {
    513 	SOC_IF_ERROR_RETURN(READ_COS_SELr(unit, port, &cval32));
    514 	*cosq = soc_reg_field_get(unit, COS_SELr, cval32, f);
    515     } else {
    516 	SOC_IF_ERROR_RETURN(READ_COS_SEL_2r(unit, port, &cval32));
    517 	*cosq = soc_reg_field_get(unit, COS_SEL_2r, cval32, f);
    518     }
    519     return BCM_E_NONE;
    520 }
    521 
    522 /*
    523  * Function:
    524  *      bcm_bradley_cosq_config_get
    525  * Purpose:
    526  *      Get the number of cos queues
    527  * Parameters:
    528  *      unit - StrataSwitch unit number.
    529  *      numq - (Output) number of cosq
    530  * Returns:
    531  *      BCM_E_XXX
    532  */
    533 
    534 int
    535 bcm_bradley_cosq_config_get(int unit, int *numq)
    536 {
    537     if (_num_cosq[unit] == 0) {
    538         return BCM_E_INIT;
    539     }
    540 
    541     if (numq != NULL) {
    542         *numq = _num_cosq[unit];
    543     }
    544 
    545     return BCM_E_NONE;
    546 }
    547 
    548 /*
    549  * Function:
    550  *      bcm_bradley_cosq_port_sched_set
    551  * Purpose:
    552  *      Set up class-of-service policy and corresponding weights and delay
    553  * Parameters:
    554  *      unit - StrataSwitch unit number.
    555  *      pbm - port bitmap
    556  *      mode - Scheduling mode, one of BCM_COSQ_xxx
    557  *      weights - Weights for each COS queue
    558  *                Only for BCM_COSQ_WEIGHTED_FAIR_ROUND_ROBIN mode.
    559  *                For DRR Weight is specified in Kbytes
    560  *      delay - This parameter is not used in 56504
    561  * Returns:
    562  *      BCM_E_XXX
    563  */
    564 
    565 int
    566 bcm_bradley_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
    567                                 int mode, const int weights[], int delay)
    568 {
    569     int port, t, i;
    570     uint32 wrr, escfg, minsp;
    571     int mbits = 0;
    572     int enc_weights[8];
    573 
    574     switch (mode) {
    575     case BCM_COSQ_STRICT:
    576         mbits = 0;
    577         break;
    578     case BCM_COSQ_ROUND_ROBIN:
    579         mbits = 1;
    580         break;
    581     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
    582         mbits = 2;
    583         /*
    584          * All weight values must fit within 7 bits.
    585          * If weight is 0, this queue is run in strict mode,
    586          * others run in WRR mode.
    587          */
    588 
    589         t = weights[0] | weights[1] | weights[2] | weights[3] |
    590             weights[4] | weights[5] | weights[6] | weights[7];
    591 
    592         if ((t & ~0x7f) != 0) {
    593             return BCM_E_PARAM;
    594         }
    595         for(i = 0; i < 8; i++) {
    596             enc_weights[i] = weights[i];
    597         }
    598         break;
    599     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
    600         mbits = 3;
    601         for(i = 0; i < 8; i++) {
    602             enc_weights[i] = _bcm_hb_cos_drr_kbytes_to_weight(weights[i]);
    603         }
    604         break;
    605     case BCM_COSQ_BOUNDED_DELAY:        /* not supported in xgs */
    606     default:
    607         return BCM_E_PARAM;
    608     }
    609 
    610     PBMP_ITER(pbm, port) {
    611         SOC_IF_ERROR_RETURN
    612             (READ_ESCONFIGr(unit, port, &escfg));
    613         soc_reg_field_set(unit, ESCONFIGr, &escfg, SCHEDULING_SELECTf, mbits);
    614         SOC_IF_ERROR_RETURN
    615             (WRITE_ESCONFIGr(unit, port, escfg));
    616     }
    617 
    618     if ((mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) ||
    619         (mode == BCM_COSQ_DEFICIT_ROUND_ROBIN)) {
    620         /*
    621          * Weighted Fair Queueing scheduling among vaild COSs
    622          */
    623         PBMP_ITER(pbm, port) {
    624             SOC_IF_ERROR_RETURN
    625                 (READ_MINSPCONFIGr(unit, port, &minsp));
    626             for(i = 0; i < 8; i++) {
    627                 SOC_IF_ERROR_RETURN
    628                     (READ_COSWEIGHTSr(unit, port, i, &wrr));
    629     /*    coverity[uninit_use_in_call : FALSE]    */
    630                 soc_reg_field_set(unit, COSWEIGHTSr, &wrr,
    631                                   COSWEIGHTSf, enc_weights[i]);
    632                 SOC_IF_ERROR_RETURN
    633                     (WRITE_COSWEIGHTSr(unit, port, i, wrr));
    634                 /* Set strict priority bit if weight is zero */
    635                 if (enc_weights[i] == 0) {
    636                     minsp |= (1 << i);
    637                 } else {
    638                     minsp &= ~(1 << i);
    639                 }
    640             }
    641             SOC_IF_ERROR_RETURN
    642                 (WRITE_MINSPCONFIGr(unit, port, minsp));
    643         }
    644     }
    645     return BCM_E_NONE;
    646 }
    647 
    648 /*
    649  * Function:
    650  *      bcm_bradley_cosq_port_sched_get
    651  * Purpose:
    652  *      Retrieve class-of-service policy and corresponding weights and delay
    653  * Parameters:
    654  *      unit     - StrataSwitch unit number.
    655  *      pbm      - port bitmap
    656  *      mode     - (output) Scheduling mode, one of BCM_COSQ_xxx
    657  *      weights  - (output) Weights for each COS queue
    658  *                          Only for BCM_COSQ_WEIGHTED_ROUND_ROBIN and
    659  *                          BCM_COSQ_DEFICIT_ROUND_ROBIN mode.
    660  *                 For DRR Weight is specified in Kbytes
    661  *      delay    - This parameter is not used in 56504
    662  * Returns:
    663  *      BCM_E_XXX
    664  * Notes:
    665  *      Actually just returns data for the first port in the bitmap
    666  */
    667 
    668 int
    669 bcm_bradley_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
    670                                 int *mode, int weights[], int *delay)
    671 {
    672     uint32 escfg, wrr;
    673     int mbits, port, i;
    674 
    675     mbits = -1;
    676     PBMP_ITER(pbm, port) {
    677         SOC_IF_ERROR_RETURN
    678             (READ_ESCONFIGr(unit, port, &escfg));
    679         mbits = soc_reg_field_get(unit, ESCONFIGr, escfg, SCHEDULING_SELECTf);
    680         break;
    681     }
    682 
    683     switch (mbits) {
    684     case 0:
    685         *mode = BCM_COSQ_STRICT;
    686         break;
    687     case 1:
    688         *mode = BCM_COSQ_ROUND_ROBIN;
    689         break;
    690     case 2:
    691         *mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
    692         break;
    693     case 3:
    694         *mode = BCM_COSQ_DEFICIT_ROUND_ROBIN;
    695         break;
    696     default:
    697         return BCM_E_INTERNAL;
    698     }
    699 
    700     if ((mbits == 2) || (mbits == 3)) {
    701         wrr = 0;
    702         PBMP_ITER(pbm, port) {
    703             for(i = 0; i < 8; i++) {
    704                 SOC_IF_ERROR_RETURN
    705                     (READ_COSWEIGHTSr(unit, port, i, &wrr));
    706                 weights[i] = soc_reg_field_get(unit, COSWEIGHTSr, wrr,
    707                                                COSWEIGHTSf);
    708             }
    709             break;
    710         }
    711 
    712         if (mbits == 3) {
    713             int i;
    714             for(i = 0; i < 8; i++) {
    715                 weights[i] = _bcm_hb_cos_drr_weight_to_kbytes(weights[i]);
    716             }
    717         }
    718     }
    719 
    720     if (delay) {
    721         *delay = 0;
    722     }
    723     return BCM_E_NONE;
    724 }
    725 
    726 /*
    727  * Function:
    728  *      bcm_bradley_cosq_sched_weight_max_get
    729  * Purpose:
    730  *      Retrieve maximum weights for given COS policy.
    731  * Parameters:
    732  *      unit - StrataSwitch unit number.
    733  *      mode - Scheduling mode, one of BCM_COSQ_xxx
    734  *      weight_max - (output) Maximum weight for COS queue.
    735  *              For DRR mode Weight is specified in Kbytes
    736  *              0 if mode is BCM_COSQ_STRICT.
    737  *              1 if mode is BCM_COSQ_ROUND_ROBIN.
    738  *              -1 if not applicable to mode.
    739  * Returns:
    740  *      BCM_E_XXX
    741  */
    742 
    743 int
    744 bcm_bradley_cosq_sched_weight_max_get(int unit, int mode, int *weight_max)
    745 {
    746     switch (mode) {
    747     case BCM_COSQ_STRICT:
    748         *weight_max = BCM_COSQ_WEIGHT_STRICT;
    749         break;
    750     case BCM_COSQ_ROUND_ROBIN:
    751         *weight_max = BCM_COSQ_WEIGHT_MIN;
    752         break;
    753     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
    754         *weight_max = HB_WRR_WEIGHT_MAX;
    755         break;
    756     case BCM_COSQ_DEFICIT_ROUND_ROBIN:
    757         *weight_max = _bcm_hb_cos_drr_weight_to_kbytes(HB_DRR_WEIGHT_MAX);
    758         break;
    759     default:
    760         *weight_max = BCM_COSQ_WEIGHT_UNLIMITED;
    761         return BCM_E_PARAM;
    762     }
    763 
    764     return BCM_E_NONE;
    765 }
    766 
    767 #ifndef BCM_SW_STATE_DUMP_DISABLE
    768 /*
    769  * Function:
    770  *     bcm_bradley_cosq_sw_dump
    771  * Purpose:
    772  *     Displays COS Queue information maintained by software.
    773  * Parameters:
    774  *     unit - Device unit number
    775  * Returns:
    776  *     None
    777  */
    778 void
    779 bcm_bradley_cosq_sw_dump(int unit)
    780 {
    781     LOG_CLI((BSL_META_U(unit,
    782                         "\nSW Information COSQ - Unit %d\n"), unit));
    783     LOG_CLI((BSL_META_U(unit,
    784                         "    Number: %d\n"), _num_cosq[unit]));
    785 
    786     return;
    787 }
    788 #endif /* BCM_SW_STATE_DUMP_DISABLE */
    789 
    790 #else /* BCM_BRADLEY_SUPPORT */
    791 int _bradley_cosq_not_empty;
    792 #endif  /* BCM_BRADLEY_SUPPORT */
    793