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


      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  * File:        cosq.c
      8  */
      9 
     10 #include <soc/defs.h>
     11 #if defined(BCM_HERCULES_SUPPORT)
     12 #include <sal/core/libc.h>
     13 #include <shared/bsl.h>
     14 #include <soc/drv.h>
     15 #include <soc/scache.h>
     16 #include <soc/debug.h>
     17 #include <soc/hercules.h>
     18 
     19 #include <bcm/error.h>
     20 #include <bcm/cosq.h>
     21 #include <bcm/module.h>
     22 
     23 #include <bcm_int/esw/mbcm.h>
     24 #include <bcm_int/esw/hercules.h>
     25 
     26 #ifdef BCM_WARM_BOOT_SUPPORT
     27 #include <bcm_int/esw/switch.h>
     28 #endif /* BCM_WARM_BOOT_SUPPORT */
     29 
     30 static int _num_cosq[SOC_MAX_NUM_DEVICES];
     31 
     32 #ifdef BCM_WARM_BOOT_SUPPORT
     33 
     34 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
     35 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
     36 
     37 /*
     38  * Function:
     39  *      _bcm_hercules_cosq_reinit
     40  * Purpose:
     41  *      Recover COSQ software state.
     42  * Parameters:
     43  *      unit - Unit number.
     44  * Returns:
     45  *      BCM_E_XXX
     46  */
     47 STATIC int
     48 _bcm_hercules_cosq_reinit(int unit)
     49 {
     50     int                 rv;
     51     soc_scache_handle_t scache_handle;
     52     uint8               *cosq_scache_ptr;
     53     uint32              num_cosq;
     54  	 
     55     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
     56     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
     57                                  0, &cosq_scache_ptr, 
     58                                  BCM_WB_DEFAULT_VERSION, NULL);
     59 
     60     if (rv == BCM_E_NOT_FOUND) {
     61         cosq_scache_ptr = NULL;
     62     } else if (BCM_FAILURE(rv)) {
     63         return rv;
     64     }
     65 
     66     if (cosq_scache_ptr != NULL) {
     67         /* Number COSQ */
     68         sal_memcpy(&num_cosq, cosq_scache_ptr, sizeof(num_cosq));
     69         _num_cosq[unit] = num_cosq;
     70 
     71     } else {
     72         int cos, lossless;
     73 
     74         /* Pick from config */
     75         lossless = soc_property_get(unit, spn_LOSSLESS_MODE, 0);
     76         cos = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
     77 
     78         if (cos < 1) {
     79        	    cos = 1;
     80         } else if (lossless && cos > 4) {
     81       	    cos = 4;
     82         } else if (cos > NUM_COS(unit)) {
     83        	    cos = NUM_COS(unit);
     84         }
     85         _num_cosq[unit] = cos;
     86     }
     87 
     88     return BCM_E_NONE;
     89 }
     90 #endif /* BCM_WARM_BOOT_SUPPORT */
     91 
     92 int
     93 bcm_hercules_cosq_init(int unit)
     94 {
     95     int		lossless, num_cos;
     96 #ifdef BCM_WARM_BOOT_SUPPORT
     97     int                 rv;
     98     soc_scache_handle_t scache_handle;
     99     uint32              cosq_scache_size;
    100     uint8               *cosq_scache_ptr;
    101 #endif /* BCM_WARM_BOOT_SUPPORT */
    102 
    103 #ifdef BCM_WARM_BOOT_SUPPORT
    104     /* Warm boot level 2 cache size */
    105     cosq_scache_size = sizeof(uint32); /* Number COSQ */
    106 
    107     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    108     rv = _bcm_esw_scache_ptr_get(unit, scache_handle,
    109                                  (0 == SOC_WARM_BOOT(unit)),
    110                                  cosq_scache_size, &cosq_scache_ptr, 
    111                                  BCM_WB_DEFAULT_VERSION, NULL);
    112     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    113         return rv;
    114     }
    115 
    116     if (SOC_WARM_BOOT(unit)) {
    117         return _bcm_hercules_cosq_reinit(unit);
    118     }
    119 #endif /* BCM_WARM_BOOT_SUPPORT */
    120 
    121     lossless = soc_property_get(unit, spn_LOSSLESS_MODE, 0);
    122 
    123     num_cos = soc_property_get(unit, spn_BCM_NUM_COS, BCM_COS_DEFAULT);
    124 
    125     if (num_cos < 1) {
    126 	num_cos = 1;
    127     } else if (lossless && num_cos > 4) {
    128 	num_cos = 4;
    129     } else if (num_cos > NUM_COS(unit)) {
    130 	num_cos = NUM_COS(unit);
    131     }
    132 
    133     return bcm_hercules_cosq_config_set(unit, num_cos);
    134 }
    135 
    136 int
    137 bcm_hercules_cosq_config_set(int unit, int numq)
    138 {
    139     int		lossless, num_ports;
    140     int		cos, prio, ratio, remain;
    141     soc_port_t	port;
    142 
    143     /* Validate cosq num */
    144     if (numq < 1) {
    145         return BCM_E_PARAM;
    146     }
    147 
    148     lossless = soc_property_get(unit, spn_LOSSLESS_MODE, 0);
    149 
    150     SOC_PBMP_COUNT(PBMP_HG_ALL(unit), num_ports);
    151 
    152     PBMP_ALL_ITER(unit, port) {
    153         SOC_IF_ERROR_RETURN
    154             (soc_hercules15_mmu_limits_config(unit, port, num_ports, 
    155                                               numq, lossless));
    156     }
    157 
    158     /* Map the eight internal priority levels to the active cosqs */
    159     ratio = 8 / numq;
    160     remain = 8 % numq;
    161     cos = 0;
    162     for (prio = 0; prio < 8; prio++) {
    163         BCM_IF_ERROR_RETURN
    164             (bcm_hercules_cosq_mapping_set(unit, -1, prio, cos));
    165         if ((prio + 1) == (((cos + 1) * ratio) +
    166                            ((remain < (numq - cos)) ? 0 :
    167                             (remain - (numq - cos) + 1)))) {
    168             cos++;
    169         }
    170     }
    171 
    172     _num_cosq[unit] = numq;
    173 
    174     return BCM_E_NONE;
    175 }
    176 
    177 int
    178 bcm_hercules_cosq_config_get(int unit, int *numq)
    179 {
    180     if (_num_cosq[unit] == 0) {
    181 	return BCM_E_INIT;
    182     }
    183 
    184     if (numq != NULL) {
    185 	*numq = _num_cosq[unit];
    186     }
    187 
    188     return BCM_E_NONE;
    189 }
    190 
    191 int
    192 bcm_hercules_cosq_mapping_set(int unit, bcm_port_t port,
    193 			      bcm_cos_t priority, bcm_cos_queue_t cosq)
    194 {
    195     soc_field_t	f;
    196     uint32	reg, oreg;
    197 
    198     if (cosq < 0 || cosq >= NUM_COS(unit)) {
    199 	return BCM_E_PARAM;
    200     }
    201     switch (priority) {
    202     case 0:	f = FIELD0f; break;
    203     case 1:	f = FIELD1f; break;
    204     case 2:	f = FIELD2f; break;
    205     case 3:	f = FIELD3f; break;
    206     case 4:	f = FIELD4f; break;
    207     case 5:	f = FIELD5f; break;
    208     case 6:	f = FIELD6f; break;
    209     case 7:	f = FIELD7f; break;
    210     default:	return BCM_E_PARAM;
    211     }
    212 
    213     if (port == -1) {
    214 	PBMP_HG_ITER(unit, port) {
    215 	    SOC_IF_ERROR_RETURN(READ_ING_COS_MAPr(unit, port, &reg));
    216 	    oreg = reg;
    217 	    soc_reg_field_set(unit, ING_COS_MAPr, &reg, f, cosq);
    218 	    if (reg != oreg) {
    219 		SOC_IF_ERROR_RETURN(WRITE_ING_COS_MAPr(unit, port, reg));
    220 	    }
    221 	}
    222     } else if (SOC_PORT_VALID(unit, port) && IS_HG_PORT(unit, port)) {
    223 	SOC_IF_ERROR_RETURN(READ_ING_COS_MAPr(unit, port, &reg));
    224 	oreg = reg;
    225 	soc_reg_field_set(unit, ING_COS_MAPr, &reg, f, cosq);
    226 	if (reg != oreg) {
    227 	    SOC_IF_ERROR_RETURN(WRITE_ING_COS_MAPr(unit, port, reg));
    228 	}
    229     } else {
    230 	return BCM_E_PORT;
    231     }
    232 
    233     return BCM_E_NONE;
    234 }
    235 
    236 int
    237 bcm_hercules_cosq_mapping_get(int unit, bcm_port_t port,
    238 			      bcm_cos_t priority, bcm_cos_queue_t *cosq)
    239 {
    240     soc_field_t	f;
    241     uint32	reg;
    242 
    243     switch (priority) {
    244     case 0:	f = FIELD0f; break;
    245     case 1:	f = FIELD1f; break;
    246     case 2:	f = FIELD2f; break;
    247     case 3:	f = FIELD3f; break;
    248     case 4:	f = FIELD4f; break;
    249     case 5:	f = FIELD5f; break;
    250     case 6:	f = FIELD6f; break;
    251     case 7:	f = FIELD7f; break;
    252     default:	return BCM_E_PARAM;
    253     }
    254 
    255     if (port == -1) {
    256 	reg = 0;
    257 	PBMP_HG_ITER(unit, port) {
    258 	    SOC_IF_ERROR_RETURN(READ_ING_COS_MAPr(unit, port, &reg));
    259 	    break;
    260 	}
    261 	*cosq = soc_reg_field_get(unit, ING_COS_MAPr, reg, f);
    262     } else if (SOC_PORT_VALID(unit, port) && IS_HG_PORT(unit, port)) {
    263 	SOC_IF_ERROR_RETURN(READ_ING_COS_MAPr(unit, port, &reg));
    264 	*cosq = soc_reg_field_get(unit, ING_COS_MAPr, reg, f);
    265     } else {
    266 	return BCM_E_PORT;
    267     }
    268     return BCM_E_NONE;
    269 }
    270 
    271 int
    272 bcm_hercules_cosq_port_sched_set(int unit, bcm_pbmp_t pbm,
    273 				 int mode, const int weights[], int delay)
    274 {
    275     int			port;
    276     uint32		primod;
    277     int			mbits, cos;
    278 
    279     COMPILER_REFERENCE(delay);
    280 
    281     switch (mode) {
    282     case BCM_COSQ_STRICT:
    283 	mbits = 0;
    284 	break;
    285     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
    286 	mbits = 1;
    287 	/*
    288 	 * Weight values for 5670/75 are 32-bits.
    289 	 * If weight is 0, this queue is run in strict mode,
    290 	 * others run in WRR mode.
    291 	 */
    292 	break;
    293     default:
    294         mbits = -1;
    295 	return BCM_E_PARAM;
    296     }
    297 
    298     PBMP_ITER(pbm, port) {
    299         SOC_IF_ERROR_RETURN(READ_MMU_EGS_PRIMODr(unit, port, &primod));
    300 	soc_reg_field_set(unit, MMU_EGS_PRIMODr, &primod, PRIf, mbits);
    301         SOC_IF_ERROR_RETURN(WRITE_MMU_EGS_PRIMODr(unit, port, primod));
    302     }
    303 
    304     if (mode == BCM_COSQ_WEIGHTED_ROUND_ROBIN) {
    305 	/*
    306 	 * Weighted Fair Queueing scheduling
    307 	 */
    308 	PBMP_ITER(pbm, port) {
    309             for (cos = 0; cos < 8; cos++) {
    310                 SOC_IF_ERROR_RETURN(WRITE_MMU_EGS_WGTCOSr(unit, port, cos,
    311                                                           weights[cos]));
    312             }
    313 	}
    314     }
    315 
    316     return BCM_E_NONE;
    317 }
    318 
    319 int
    320 bcm_hercules_cosq_port_sched_get(int unit, bcm_pbmp_t pbm,
    321 				 int *mode, int weights[], int *delay)
    322 {
    323     uint32		primod, rval;
    324     int			port, mbits = -1, cos;
    325 
    326     PBMP_ITER(pbm, port) {
    327         SOC_IF_ERROR_RETURN(READ_MMU_EGS_PRIMODr(unit, port, &primod));
    328 	mbits = soc_reg_field_get(unit, MMU_EGS_PRIMODr, primod, PRIf);
    329         break;
    330     }
    331 
    332     switch (mbits) {
    333     case 0:
    334         *mode = BCM_COSQ_STRICT;
    335 	break;
    336     case 1:
    337 	*mode = BCM_COSQ_WEIGHTED_ROUND_ROBIN;
    338         for (cos = 0; cos < 8; cos++) {
    339             SOC_IF_ERROR_RETURN(READ_MMU_EGS_WGTCOSr(unit, port, cos, &rval));
    340             weights[cos] =
    341                 soc_reg_field_get(unit, MMU_EGS_WGTCOSr, rval, WGTf);
    342         }
    343 	break;
    344     default:
    345 	return BCM_E_INTERNAL;
    346     }
    347 
    348     if (delay) {
    349 	*delay = 0;
    350     }
    351     return BCM_E_NONE;
    352 }
    353 
    354 int
    355 bcm_hercules_cosq_sched_weight_max_get(int unit,int mode,
    356                                             int *weight_max)
    357 {
    358     switch (mode) {
    359     case BCM_COSQ_STRICT:
    360 	*weight_max = BCM_COSQ_WEIGHT_STRICT;
    361 	break;
    362     case BCM_COSQ_WEIGHTED_ROUND_ROBIN:
    363 	*weight_max = BCM_COSQ_WEIGHT_UNLIMITED;
    364         break;
    365     default:
    366 	*weight_max = BCM_COSQ_WEIGHT_UNLIMITED;
    367 	return BCM_E_PARAM;
    368     }
    369 
    370     return BCM_E_NONE;
    371 }
    372 
    373 int
    374 bcm_hercules_cosq_port_bandwidth_set(int unit, bcm_port_t port,
    375                                      bcm_cos_queue_t cosq,
    376                                      uint32 kbits_sec_min,
    377                                      uint32 kbits_sec_max,
    378                                      uint32 kbits_sec_burst,
    379                                      uint32 flags)
    380 {
    381     return BCM_E_UNAVAIL;
    382 }
    383 
    384 int
    385 bcm_hercules_cosq_port_bandwidth_get(int unit, bcm_port_t port,
    386                                      bcm_cos_queue_t cosq,
    387                                      uint32 *kbits_sec_min,
    388                                      uint32 *kbits_sec_max,
    389                                      uint32 *kbits_sec_burst,
    390                                      uint32 *flags)
    391 {
    392     return BCM_E_UNAVAIL;
    393 }
    394 
    395 int
    396 bcm_hercules_cosq_discard_set(int unit, uint32 flags)
    397 {
    398     return BCM_E_UNAVAIL;
    399 }
    400 
    401 int
    402 bcm_hercules_cosq_discard_get(int unit, uint32 *flags)
    403 {
    404     return BCM_E_UNAVAIL;
    405 }
    406 
    407 int
    408 bcm_hercules_cosq_discard_port_set(int unit, bcm_port_t port,
    409                                    bcm_cos_queue_t cosq,
    410                                    uint32 color,
    411                                    int drop_start,
    412                                    int drop_slope,
    413                                    int average_time)
    414 {
    415     return BCM_E_UNAVAIL;
    416 }
    417 
    418 int
    419 bcm_hercules_cosq_discard_port_get(int unit, bcm_port_t port,
    420                                    bcm_cos_queue_t cosq,
    421                                    uint32 color,
    422                                    int *drop_start,
    423                                    int *drop_slope,
    424                                    int *average_time)
    425 {
    426     return BCM_E_UNAVAIL;
    427 }
    428 
    429 int
    430 bcm_hercules_cosq_detach(int unit, int software_state_only)
    431 {
    432     return BCM_E_NONE;
    433 }
    434 
    435 #ifdef BCM_WARM_BOOT_SUPPORT
    436 int
    437 bcm_hercules_cosq_sync(int unit)
    438 {
    439     soc_scache_handle_t scache_handle;
    440     uint8               *cosq_scache_ptr;
    441     uint32              num_cosq;
    442 
    443     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_COSQ, 0);
    444     BCM_IF_ERROR_RETURN
    445         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    446                                  0, &cosq_scache_ptr, 
    447                                  BCM_WB_DEFAULT_VERSION, NULL));
    448     
    449     /* Number COSQ */
    450     num_cosq = _num_cosq[unit];
    451     sal_memcpy(cosq_scache_ptr, &num_cosq, sizeof(num_cosq));
    452         
    453     return BCM_E_NONE;
    454 
    455 }
    456 #endif /* BCM_WARM_BOOT_SUPPORT */
    457 
    458 #ifndef BCM_SW_STATE_DUMP_DISABLE
    459 void
    460 bcm_hercules_cosq_sw_dump(int unit)
    461 {
    462     LOG_CLI((BSL_META_U(unit,
    463                         "\nSW Information COSQ - Unit %d\n"), unit));
    464     LOG_CLI((BSL_META_U(unit,
    465                         "    Number: %d\n"), _num_cosq[unit]));
    466 
    467     return;
    468 }
    469 #endif /* BCM_SW_STATE_DUMP_DISABLE */
    470 #else /* BCM_HERCULES_SUPPORT */
    471 int _hercules_cosq_not_empty;
    472 #endif /* BCM_HERCULES_SUPPORT */