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) */