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

scheduler.c (14073B)


      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  * Scheduler API implemenation for Tomahawk3
      8  */
      9 
     10 
     11 #if defined(BCM_TOMAHAWK3_SUPPORT)
     12 #include <bcm_int/esw/pfc.h>
     13 #include <bcm_int/esw/port.h>
     14 #include <bcm_int/esw/tomahawk3.h>
     15 #include <soc/feature.h>
     16 #include <soc/drv.h>
     17 #include <soc/types.h>
     18 #include <soc/scache.h>
     19 #include <soc/profile_mem.h>
     20 #include <soc/debug.h>
     21 #include <soc/tomahawk3.h>
     22 #include <soc/dma.h>
     23 #include <soc/mmu_config.h>
     24 
     25 _soc_mmu_cfg_scheduler_profile_t* soc_mmu_cfg_scheduler_profile_alloc(int unit)
     26 {
     27     _soc_mmu_cfg_scheduler_profile_t *sched_profile;
     28     int alloc_size=0;
     29     int i;
     30 
     31     alloc_size = sizeof(_soc_mmu_cfg_scheduler_profile_t);
     32     for (i=0; i < SOC_TH3_MAX_NUM_SCHED_PROFILE; i++) {
     33         alloc_size += sizeof(_soc_mmu_cfg_scheduler_profile_t);
     34     }
     35     sched_profile = sal_alloc(alloc_size, "MMU config scheduler profile");
     36     if (sched_profile == NULL) {
     37         return NULL;
     38     }
     39 
     40     sal_memset(sched_profile, 0, alloc_size);
     41     return sched_profile;
     42 }
     43 
     44 void
     45 soc_mmu_cfg_scheduler_profile_free(int unit, _soc_mmu_cfg_scheduler_profile_t *cfg)
     46 {
     47     if (cfg != NULL) {
     48         sal_free(cfg);
     49     }
     50 }
     51 
     52 
     53 int
     54 _soc_mmu_cfg_scheduler_profile_read(int unit, _soc_mmu_cfg_scheduler_profile_t *sched_profile,
     55                                     int *scheduler_port_profile_map)
     56 {
     57     char name[80];
     58     int idx;
     59     int port;
     60     /* char suffix; */
     61 
     62     if (scheduler_port_profile_map == NULL) {
     63         return SOC_E_PARAM;
     64     }
     65 
     66     if (sched_profile == NULL) {
     67         return SOC_E_PARAM;
     68     } 
     69 
     70     /* scheduler_profile_map_<port>=<profile_idx> */
     71     PBMP_ALL_ITER(unit, port) {
     72         scheduler_port_profile_map[port] = soc_property_port_get(unit, port,
     73             spn_SCHEDULER_PROFILE_MAP, scheduler_port_profile_map[port]);
     74     }
     75 
     76 
     77     for (idx = 0; idx < SOC_TH3_MAX_NUM_SCHED_PROFILE; idx++) {
     78         /* sched_profile<idx>.profile_valid=1*/
     79         sal_sprintf(name, "%s_%d.%s",
     80                     spn_SCHEDULER_PROFILE, idx, spn_PROFILE_VALID);
     81         sched_profile[idx].valid = soc_property_get(unit, name, sched_profile[idx].valid);
     82         sal_sprintf(name, "%s_%d.%s",
     83                     spn_SCHEDULER_PROFILE, idx, spn_NUM_UNICAST_QUEUE);
     84         (void)soc_property_get_csv(unit, name, 12,
     85                                         sched_profile[idx].num_unicast_queue);
     86         sal_sprintf(name, "%s_%d.%s",
     87                     spn_SCHEDULER_PROFILE, idx, spn_NUM_MULTICAST_QUEUE);
     88         (void)soc_property_get_csv(unit, name, 12,
     89                                         sched_profile[idx].num_multicast_queue);
     90         sal_sprintf(name, "%s_%d.%s",
     91                     spn_SCHEDULER_PROFILE, idx, spn_SCHED_STRICT_PRIORITY);
     92         (void)soc_property_get_csv(unit, name, 12,
     93                                         sched_profile[idx].strict_priority);
     94         sal_sprintf(name, "%s_%d.%s",
     95                     spn_SCHEDULER_PROFILE, idx, spn_FLOW_CONTROL_ONLY_UNICAST);
     96         (void)soc_property_get_csv(unit, name, 12,
     97                                         sched_profile[idx].flow_control_only_unicast);
     98     }
     99 
    100     return SOC_E_NONE;
    101 }
    102 
    103 /*! @fn void _soc_mmu_tomahawk3_scheduler_profile_reset(
    104  *    int unit,
    105  *    _soc_mmu_cfg_scheduler_profile_t *sched_profile,
    106  *  @param unit Chip unit number.
    107  *  @param sched_profile, Pointer to _soc_mmu_cfg_scheduler_profile_t structure
    108  *  @brief Function to reset sched_profile structure
    109  * Description:
    110  *      Function to reset sched_profile structure
    111  * Parameters:
    112  *      unit - Device number
    113  *      sched_profile - _soc_mmu_cfg_scheduler_profile_t structure
    114  * Return Value:
    115  *      SUCCESS/FAILURE
    116  */
    117 int
    118 _soc_mmu_tomahawk3_scheduler_profile_reset(int unit,
    119              _soc_mmu_cfg_scheduler_profile_t *sched_profile)
    120 {
    121     int idx, cosq_idx;
    122     int num_ucq = 0;
    123 
    124     if (sched_profile == NULL) {
    125         return SOC_E_MEMORY;
    126     }
    127 
    128     num_ucq = _soc_th3_get_num_ucq(unit);
    129 
    130     for (idx = 0; idx < SOC_TH3_MAX_NUM_SCHED_PROFILE; idx++) {
    131         for (cosq_idx = 0; cosq_idx < SOC_TH3_COS_MAX; cosq_idx++) {
    132             /* Default scheduler profile 0 is setup with default values */
    133             if (idx == 0) {
    134                 if (cosq_idx < num_ucq) {
    135                     sched_profile[idx].num_unicast_queue[cosq_idx] = 1;
    136                     sched_profile[idx].num_multicast_queue[cosq_idx] = 0;
    137                 } else {
    138                     sched_profile[idx].num_unicast_queue[cosq_idx] = 0;
    139                     sched_profile[idx].num_multicast_queue[cosq_idx] = 1;
    140                 }
    141                 sched_profile[idx].valid = 1;
    142                 sched_profile[idx].strict_priority[cosq_idx] = 0;
    143                 sched_profile[idx].flow_control_only_unicast[cosq_idx] = 0;
    144             } else {
    145                 sched_profile[idx].num_unicast_queue[cosq_idx] = -1;
    146                 sched_profile[idx].num_multicast_queue[cosq_idx] = -1;
    147                 sched_profile[idx].strict_priority[cosq_idx] = -1;
    148                 sched_profile[idx].flow_control_only_unicast[cosq_idx] = -1;
    149                 sched_profile[idx].valid = 0;
    150             }
    151         }
    152     }
    153     return SOC_E_NONE;
    154 
    155 }
    156 
    157 /*! @fn int _soc_mmu_tomahawk3_scheduler_profile_config_check(
    158  *    int unit,
    159  *    _soc_mmu_cfg_scheduler_profile_t *sched_profile,
    160  *  @param unit Chip unit number.
    161  *  @param sched_profile, Pointer to _soc_mmu_cfg_scheduler_profile_t structure
    162  *  @brief Function to check if config bcm settings are valid
    163  * Description:
    164  *      Function to check if config bcm settings are valid
    165  * Parameters:
    166  *      unit - Device number
    167  *      idx - Profile index
    168  *      sched_profile - _soc_mmu_cfg_scheduler_profile_t structure
    169  * Return Value:
    170  *      SUCCESS/FAILURE
    171  */
    172 int
    173 _soc_mmu_tomahawk3_scheduler_profile_config_check(int unit, int idx,
    174              _soc_mmu_cfg_scheduler_profile_t *sched_profile)
    175 {
    176     int idx1, cosq_idx;
    177     int total_numq, total_num_ucq, total_num_mcq = 0;
    178     int num_uc_q, num_mc_q;
    179     int current_cosq_idx;
    180 
    181     num_uc_q = _soc_th3_get_num_ucq(unit);
    182     num_mc_q = _soc_th3_get_num_mcq(unit);
    183 
    184     total_num_ucq = 0;
    185     total_num_mcq = 0;
    186     current_cosq_idx = 0;
    187 
    188     for (idx1 = 0; idx1 < SOC_TH3_COS_MAX; idx1++) {
    189         /* Get total number of UC queues */
    190         if (sched_profile[idx].num_unicast_queue[idx1] != -1) {
    191             total_num_ucq += sched_profile[idx].num_unicast_queue[idx1];
    192         }
    193         /* Get total number of MC queues */
    194         if (sched_profile[idx].num_multicast_queue[idx1] != -1) {
    195             total_num_mcq += sched_profile[idx].num_multicast_queue[idx1];
    196         }
    197     }
    198 
    199     /* Total number of UC and MC Queues cannot exceed those
    200        specified by mcq mode */
    201     if (total_num_ucq > num_uc_q) {
    202         LOG_INFO(BSL_LS_SOC_COMMON,
    203                 (BSL_META_U(unit, "Profile %d Max unicast queues per port is %d\n"),
    204                 idx, num_uc_q));
    205         return SOC_E_FAIL;
    206     }
    207     if (total_num_mcq > num_mc_q) {
    208         LOG_INFO(BSL_LS_SOC_COMMON,
    209                 (BSL_META_U(unit, "Profile %d Max multicast queues per port is %d\n"),
    210                 idx, num_mc_q));
    211        return SOC_E_FAIL;
    212     }
    213 
    214 
    215     for (cosq_idx = 0; cosq_idx < SOC_TH3_COS_MAX; cosq_idx++) {
    216         /* All possible legal configs are UC+UC, UC+MC, UC, MC, NONE */
    217         if ((sched_profile[idx].num_multicast_queue[cosq_idx] +
    218              sched_profile[idx].num_unicast_queue[cosq_idx]) > 2 ) {
    219             LOG_INFO(BSL_LS_SOC_COMMON,
    220                 (BSL_META_U(unit, "Profile %d Max unicast + multicast queues per cos is 2\n"), idx));
    221             return SOC_E_FAIL;
    222         }
    223         if (sched_profile[idx].num_unicast_queue[cosq_idx] > 2) {
    224             LOG_INFO(BSL_LS_SOC_COMMON,
    225                 (BSL_META_U(unit, "Profile %d Max unicast queues per cos is 2\n"), idx));
    226             return SOC_E_FAIL;
    227         }
    228         if (sched_profile[idx].num_multicast_queue[cosq_idx] > 1) {
    229             LOG_INFO(BSL_LS_SOC_COMMON,
    230                 (BSL_META_U(unit, "Profile %d Max multicast queues per cos is 2\n"), idx));
    231             return SOC_E_FAIL;
    232         }
    233 
    234         /* Make sure that L0->L1 node connection possible */
    235         /* L1.n can connect to L0.n and L0.n+1 only */
    236         /* L1.11 can connect to L0.11 only */
    237         total_numq = sched_profile[idx].num_unicast_queue[cosq_idx] +
    238                      sched_profile[idx].num_multicast_queue[cosq_idx];
    239 
    240         if ((total_numq > 0) && (current_cosq_idx == SOC_TH3_COS_MAX)) {
    241             LOG_INFO(BSL_LS_SOC_COMMON,
    242                 (BSL_META_U(unit, "[1] Profile %d cos %d Cos to queue mapping error\n"),
    243                 idx, cosq_idx));
    244             return SOC_E_FAIL;
    245         }
    246 
    247         if (total_numq == 2) {
    248             current_cosq_idx += 2;
    249         } else if (total_numq == 1) {
    250             current_cosq_idx += 1;
    251         } else {
    252             continue;
    253         }
    254     }
    255     return SOC_E_NONE;
    256 }
    257 
    258 
    259 /*! @fn int _soc_mmu_tomahawk3_scheduler_profile_check(
    260  *    int unit,
    261  *    _soc_mmu_cfg_scheduler_profile_t *sched_profile,
    262  *  @param unit Chip unit number.
    263  *  @param sched_profile, Pointer to _soc_mmu_cfg_scheduler_profile_t structure
    264  *  @brief Function to check if config bcm settings are valid
    265  * Description:
    266  *      Function to check if config bcm settings are valid
    267  * Parameters:
    268  *      unit - Device number
    269  *      sched_profile - _soc_mmu_cfg_scheduler_profile_t structure
    270  * Return Value:
    271  *      SUCCESS/FAILURE
    272  */
    273 int
    274 _soc_mmu_tomahawk3_scheduler_profile_check(int unit,
    275              _soc_mmu_cfg_scheduler_profile_t *sched_profile)
    276 {
    277     int idx;
    278 
    279     for (idx = 0; idx < SOC_TH3_MAX_NUM_SCHED_PROFILE; idx++) {
    280         if (sched_profile[idx].valid != 1) {
    281             LOG_INFO(BSL_LS_SOC_COMMON,
    282                 (BSL_META_U(unit, "Skipping invalid scheduler profile %d\n"), idx));
    283             continue;
    284         }
    285         SOC_IF_ERROR_RETURN(_soc_mmu_tomahawk3_scheduler_profile_config_check(unit,
    286                            idx, sched_profile));
    287 
    288     }
    289 
    290     return SOC_E_NONE;
    291 }
    292 
    293 int _soc_scheduler_profile_mapping_setup(int unit, _soc_mmu_cfg_scheduler_profile_t *sched_profile,
    294                                          int profile_index, int *L0, int *schedq, int *mmuq,
    295                                          int *cos_list, int *strict_priority, int *fc_is_uc_only)
    296 {
    297     int mcq_base, ucq_base;
    298     int total_numq, num_ucq, num_mcq;
    299     int sp, fc_uc;
    300     int cosq_idx;
    301     int current_q_pos = 0;
    302 
    303     ucq_base = 0;
    304     mcq_base = _soc_th3_get_num_ucq(unit);
    305 
    306     if ((sched_profile == NULL) ||
    307         (L0 == NULL) ||
    308         (schedq == NULL) ||
    309         (cos_list == NULL) ||
    310         (strict_priority == NULL) ||
    311         (fc_is_uc_only == NULL) ||
    312         (mmuq == NULL)) {
    313         return SOC_E_MEMORY;
    314     }
    315 
    316     if (profile_index < 0 || profile_index >= SOC_TH3_MAX_NUM_SCHED_PROFILE) {
    317         return SOC_E_PARAM;
    318     }
    319 
    320     for (cosq_idx = 0; cosq_idx < SOC_TH3_COS_MAX; cosq_idx++) {
    321         cos_list[cosq_idx] = -1;
    322         strict_priority[cosq_idx] = 0;
    323         fc_is_uc_only[cosq_idx] = 0;
    324     }
    325 
    326     for (cosq_idx = 0; cosq_idx < SOC_TH3_COS_MAX; cosq_idx++) {
    327         if ((sched_profile[profile_index].num_unicast_queue[cosq_idx] == -1) &&
    328             (sched_profile[profile_index].num_multicast_queue[cosq_idx] == -1)) {
    329             LOG_INFO(BSL_LS_SOC_COMMON,
    330                 (BSL_META_U(unit, "Profile %d Not a valid cos %d\n"),
    331                 profile_index, cosq_idx));
    332             continue;
    333         }
    334 
    335         total_numq = sched_profile[profile_index].num_unicast_queue[cosq_idx] +
    336                      sched_profile[profile_index].num_multicast_queue[cosq_idx];
    337         num_ucq = sched_profile[profile_index].num_unicast_queue[cosq_idx];
    338         num_mcq = sched_profile[profile_index].num_multicast_queue[cosq_idx];
    339         sp = sched_profile[profile_index].strict_priority[cosq_idx];
    340         fc_uc = sched_profile[profile_index].flow_control_only_unicast[cosq_idx];
    341 
    342         if (total_numq == 0) {
    343             continue;
    344         }
    345 
    346         if (current_q_pos == SOC_TH3_COS_MAX) {
    347             return SOC_E_FAIL;
    348         }
    349 
    350         if (total_numq == 2) {
    351             L0[current_q_pos] = current_q_pos+1;
    352             L0[current_q_pos+1] = current_q_pos+1;
    353             schedq[current_q_pos] = current_q_pos;
    354             schedq[current_q_pos+1] = current_q_pos+1;
    355             cos_list[current_q_pos] = cosq_idx;
    356             cos_list[current_q_pos+1] = cosq_idx;
    357             strict_priority[current_q_pos] = sp;
    358             strict_priority[current_q_pos+1] = sp;
    359             fc_is_uc_only[current_q_pos] = fc_uc;
    360             fc_is_uc_only[current_q_pos+1] = fc_uc;
    361             if (num_ucq == 2) {
    362                 mmuq[current_q_pos] = ucq_base++;
    363                 mmuq[current_q_pos+1] = ucq_base++;
    364             }
    365             else if ((num_ucq == 1) && (num_mcq == 1)) {
    366                 mmuq[current_q_pos] = ucq_base++;
    367                 mmuq[current_q_pos+1] = mcq_base++;
    368             }
    369             current_q_pos += 2;
    370         } else if (total_numq == 1) {
    371             L0[current_q_pos] = current_q_pos;
    372             schedq[current_q_pos] = current_q_pos;
    373             cos_list[current_q_pos] = cosq_idx;
    374             strict_priority[current_q_pos] = sp;
    375             fc_is_uc_only[current_q_pos] = fc_uc;
    376             if (num_ucq == 1) {
    377                 mmuq[current_q_pos] = ucq_base++;
    378             }
    379             else if (num_mcq == 1) {
    380                 mmuq[current_q_pos] = mcq_base++;
    381             }
    382             current_q_pos += 1;
    383         } else {
    384             return SOC_E_PARAM;
    385         }
    386     }
    387 
    388     for (cosq_idx = 0; cosq_idx <  SOC_TH3_COS_MAX; cosq_idx++) {
    389         LOG_INFO(BSL_LS_SOC_COSQ,
    390             (BSL_META_U(unit, "Profile %d cos %d L0 %d schedq %d mmuq %d cos_list %d strict_priority %d\n"),
    391             profile_index, cosq_idx, L0[cosq_idx], schedq[cosq_idx],
    392             mmuq[cosq_idx], cos_list[cosq_idx], strict_priority[cosq_idx]));
    393     }
    394     return SOC_E_NONE;
    395 }
    396 
    397 
    398 #endif  /* defined (BCM_TOMAHAWK3_SUPPORT) */