cosq.c (100070B)
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 * MMU/Cosq soc routines 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <soc/debug.h> 14 #include <soc/util.h> 15 #include <soc/mem.h> 16 #include <soc/triumph3.h> 17 18 #if defined(BCM_TRIUMPH3_SUPPORT) 19 20 #define _SOC_TR3_ROOT_SCHEDULER_INDEX(u,p) \ 21 SOC_INFO((u)).port_p2m_mapping[SOC_INFO((u)).port_l2p_mapping[(p)]] 22 23 #define _SOC_TR3_DEF_SCHED_NODE_BASE(u,p,cfg,t) \ 24 (cfg)[(t)].base_factor * (p) 25 26 #define _SOC_TR3_IS_HSP_PORT(u,p) \ 27 ((IS_CE_PORT((u),(p))) || \ 28 ((IS_HG_PORT((u),(p))) && (SOC_INFO((u)).port_speed_max[(p)] >= 100000))) 29 30 #define _SOC_TR3_LLS_OP_TEAR 0 31 #define _SOC_TR3_LLS_OP_SETUP 1 32 #define _SOC_TR3_LLS_OP_TRAVERSE 2 33 34 #define _SOC_TR3_DYN_SET 4 35 36 static int _soc_tr3_init_done[SOC_MAX_NUM_DEVICES] = {0}; 37 static int _tr3_invalid_ptr[SOC_MAX_NUM_DEVICES][SOC_TR3_NODE_LVL_MAX]; 38 static int _tr2_node_max[SOC_MAX_NUM_DEVICES][SOC_TR3_NODE_LVL_MAX]; 39 40 typedef struct _soc_tr3_b0_cb_s { 41 sal_mutex_t lock; 42 int port[_SOC_TR3_DYN_SET]; 43 } _soc_tr3_b0_cb_t; 44 45 static _soc_tr3_b0_cb_t _tr3_b0_unit_data[SOC_MAX_NUM_DEVICES]; 46 47 int _bcm_tr3_port_sdyn[SOC_MAX_NUM_DEVICES][SOC_PBMP_PORT_MAX]; 48 int _bcm_tr3_port_numq[SOC_MAX_NUM_DEVICES][SOC_PBMP_PORT_MAX]; 49 50 STATIC int _soc_tr3_alloc_dyn_set(int unit, int port, 51 soc_reg_t *r_a, soc_reg_t *r_b, soc_reg_t *r_ctrl) 52 { 53 _soc_tr3_b0_cb_t *pcb; 54 int ii, empty_at = -1, rv = SOC_E_NONE; 55 soc_reg_t dyn_change_a[] = { 56 LLS_SP_WERR_DYN_CHANGE_0Ar, 57 LLS_SP_WERR_DYN_CHANGE_1Ar, 58 LLS_SP_WERR_DYN_CHANGE_2Ar, 59 LLS_SP_WERR_DYN_CHANGE_3Ar 60 }; 61 soc_reg_t dyn_change_b[] = { 62 LLS_SP_WERR_DYN_CHANGE_0Br, 63 LLS_SP_WERR_DYN_CHANGE_1Br, 64 LLS_SP_WERR_DYN_CHANGE_2Br, 65 LLS_SP_WERR_DYN_CHANGE_3Br 66 }; 67 68 soc_reg_t dyn_change_ctrl[] = { 69 LLS_SP_WERR_DYN_CHANGE_0r, 70 LLS_SP_WERR_DYN_CHANGE_1r, 71 LLS_SP_WERR_DYN_CHANGE_2r, 72 LLS_SP_WERR_DYN_CHANGE_3r 73 }; 74 75 pcb = &_tr3_b0_unit_data[unit]; 76 77 sal_mutex_take(pcb->lock, sal_sem_FOREVER); 78 for (ii = 0; ii < _SOC_TR3_DYN_SET; ii++) { 79 if (pcb->port[ii] == -1) { 80 empty_at = ii; 81 } else if (pcb->port[ii] == port) { 82 rv = SOC_E_BUSY; 83 break; 84 } 85 } 86 87 if (!rv && (empty_at >= 0)) { 88 pcb->port[empty_at] = port; 89 } 90 91 sal_mutex_give(pcb->lock); 92 93 if (rv) { 94 return rv; 95 } 96 97 if (empty_at == -1) { 98 return SOC_E_BUSY; 99 } 100 101 *r_a = dyn_change_a[empty_at]; 102 *r_b = dyn_change_b[empty_at]; 103 *r_ctrl = dyn_change_ctrl[empty_at]; 104 105 return SOC_E_NONE; 106 } 107 108 STATIC int _soc_tr3_free_dyn_set(int unit, int port) 109 { 110 _soc_tr3_b0_cb_t *pcb; 111 int ii; 112 113 pcb = &_tr3_b0_unit_data[unit]; 114 115 sal_mutex_take(pcb->lock, sal_sem_FOREVER); 116 for (ii = 0; ii < _SOC_TR3_DYN_SET; ii++) { 117 if (pcb->port[ii] == port) { 118 pcb->port[ii] = -1; 119 } 120 } 121 sal_mutex_give(pcb->lock); 122 123 return SOC_E_NONE; 124 } 125 126 int 127 soc_tr3_cosq_set_sched_parent(int unit, soc_port_t port, 128 int level, int hw_index, 129 int parent_hw_idx) 130 { 131 uint32 entry[SOC_MAX_MEM_WORDS]; 132 soc_mem_t mem; 133 uint32 *bmap = NULL; 134 135 mem = _SOC_TR3_NODE_PARENT_MEM(level); 136 137 LOG_INFO(BSL_LS_SOC_COSQ, 138 (BSL_META_U(unit, 139 "Port:%d L%d : %d parent:%d\n"), 140 port, level - 1, hw_index, parent_hw_idx)); 141 /* For HSP port we don't need to set LLS mem */ 142 if (_SOC_TR3_IS_HSP_PORT(unit, port)) { 143 return SOC_E_NONE; 144 } 145 146 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 147 148 soc_mem_field32_set(unit, mem, entry, C_PARENTf, parent_hw_idx); 149 150 SOC_IF_ERROR_RETURN 151 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 152 153 if (level == SOC_TR3_NODE_LVL_L0) { 154 bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 155 } else if (level == SOC_TR3_NODE_LVL_L1) { 156 bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 157 } else if (level == SOC_TR3_NODE_LVL_L2) { 158 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 159 } 160 if (bmap != NULL) { 161 SOC_LLS_SCHEDULER_LOCK(unit); 162 if (parent_hw_idx == _soc_tr3_invalid_parent_index(unit, level)) { 163 SHR_BITCLR(bmap, hw_index); 164 } else { 165 SHR_BITSET(bmap, hw_index); 166 } 167 SOC_LLS_SCHEDULER_UNLOCK(unit); 168 } 169 return SOC_E_NONE; 170 } 171 172 int 173 soc_tr3_sched_weight_set(int unit, int level, int index, int weight) 174 { 175 soc_mem_t mem_weight; 176 uint32 entry[SOC_MAX_MEM_WORDS]; 177 178 mem_weight = _SOC_TR3_NODE_WIEGHT_MEM(level); 179 if (mem_weight <= 0) { 180 return SOC_E_PARAM; 181 } 182 183 SOC_IF_ERROR_RETURN 184 (soc_mem_read(unit, mem_weight, MEM_BLOCK_ALL, index, &entry)); 185 186 soc_mem_field32_set(unit, mem_weight, &entry, C_WEIGHTf, weight); 187 188 SOC_IF_ERROR_RETURN 189 (soc_mem_write(unit, mem_weight, MEM_BLOCK_ALL, index, &entry)); 190 191 LOG_INFO(BSL_LS_SOC_COSQ, 192 (BSL_META_U(unit, 193 "sched_weight_set L%d index=%d wt=%d\n"), 194 level, index, weight)); 195 return SOC_E_NONE; 196 } 197 198 int 199 soc_tr3_sched_weight_get(int unit, int level, int index, int *weight) 200 { 201 soc_mem_t mem_weight; 202 uint32 entry[SOC_MAX_MEM_WORDS]; 203 204 mem_weight = _SOC_TR3_NODE_WIEGHT_MEM(level); 205 if (mem_weight <= 0) { 206 return SOC_E_PARAM; 207 } 208 209 SOC_IF_ERROR_RETURN 210 (soc_mem_read(unit, mem_weight, MEM_BLOCK_ALL, index, &entry)); 211 212 *weight = soc_mem_field32_get(unit, mem_weight, &entry, C_WEIGHTf); 213 214 LOG_INFO(BSL_LS_SOC_COSQ, 215 (BSL_META_U(unit, 216 "sched_weight_get L%d index=%d wt=%d\n"), 217 level, index, *weight)); 218 return SOC_E_NONE; 219 } 220 221 int 222 soc_tr3_cosq_set_sched_child_config_dynamic(int unit, soc_port_t port, 223 int level, int index, 224 int num_spri, int first_child, 225 int first_mc_child, uint32 ucmap, 226 uint32 spmap, int child_index) 227 { 228 uint32 entry[SOC_MAX_MEM_WORDS], rval, d32, timeout_val; 229 soc_mem_t mem; 230 int rv = SOC_E_NONE; 231 soc_reg_t r_a = INVALIDr, r_b = INVALIDr, r_ctrl = INVALIDr; 232 soc_timeout_t timeout; 233 234 SOC_IF_ERROR_RETURN(READ_LLS_CONFIG0r(unit, &rval)); 235 if (!soc_reg_field_get(unit, LLS_CONFIG0r, rval, SPRI_VECT_MODE_ENABLEf)) { 236 soc_reg_field_set(unit, LLS_CONFIG0r, &rval, SPRI_VECT_MODE_ENABLEf, 1); 237 SOC_IF_ERROR_RETURN(WRITE_LLS_CONFIG0r(unit, rval)); 238 } 239 240 mem = _SOC_TR3_NODE_CONFIG_MEM(level); 241 if (mem == INVALIDm) { 242 return SOC_E_INTERNAL; 243 } 244 245 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 246 247 LOG_INFO(BSL_LS_SOC_COSQ, 248 (BSL_META_U(unit, 249 "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x NUMSP=%d\n"), 250 port, (level==0) ? "r" : "", level - 1, 251 index, first_child, first_mc_child, ucmap, num_spri)); 252 253 mem = _SOC_TR3_NODE_CONFIG_MEM(level); 254 SOC_IF_ERROR_RETURN( 255 soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 256 soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, spmap & 0xf); 257 soc_mem_field32_set(unit, mem, &entry, P_VECT_SPRI_7_4f, (spmap >> 4) & 0xf); 258 259 if (mem == LLS_L1_CONFIGm) { 260 soc_mem_field32_set(unit, mem, &entry, P_START_UC_SPRIf, first_child); 261 soc_mem_field32_set(unit, mem, &entry, P_START_MC_SPRIf, 262 first_mc_child); 263 soc_mem_field32_set(unit, mem, &entry, P_SPRI_SELECTf, (num_spri > 0) ? ucmap : 0); 264 } else { 265 soc_mem_field32_set(unit, mem, &entry, P_START_SPRIf, first_child); 266 } 267 268 SOC_IF_ERROR_RETURN(_soc_tr3_alloc_dyn_set(unit, port, 269 &r_a, &r_b, &r_ctrl)); 270 271 rval = 0; 272 soc_bits_get(entry, 0, 31, &d32); 273 soc_reg_field_set(unit, r_b, &rval, LLS_PARENT_CONFIG_31_0f, d32); 274 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_b, REG_PORT_ANY, 0, rval)); 275 276 rval = 0; 277 soc_reg_field_set(unit, r_a, &rval, NODE_LEVELf, level + 1); 278 soc_reg_field_set(unit, r_a, &rval, NODE_IDf, child_index); 279 soc_reg_field_set(unit, r_a, &rval, PARENT_IDf, index); 280 soc_bits_get(entry, 32, 39, &d32); 281 soc_reg_field_set(unit, r_a, &rval, LLS_PARENT_CONFIG_39_32f, d32); 282 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_a, REG_PORT_ANY, 0, rval)); 283 284 rval = 0; 285 soc_reg_field_set(unit, r_ctrl, &rval, IN_USEf, 1); 286 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_ctrl, REG_PORT_ANY, 0, rval)); 287 288 if (!SAL_BOOT_SIMULATION) { 289 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000); 290 soc_timeout_init(&timeout, timeout_val, 0); 291 292 do { 293 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, r_ctrl, REG_PORT_ANY, 0, &rval)); 294 if (soc_timeout_check(&timeout)) { 295 rv = SOC_E_TIMEOUT; 296 break; 297 } 298 } while (soc_reg_field_get(unit, r_ctrl, rval, IN_USEf)); 299 } 300 301 SOC_IF_ERROR_RETURN(_soc_tr3_free_dyn_set(unit, port)); 302 303 return rv; 304 } 305 306 int 307 soc_tr3_cosq_set_sched_child_config(int unit, soc_port_t port, 308 int level, int index, 309 int num_spri, int first_child, 310 int first_mc_child, uint32 ucmap, 311 uint32 spmap) 312 { 313 uint32 entry[SOC_MAX_MEM_WORDS]; 314 soc_mem_t mem; 315 int sch_index; 316 int sp_vec = soc_feature(unit, soc_feature_tr3_sp_vector_mask); 317 318 mem = _SOC_TR3_NODE_CONFIG_MEM(level); 319 if (mem == INVALIDm) { 320 return SOC_E_INTERNAL; 321 } 322 323 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 324 325 LOG_INFO(BSL_LS_SOC_COSQ, 326 (BSL_META_U(unit, 327 "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x NUMSP=%d\n"), 328 port, (level==0) ? "r" : "", level - 1, 329 index, first_child, first_mc_child, ucmap, num_spri)); 330 331 sch_index = index; 332 mem = _SOC_TR3_NODE_CONFIG_MEM(level); 333 SOC_IF_ERROR_RETURN( 334 soc_mem_read(unit, mem, MEM_BLOCK_ALL, sch_index, &entry)); 335 if (sp_vec) { 336 soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, spmap & 0xf); 337 soc_mem_field32_set(unit, mem, &entry, P_VECT_SPRI_7_4f, (spmap >> 4) & 0xf); 338 } else { 339 soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, num_spri); 340 } 341 342 if (mem == LLS_L1_CONFIGm) { 343 soc_mem_field32_set(unit, mem, &entry, P_START_UC_SPRIf, first_child); 344 soc_mem_field32_set(unit, mem, &entry, P_START_MC_SPRIf, 345 first_mc_child); 346 soc_mem_field32_set(unit, mem, &entry, P_SPRI_SELECTf, (num_spri > 0) ? ucmap : 0); 347 } else { 348 soc_mem_field32_set(unit, mem, &entry, P_START_SPRIf, first_child); 349 } 350 351 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, sch_index, &entry)); 352 353 return SOC_E_NONE; 354 } 355 356 int 357 soc_tr3_cosq_set_sched_mode(int unit, soc_port_t port, int level, int index, 358 soc_tr3_sched_mode_e mode, int weight) 359 { 360 uint32 entry[SOC_MAX_MEM_WORDS], fval; 361 soc_mem_t mem; 362 363 if (mode == SOC_TR3_SCHED_MODE_STRICT) { 364 weight = 0; 365 } 366 367 if ((!soc_property_get(unit, spn_BCM5664X_WRR_GRANULARITY_1, 0)) && 368 (mode == SOC_TR3_SCHED_MODE_WRR)) { 369 weight *= 2; 370 } 371 372 SOC_IF_ERROR_RETURN(soc_tr3_sched_weight_set(unit, level, index, weight)); 373 374 if (mode != SOC_TR3_SCHED_MODE_STRICT) { 375 mem = _SOC_TR3_NODE_CONFIG_MEM(SOC_TR3_NODE_LVL_ROOT); 376 index = _SOC_TR3_ROOT_SCHEDULER_INDEX(unit, port); 377 SOC_IF_ERROR_RETURN( 378 soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 379 380 fval = (mode == SOC_TR3_SCHED_MODE_WRR) ? 1 : 0; 381 if (soc_mem_field32_get(unit, mem, entry, 382 PACKET_MODE_WRR_ACCOUNTING_ENABLEf) != fval) { 383 soc_mem_field32_set(unit, mem, entry, 384 PACKET_MODE_WRR_ACCOUNTING_ENABLEf, fval); 385 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry)); 386 } 387 } 388 389 return SOC_E_NONE; 390 } 391 392 int 393 soc_tr3_cosq_set_sched_config(int unit, soc_port_t port, 394 int level, int index, int child_index, 395 int num_spri, int first_child, 396 int first_mc_child, uint32 ucmap, uint32 spmap, 397 soc_tr3_sched_mode_e mode, int weight) 398 { 399 int child_level; 400 int sp_vec = soc_feature(unit, soc_feature_tr3_sp_vector_mask); 401 int enable_dynamic = 1; 402 403 #ifdef PLISIM 404 if (SAL_BOOT_PLISIM) { 405 enable_dynamic = 0; 406 } 407 #endif 408 409 if (level >= SOC_TR3_NODE_LVL_L2) { 410 return SOC_E_PARAM; 411 } 412 413 /* 414 * COVERITY 415 * 416 * enable_dynamic variable is by default 1 and gets assigned to 0 if PLISIM is defined. 417 * So ignore the coverity warning below 418 */ 419 if (sp_vec && enable_dynamic) { 420 SOC_IF_ERROR_RETURN(soc_tr3_cosq_set_sched_child_config_dynamic(unit, port, 421 level, index, num_spri, first_child, 422 /* coverity[dead_error_begin] */ 423 first_mc_child, ucmap, spmap, child_index)); 424 } else { 425 SOC_IF_ERROR_RETURN(soc_tr3_cosq_set_sched_child_config(unit, port, 426 level, index, num_spri, first_child, first_mc_child, ucmap, spmap)); 427 } 428 429 if (child_index >= 0) { 430 soc_tr3_get_child_type(unit, port, level, &child_level); 431 SOC_IF_ERROR_RETURN(soc_tr3_cosq_set_sched_mode(unit, port, child_level, 432 child_index, mode, weight)); 433 } 434 435 return SOC_E_NONE; 436 } 437 438 int 439 soc_tr3_sched_get_node_config(int unit, soc_port_t port, int level, int index, 440 int *pnum_spri, int *pfirst_child, 441 int *pfirst_mc_child, uint32 *pucmap, 442 uint32 *pspmap) 443 { 444 uint32 entry[SOC_MAX_MEM_WORDS]; 445 soc_mem_t mem; 446 uint32 num_spri = 0, ucmap = 0, f1, f2; 447 int first_child = -1, first_mc_child = -1, ii; 448 int sp_vec = soc_feature(unit, soc_feature_tr3_sp_vector_mask); 449 450 *pspmap = 0; 451 452 mem = _SOC_TR3_NODE_CONFIG_MEM(level); 453 if (mem == INVALIDm) { 454 return SOC_E_INTERNAL; 455 } 456 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 457 if (sp_vec) { 458 f1 = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf); 459 f2 = soc_mem_field32_get(unit, mem, &entry, P_VECT_SPRI_7_4f); 460 *pspmap = f1 | (f2 << 4); 461 for (ii = 0; ii < 32; ii++) { 462 if ((1 << ii) & *pspmap) { 463 num_spri++; 464 } 465 } 466 } else { 467 num_spri = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf); 468 } 469 470 if (mem == LLS_L1_CONFIGm) { 471 first_child = soc_mem_field32_get(unit, mem, &entry, P_START_UC_SPRIf); 472 first_mc_child = soc_mem_field32_get(unit, mem, 473 &entry, P_START_MC_SPRIf); 474 ucmap = soc_mem_field32_get(unit, mem, &entry, P_SPRI_SELECTf); 475 } else { 476 first_child = soc_mem_field32_get(unit, mem, &entry, P_START_SPRIf); 477 first_mc_child = 0; 478 } 479 480 if (num_spri == 0) { 481 ucmap = 0; 482 } 483 484 if (pnum_spri) { 485 *pnum_spri = num_spri; 486 } 487 488 if (pucmap) { 489 *pucmap = ucmap; 490 } 491 492 if (pfirst_child) { 493 *pfirst_child = first_child; 494 } 495 496 if (pfirst_mc_child) { 497 *pfirst_mc_child = first_mc_child; 498 } 499 return SOC_E_NONE; 500 } 501 502 int 503 soc_tr3_cosq_get_sched_mode(int unit, soc_port_t port, int level, int index, 504 soc_tr3_sched_mode_e *pmode, int *weight) 505 { 506 uint32 entry[SOC_MAX_MEM_WORDS]; 507 soc_mem_t mem; 508 soc_tr3_sched_mode_e mode = SOC_TR3_SCHED_MODE_UNKNOWN; 509 510 SOC_IF_ERROR_RETURN(soc_tr3_sched_weight_get(unit, level, index, weight)); 511 512 if (*weight == 0) { 513 mode = SOC_TR3_SCHED_MODE_STRICT; 514 } else { 515 mem = _SOC_TR3_NODE_CONFIG_MEM(SOC_TR3_NODE_LVL_ROOT); 516 index = _SOC_TR3_ROOT_SCHEDULER_INDEX(unit, port); 517 SOC_IF_ERROR_RETURN( 518 soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 519 if (soc_mem_field32_get(unit, mem, entry, PACKET_MODE_WRR_ACCOUNTING_ENABLEf)) { 520 mode = SOC_TR3_SCHED_MODE_WRR; 521 if (!soc_property_get(unit, spn_BCM5664X_WRR_GRANULARITY_1, 0)) { 522 *weight /= 2; 523 } 524 } else { 525 mode = SOC_TR3_SCHED_MODE_WDRR; 526 } 527 } 528 529 if (pmode) { 530 *pmode = mode; 531 } 532 533 return SOC_E_NONE; 534 } 535 536 int 537 soc_tr3_cosq_get_sched_config(int unit, soc_port_t port, 538 int level, int index, int child_index, 539 int *pnum_spri, int *pfirst_child, 540 int *pfirst_mc_child, uint32 *pucmap, uint32 *pspmap, 541 soc_tr3_sched_mode_e *pmode, int *weight) 542 { 543 int child_level; 544 545 if (level >= SOC_TR3_NODE_LVL_L2) { 546 return SOC_E_PARAM; 547 } 548 549 SOC_IF_ERROR_RETURN(soc_tr3_sched_get_node_config(unit, port, level, 550 index, pnum_spri, pfirst_child, pfirst_mc_child, pucmap, 551 pspmap)); 552 553 if (child_index >= 0) { 554 soc_tr3_get_child_type(unit, port, level, &child_level); 555 556 SOC_IF_ERROR_RETURN( 557 soc_tr3_cosq_get_sched_mode(unit, port, child_level, child_index, 558 pmode, weight)); 559 } 560 561 return SOC_E_NONE; 562 } 563 564 int soc_tr3_get_child_type(int unit, soc_port_t port, int level, 565 int *child_type) 566 { 567 *child_type = -1; 568 569 if (level == SOC_TR3_NODE_LVL_ROOT) { 570 *child_type = SOC_TR3_NODE_LVL_L0; 571 } else if (level == SOC_TR3_NODE_LVL_L0) { 572 *child_type = (_SOC_TR3_IS_HSP_PORT(unit, port)) ? 573 SOC_TR3_NODE_LVL_L2 : SOC_TR3_NODE_LVL_L1; 574 } else if (level == SOC_TR3_NODE_LVL_L1) { 575 *child_type = SOC_TR3_NODE_LVL_L2; 576 } 577 return SOC_E_NONE; 578 } 579 580 int 581 soc_tr3_hsp_sched_weight_set(int unit, int port, int cosq, int weight, int adjust_cos) 582 { 583 /* COS 0 reserved for MG group mode (currenly unsupported) */ 584 const int adjusted_cosq = cosq + adjust_cos; 585 uint32 rval = 0; 586 uint32 spmap; 587 588 if (!_SOC_TR3_IS_HSP_PORT(unit, port)) { 589 return SOC_E_PARAM; 590 } 591 /* Check if adjusted_cosq doesn't cross limit */ 592 if (adjusted_cosq >= _SOC_HSP_MAX_L0_NODES) { 593 return SOC_E_PARAM; 594 } 595 soc_reg_field_set(unit, L0_COSWEIGHTSr, &rval, COSWEIGHTSf, weight); 596 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, 597 L0_COSWEIGHTSr, port, adjusted_cosq, rval)); 598 599 /* Ensure that when scheduling minumum bandwidth, schedule disciple matches */ 600 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_PORT_CONFIGr, port, 0, &rval)); 601 spmap = soc_reg_field_get(unit, HES_PORT_CONFIGr, rval, MINSPCONFIGf); 602 603 if (weight) { 604 spmap &= ~(1 << adjusted_cosq); 605 } else { 606 spmap |= (1 << adjusted_cosq); 607 } 608 609 soc_reg_field_set(unit, HES_PORT_CONFIGr, &rval, MINSPCONFIGf, spmap); 610 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, HES_PORT_CONFIGr, port, 0, rval)); 611 612 return SOC_E_NONE; 613 } 614 615 int 616 soc_tr3_hsp_sched_weight_get(int unit, int port, int cosq, int *weight) 617 { 618 uint32 rval = 0; 619 int adjusted_cosq = cosq + _SOC_HSP_VALID_L0_START; 620 if (!_SOC_TR3_IS_HSP_PORT(unit, port)) { 621 return SOC_E_PARAM; 622 } 623 if (adjusted_cosq >= _SOC_HSP_MAX_L0_NODES) { 624 return SOC_E_PARAM; 625 } 626 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, L0_COSWEIGHTSr, port, 627 adjusted_cosq, &rval)); 628 *weight = soc_reg_field_get(unit, L0_COSWEIGHTSr, rval, COSWEIGHTSf); 629 return SOC_E_NONE; 630 } 631 632 int 633 soc_tr3_hsp_set_sched_config(int unit, soc_port_t port, int cosq, 634 soc_tr3_sched_mode_e mode, int adjust_cos) 635 { 636 uint32 rval = 0; 637 638 if (!_SOC_TR3_IS_HSP_PORT(unit, port)) { 639 return SOC_E_PARAM; 640 } 641 if ((cosq + adjust_cos) >= _SOC_HSP_MAX_L0_NODES) { 642 return SOC_E_PARAM; 643 } 644 if (mode == SOC_TR3_SCHED_MODE_STRICT) { 645 soc_tr3_hsp_sched_weight_set(unit, port, cosq, 0, adjust_cos); 646 } else if (mode == SOC_TR3_SCHED_MODE_WRR) { 647 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_L0_CONFIGr, 648 port, 0, &rval)); 649 soc_reg_field_set(unit, HES_L0_CONFIGr, &rval, 650 SCHEDULING_SELECTf, 0); 651 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, HES_L0_CONFIGr, port, 0, rval)); 652 rval = 0; 653 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_PORT_CONFIGr, 654 port, 0, &rval)); 655 soc_reg_field_set(unit, HES_PORT_CONFIGr, &rval, 656 SCHEDULING_SELECTf, 0); 657 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, HES_PORT_CONFIGr, port, 0, rval)); 658 659 } else if (mode == SOC_TR3_SCHED_MODE_WDRR) { 660 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_L0_CONFIGr, 661 port, 0, &rval)); 662 soc_reg_field_set(unit, HES_L0_CONFIGr, &rval, 663 SCHEDULING_SELECTf, 0x3FF); 664 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, HES_L0_CONFIGr, port, 0, rval)); 665 rval = 0; 666 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_PORT_CONFIGr, 667 port, 0, &rval)); 668 soc_reg_field_set(unit, HES_PORT_CONFIGr, &rval, 669 SCHEDULING_SELECTf, 1); 670 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, HES_PORT_CONFIGr, port, 0, rval)); 671 } 672 673 return SOC_E_NONE; 674 } 675 676 int 677 soc_tr3_hsp_get_sched_config(int unit, soc_port_t port, int cosq, 678 soc_tr3_sched_mode_e *mode) 679 { 680 uint32 rval = 0, fval = 0; 681 int wt = 0, adjusted_cosq = cosq + _SOC_HSP_VALID_L0_START; 682 683 if (!_SOC_TR3_IS_HSP_PORT(unit, port)) { 684 return SOC_E_PARAM; 685 } 686 if (adjusted_cosq >= _SOC_HSP_MAX_L0_NODES) { 687 return SOC_E_PARAM; 688 } 689 soc_tr3_hsp_sched_weight_get(unit, port, cosq, &wt); 690 if (wt == 0) { 691 *mode = SOC_TR3_SCHED_MODE_STRICT; 692 } else { 693 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_L0_CONFIGr, port, 694 0, &rval)); 695 fval = soc_reg_field_get(unit, HES_L0_CONFIGr, rval, SCHEDULING_SELECTf); 696 *mode = (fval == 0) ? SOC_TR3_SCHED_MODE_WRR : SOC_TR3_SCHED_MODE_WDRR; 697 } 698 return SOC_E_NONE; 699 } 700 STATIC 701 int _soc_tr3_hsp_get_cos_index(int unit, int port, int index, int cosq, int *ptr_cos) 702 { 703 int cos; 704 705 if (!_SOC_TR3_IS_HSP_PORT(unit, port)) { 706 return SOC_E_PARAM; 707 } 708 if (ptr_cos == NULL) { 709 return SOC_E_PARAM; 710 } 711 /* Calculate cos. Allow only l0 node index 1 to 9 */ 712 if ((index < _SOC_HSP_VALID_L0_START) || 713 (index > _SOC_HSP_VALID_L0_END)) { 714 return SOC_E_PARAM; 715 } 716 if ((cosq < _SOC_HSP_MIN_QUEUE_OFFSET) || 717 (cosq > _SOC_HSP_MAX_QUEUE_OFFSET)) { 718 return SOC_E_PARAM; 719 } 720 721 if (index == _SOC_HSP_VALID_L0_END) { 722 if ((cosq == 0) || (cosq == 1)) { 723 /* Unicast Queue */ 724 cos = _SOC_HSP_LAST_L0_UC_START + cosq; 725 } else { 726 /* Multicast Queue */ 727 cos = _SOC_HSP_LAST_L0_MC_START + 728 (cosq - _SOC_HSP_LAST_L0_MAX_UC_QUEUE ); 729 } 730 } else { 731 if (cosq > 1 ) { 732 return SOC_E_PARAM; 733 } 734 if (cosq == 0) { 735 cos = index - _SOC_HSP_VALID_L0_START; 736 } else { 737 cos = _SOC_HSP_MAX_L0_NODES + (index - _SOC_HSP_VALID_L0_START); 738 } 739 } 740 *ptr_cos = cos; 741 return SOC_E_NONE; 742 } 743 int 744 _soc_tr3_hsp_sched_weight_set(int unit, int port, int index, int cosq, int weight) 745 { 746 uint32 rval = 0; 747 int cos; 748 749 SOC_IF_ERROR_RETURN(_soc_tr3_hsp_get_cos_index(unit, port, index, cosq, &cos)); 750 /* Now configure weight */ 751 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_COSWEIGHTSr, port, cos, &rval)); 752 soc_reg_field_set(unit, HES_Q_COSWEIGHTSr, &rval, COSWEIGHTSf, weight); 753 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, HES_Q_COSWEIGHTSr, port, cos, rval)); 754 755 return SOC_E_NONE; 756 } 757 758 int 759 _soc_tr3_hsp_sched_weight_get(int unit, int port, int index, int cosq, int *weight) 760 { 761 uint32 rval = 0; 762 int cos; 763 764 SOC_IF_ERROR_RETURN(_soc_tr3_hsp_get_cos_index(unit, port, index, cosq, &cos)); 765 766 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_COSWEIGHTSr, port, cos, &rval)); 767 *weight = soc_reg_field_get(unit, HES_Q_COSWEIGHTSr, rval, COSWEIGHTSf); 768 769 return SOC_E_NONE; 770 } 771 772 int 773 _soc_tr3_hsp_set_sched_config(int unit, soc_port_t port, int index, int cosq, 774 soc_tr3_sched_mode_e mode) 775 { 776 uint32 rval = 0, temp = 0, q_spmap; 777 int cos; 778 779 SOC_IF_ERROR_RETURN(_soc_tr3_hsp_get_cos_index(unit, port, index, cosq, &cos)); 780 781 if (mode == SOC_TR3_SCHED_MODE_STRICT) { 782 SOC_IF_ERROR_RETURN(_soc_tr3_hsp_sched_weight_set(unit, port, index, cosq, 0)); 783 temp = 1 << cos; 784 } 785 /* Note that we don't differ b/w wrr and werr at queue level */ 786 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_MINSPr, port, 0, &rval)); 787 q_spmap = soc_reg_field_get(unit, HES_Q_MINSPr, rval, MINSPCONFIGf); 788 q_spmap = q_spmap | temp; 789 soc_reg_field_set(unit, HES_Q_MINSPr, &rval, MINSPCONFIGf, q_spmap); 790 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, HES_Q_MINSPr, port, 0, rval)); 791 return SOC_E_NONE; 792 } 793 794 int 795 _soc_tr3_hsp_get_sched_config(int unit, soc_port_t port, int index, int cosq, 796 soc_tr3_sched_mode_e *mode) 797 { 798 uint32 rval = 0, q_spmap; 799 int cos; 800 801 SOC_IF_ERROR_RETURN(_soc_tr3_hsp_get_cos_index(unit, port, index, cosq, &cos)); 802 803 /* Note that we don't differ b/w wrr and werr at queue level */ 804 805 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_MINSPr, port, 0, &rval)); 806 q_spmap = soc_reg_field_get(unit, HES_Q_MINSPr, rval, MINSPCONFIGf); 807 808 if ((q_spmap >> cos) & 1) { 809 *mode = SOC_TR3_SCHED_MODE_STRICT; 810 } else { 811 *mode = SOC_TR3_SCHED_MODE_WRR; 812 } 813 return SOC_E_NONE; 814 } 815 typedef struct _soc_tr3_lls_config_s { 816 uint32 level; 817 int node_id; 818 int num_children; 819 int sched_mode; 820 int weights[48]; 821 /* Only for L2 nodes it denotes which of the children are UC (1), MC(0) */ 822 uint32 uc_mc_map; 823 } _soc_tr3_lls_config_t; 824 825 static int tr3_sm_port_num_sched_at_lvl[] = { 826 /* root */ 1, 827 /* L0 */ 1, 828 /* L1 */ 1 829 }; 830 831 static int tr3_lb_port_num_sched_at_lvl[] = { 832 /* root */ 1, 833 /* L0 */ 2, 834 /* L1 */ 9 835 }; 836 837 static int tr3_port_num_sched_at_lvl[] = { 838 /* root */ 1, 839 /* L0 */ 1, 840 /* L1 */ 8 841 }; 842 843 static int tr3_hg_port_num_sched_at_lvl[] = { 844 /* root */ 1, 845 /* L0 */ 1, 846 /* L1 */ 9 847 }; 848 849 static int tr3_cpu_num_sched_at_lvl[] = { 850 /* root */ 1, 851 /* L0 */ 3, 852 /* L1 */ 10 853 }; 854 855 static _soc_tr3_lls_config_t _tr3_port_sm_lls_config[] = { 856 /* SOC_TR3_NODE_LVL_ROOT */ 857 { SOC_TR3_NODE_LVL_ROOT, 0, 858 1, SOC_TR3_SCHED_MODE_WRR, 859 { 1,1,1,1,1,1,1,1, 860 1,1,1,1,1,1,1,1, 861 1,1,1,1,1,1,1,1, 862 1,1,1,1,1,1,1,1, 863 1,1,1,1,1,1,1,1, 864 1,1,1,1,1,1,1,1 }, 865 0}, 866 /* SOC_TR3_NODE_LVL_L0 L0.0 */ 867 { SOC_TR3_NODE_LVL_L0, 0, 868 1, SOC_TR3_SCHED_MODE_WRR, 869 { 1,1,1,1,1,1,1,1, 870 1,1,1,1,1,1,1,1, 871 1,1,1,1,1,1,1,1, 872 1,1,1,1,1,1,1,1, 873 1,1,1,1,1,1,1,1, 874 1,1,1,1,1,1,1,1 }, 875 0}, 876 /* SOC_TR3_NODE_LVL_L1 L1.0 */ 877 { SOC_TR3_NODE_LVL_L1, 0, 878 1, SOC_TR3_SCHED_MODE_WRR, 879 { 1,1,1,1,1,1,1,1, 880 1,1,1,1,1,1,1,1, 881 1,1,1,1,1,1,1,1, 882 1,1,1,1,1,1,1,1, 883 1,1,1,1,1,1,1,1, 884 1,1,1,1,1,1,1,1 }, 885 0x0 /* 1 UC nodes */}, 886 /* SOC_TR3_NODE_LVL_L2 */ 887 { -1, 0, 0, -1, 888 { 1,1,1,1,1,1,1,1, 889 1,1,1,1,1,1,1,1, 890 1,1,1,1,1,1,1,1, 891 1,1,1,1,1,1,1,1, 892 1,1,1,1,1,1,1,1, 893 1,1,1,1,1,1,1,1 }, 894 1 } 895 }; 896 897 static _soc_tr3_lls_config_t _tr3_lb_port_lls_config[] = { 898 /* SOC_TR3_NODE_LVL_ROOT */ 899 { SOC_TR3_NODE_LVL_ROOT, 0, 900 2, SOC_TR3_SCHED_MODE_WRR, 901 { 1,1,1,1,1,1,1,1, 902 1,1,1,1,1,1,1,1, 903 1,1,1,1,1,1,1,1, 904 1,1,1,1,1,1,1,1, 905 1,1,1,1,1,1,1,1, 906 1,1,1,1,1,1,1,1 }, 907 0}, 908 /* SOC_TR3_NODE_LVL_L0 L0.0 */ 909 { SOC_TR3_NODE_LVL_L0, 0, 910 1, SOC_TR3_SCHED_MODE_WRR, 911 { 1,1,1,1,1,1,1,1, 912 1,1,1,1,1,1,1,1, 913 1,1,1,1,1,1,1,1, 914 1,1,1,1,1,1,1,1, 915 1,1,1,1,1,1,1,1, 916 1,1,1,1,1,1,1,1 }, 917 0}, 918 /* SOC_TR3_NODE_LVL_L0 L0.1 */ 919 { SOC_TR3_NODE_LVL_L0, 1, 920 8, SOC_TR3_SCHED_MODE_WRR, 921 { 1,1,1,1,1,1,1,1, 922 1,1,1,1,1,1,1,1, 923 1,1,1,1,1,1,1,1, 924 1,1,1,1,1,1,1,1, 925 1,1,1,1,1,1,1,1, 926 1,1,1,1,1,1,1,1 }, 927 0}, 928 /* SOC_TR3_NODE_LVL_L1 L1.0 */ 929 { SOC_TR3_NODE_LVL_L1, 0, 930 1, SOC_TR3_SCHED_MODE_WRR, 931 { 1,1,1,1,1,1,1,1, 932 1,1,1,1,1,1,1,1, 933 1,1,1,1,1,1,1,1, 934 1,1,1,1,1,1,1,1, 935 1,1,1,1,1,1,1,1, 936 1,1,1,1,1,1,1,1 }, 937 0 /* 1 MC (QCN) node */}, 938 /* SOC_TR3_NODE_LVL_L1 L1.1 */ 939 { SOC_TR3_NODE_LVL_L1, 1, 940 2, SOC_TR3_SCHED_MODE_WRR, 941 { 1,1,1,1,1,1,1,1, 942 1,1,1,1,1,1,1,1, 943 1,1,1,1,1,1,1,1, 944 1,1,1,1,1,1,1,1, 945 1,1,1,1,1,1,1,1, 946 1,1,1,1,1,1,1,1 }, 947 0x1 /* 1 UC nodes, 1 MC node */}, 948 /* SOC_TR3_NODE_LVL_L1 L1.2 */ 949 { SOC_TR3_NODE_LVL_L1, 2, 950 2, SOC_TR3_SCHED_MODE_WRR, 951 { 1,1,1,1,1,1,1,1, 952 1,1,1,1,1,1,1,1, 953 1,1,1,1,1,1,1,1, 954 1,1,1,1,1,1,1,1, 955 1,1,1,1,1,1,1,1, 956 1,1,1,1,1,1,1,1 }, 957 0x1 /* 1 UC nodes, 1 MC node */}, 958 /* SOC_TR3_NODE_LVL_L1 L1.3 */ 959 { SOC_TR3_NODE_LVL_L1, 3, 960 2, SOC_TR3_SCHED_MODE_WRR, 961 { 1,1,1,1,1,1,1,1, 962 1,1,1,1,1,1,1,1, 963 1,1,1,1,1,1,1,1, 964 1,1,1,1,1,1,1,1, 965 1,1,1,1,1,1,1,1, 966 1,1,1,1,1,1,1,1 }, 967 0x1 /* 1 UC nodes, 1 MC node */}, 968 /* SOC_TR3_NODE_LVL_L1 L1.4 */ 969 { SOC_TR3_NODE_LVL_L1, 4, 970 2, SOC_TR3_SCHED_MODE_WRR, 971 { 1,1,1,1,1,1,1,1, 972 1,1,1,1,1,1,1,1, 973 1,1,1,1,1,1,1,1, 974 1,1,1,1,1,1,1,1, 975 1,1,1,1,1,1,1,1, 976 1,1,1,1,1,1,1,1 }, 977 0x1 /* 1 UC nodes, 1 MC node */}, 978 /* SOC_TR3_NODE_LVL_L1 L1.5 */ 979 { SOC_TR3_NODE_LVL_L1, 5, 980 2, SOC_TR3_SCHED_MODE_WRR, 981 { 1,1,1,1,1,1,1,1, 982 1,1,1,1,1,1,1,1, 983 1,1,1,1,1,1,1,1, 984 1,1,1,1,1,1,1,1, 985 1,1,1,1,1,1,1,1, 986 1,1,1,1,1,1,1,1 }, 987 0x1 /* 1 UC nodes, 1 MC node */}, 988 /* SOC_TR3_NODE_LVL_L1 L1.6 */ 989 { SOC_TR3_NODE_LVL_L1, 6, 990 2, SOC_TR3_SCHED_MODE_WRR, 991 { 1,1,1,1,1,1,1,1, 992 1,1,1,1,1,1,1,1, 993 1,1,1,1,1,1,1,1, 994 1,1,1,1,1,1,1,1, 995 1,1,1,1,1,1,1,1, 996 1,1,1,1,1,1,1,1 }, 997 0x1 /* 1 UC nodes, 1 MC node */}, 998 /* SOC_TR3_NODE_LVL_L1 L1.7 */ 999 { SOC_TR3_NODE_LVL_L1, 7, 1000 2, SOC_TR3_SCHED_MODE_WRR, 1001 { 1,1,1,1,1,1,1,1, 1002 1,1,1,1,1,1,1,1, 1003 1,1,1,1,1,1,1,1, 1004 1,1,1,1,1,1,1,1, 1005 1,1,1,1,1,1,1,1, 1006 1,1,1,1,1,1,1,1 }, 1007 0x1 /* 1 UC nodes, 1 MC node */}, 1008 /* SOC_TR3_NODE_LVL_L1 L1.8 */ 1009 { SOC_TR3_NODE_LVL_L1, 8, 1010 2, SOC_TR3_SCHED_MODE_WRR, 1011 { 1,1,1,1,1,1,1,1, 1012 1,1,1,1,1,1,1,1, 1013 1,1,1,1,1,1,1,1, 1014 1,1,1,1,1,1,1,1, 1015 1,1,1,1,1,1,1,1, 1016 1,1,1,1,1,1,1,1 }, 1017 0x1 /* 1 UC nodes, 1 MC node */}, 1018 /* SOC_TR3_NODE_LVL_L2 */ 1019 { -1, 0, 0, -1, 1020 { 1,1,1,1,1,1,1,1, 1021 1,1,1,1,1,1,1,1, 1022 1,1,1,1,1,1,1,1, 1023 1,1,1,1,1,1,1,1, 1024 1,1,1,1,1,1,1,1, 1025 1,1,1,1,1,1,1,1 }, 1026 1 } 1027 }; 1028 1029 static _soc_tr3_lls_config_t _tr3_port_lls_config[] = { 1030 /* SOC_TR3_NODE_LVL_ROOT */ 1031 { SOC_TR3_NODE_LVL_ROOT, 0, 1032 1, SOC_TR3_SCHED_MODE_WRR, 1033 { 1,1,1,1,1,1,1,1, 1034 1,1,1,1,1,1,1,1, 1035 1,1,1,1,1,1,1,1, 1036 1,1,1,1,1,1,1,1, 1037 1,1,1,1,1,1,1,1, 1038 1,1,1,1,1,1,1,1 }, 1039 0}, 1040 /* SOC_TR3_NODE_LVL_L0 L0.0 */ 1041 { SOC_TR3_NODE_LVL_L0, 0, 1042 8, SOC_TR3_SCHED_MODE_WRR, 1043 { 1,1,1,1,1,1,1,1, 1044 1,1,1,1,1,1,1,1, 1045 1,1,1,1,1,1,1,1, 1046 1,1,1,1,1,1,1,1, 1047 1,1,1,1,1,1,1,1, 1048 1,1,1,1,1,1,1,1 }, 1049 0}, 1050 /* SOC_TR3_NODE_LVL_L1 L1.0 */ 1051 { SOC_TR3_NODE_LVL_L1, 0, 1052 2, SOC_TR3_SCHED_MODE_WRR, 1053 { 1,1,1,1,1,1,1,1, 1054 1,1,1,1,1,1,1,1, 1055 1,1,1,1,1,1,1,1, 1056 1,1,1,1,1,1,1,1, 1057 1,1,1,1,1,1,1,1, 1058 1,1,1,1,1,1,1,1 }, 1059 0x1 /* 1 UC nodes, 1 MC node */}, 1060 /* SOC_TR3_NODE_LVL_L1 L1.1 */ 1061 { SOC_TR3_NODE_LVL_L1, 1, 1062 2, SOC_TR3_SCHED_MODE_WRR, 1063 { 1,1,1,1,1,1,1,1, 1064 1,1,1,1,1,1,1,1, 1065 1,1,1,1,1,1,1,1, 1066 1,1,1,1,1,1,1,1, 1067 1,1,1,1,1,1,1,1, 1068 1,1,1,1,1,1,1,1 }, 1069 0x1 /* 1 UC nodes, 1 MC node */}, 1070 /* SOC_TR3_NODE_LVL_L1 L1.2 */ 1071 { SOC_TR3_NODE_LVL_L1, 2, 1072 2, SOC_TR3_SCHED_MODE_WRR, 1073 { 1,1,1,1,1,1,1,1, 1074 1,1,1,1,1,1,1,1, 1075 1,1,1,1,1,1,1,1, 1076 1,1,1,1,1,1,1,1, 1077 1,1,1,1,1,1,1,1, 1078 1,1,1,1,1,1,1,1 }, 1079 0x1 /* 1 UC nodes, 1 MC node */}, 1080 /* SOC_TR3_NODE_LVL_L1 L1.3 */ 1081 { SOC_TR3_NODE_LVL_L1, 3, 1082 2, SOC_TR3_SCHED_MODE_WRR, 1083 { 1,1,1,1,1,1,1,1, 1084 1,1,1,1,1,1,1,1, 1085 1,1,1,1,1,1,1,1, 1086 1,1,1,1,1,1,1,1, 1087 1,1,1,1,1,1,1,1, 1088 1,1,1,1,1,1,1,1 }, 1089 0x1 /* 1 UC nodes, 1 MC node */}, 1090 /* SOC_TR3_NODE_LVL_L1 L1.4 */ 1091 { SOC_TR3_NODE_LVL_L1, 4, 1092 2, SOC_TR3_SCHED_MODE_WRR, 1093 { 1,1,1,1,1,1,1,1, 1094 1,1,1,1,1,1,1,1, 1095 1,1,1,1,1,1,1,1, 1096 1,1,1,1,1,1,1,1, 1097 1,1,1,1,1,1,1,1, 1098 1,1,1,1,1,1,1,1 }, 1099 0x1 /* 1 UC nodes, 1 MC node */}, 1100 /* SOC_TR3_NODE_LVL_L1 L1.5 */ 1101 { SOC_TR3_NODE_LVL_L1, 5, 1102 2, SOC_TR3_SCHED_MODE_WRR, 1103 { 1,1,1,1,1,1,1,1, 1104 1,1,1,1,1,1,1,1, 1105 1,1,1,1,1,1,1,1, 1106 1,1,1,1,1,1,1,1, 1107 1,1,1,1,1,1,1,1, 1108 1,1,1,1,1,1,1,1 }, 1109 0x1 /* 1 UC nodes, 1 MC node */}, 1110 /* SOC_TR3_NODE_LVL_L1 L1.6 */ 1111 { SOC_TR3_NODE_LVL_L1, 6, 1112 2, SOC_TR3_SCHED_MODE_WRR, 1113 { 1,1,1,1,1,1,1,1, 1114 1,1,1,1,1,1,1,1, 1115 1,1,1,1,1,1,1,1, 1116 1,1,1,1,1,1,1,1, 1117 1,1,1,1,1,1,1,1, 1118 1,1,1,1,1,1,1,1 }, 1119 0x1 /* 1 UC nodes, 1 MC node */}, 1120 /* SOC_TR3_NODE_LVL_L1 L1.7 */ 1121 { SOC_TR3_NODE_LVL_L1, 7, 1122 2, SOC_TR3_SCHED_MODE_WRR, 1123 { 1,1,1,1,1,1,1,1, 1124 1,1,1,1,1,1,1,1, 1125 1,1,1,1,1,1,1,1, 1126 1,1,1,1,1,1,1,1, 1127 1,1,1,1,1,1,1,1, 1128 1,1,1,1,1,1,1,1 }, 1129 0x1 /* 1 UC nodes, 1 MC node */}, 1130 /* SOC_TR3_NODE_LVL_L2 */ 1131 { -1, 0, 0, -1, 1132 { 1,1,1,1,1,1,1,1, 1133 1,1,1,1,1,1,1,1, 1134 1,1,1,1,1,1,1,1, 1135 1,1,1,1,1,1,1,1, 1136 1,1,1,1,1,1,1,1, 1137 1,1,1,1,1,1,1,1 }, 1138 1 } 1139 }; 1140 1141 static _soc_tr3_lls_config_t _tr3_port_dyn_lls_config[] = { 1142 /* SOC_TR3_NODE_LVL_ROOT */ 1143 { SOC_TR3_NODE_LVL_ROOT, 0, 1144 1, SOC_TR3_SCHED_MODE_WRR, 1145 { 1,1,1,1,1,1,1,1, 1146 1,1,1,1,1,1,1,1, 1147 1,1,1,1,1,1,1,1, 1148 1,1,1,1,1,1,1,1, 1149 1,1,1,1,1,1,1,1, 1150 1,1,1,1,1,1,1,1 }, 1151 0}, 1152 /* SOC_TR3_NODE_LVL_L0 L0.0 */ 1153 { SOC_TR3_NODE_LVL_L0, 0, 1154 16, SOC_TR3_SCHED_MODE_WRR, 1155 { 1,1,1,1,1,1,1,1, 1156 1,1,1,1,1,1,1,1, 1157 1,1,1,1,1,1,1,1, 1158 1,1,1,1,1,1,1,1, 1159 1,1,1,1,1,1,1,1, 1160 1,1,1,1,1,1,1,1 }, 1161 0}, 1162 /* SOC_TR3_NODE_LVL_L1 L1.0 */ 1163 { SOC_TR3_NODE_LVL_L1, 0, 1164 2, SOC_TR3_SCHED_MODE_WRR, 1165 { 1,1,1,1,1,1,1,1, 1166 1,1,1,1,1,1,1,1, 1167 1,1,1,1,1,1,1,1, 1168 1,1,1,1,1,1,1,1, 1169 1,1,1,1,1,1,1,1, 1170 1,1,1,1,1,1,1,1 }, 1171 0x1 /* 1 UC nodes, 1 MC node */}, 1172 /* SOC_TR3_NODE_LVL_L1 L1.1 */ 1173 { SOC_TR3_NODE_LVL_L1, 1, 1174 2, SOC_TR3_SCHED_MODE_WRR, 1175 { 1,1,1,1,1,1,1,1, 1176 1,1,1,1,1,1,1,1, 1177 1,1,1,1,1,1,1,1, 1178 1,1,1,1,1,1,1,1, 1179 1,1,1,1,1,1,1,1, 1180 1,1,1,1,1,1,1,1 }, 1181 0x1 /* 1 UC nodes, 1 MC node */}, 1182 /* SOC_TR3_NODE_LVL_L1 L1.2 */ 1183 { SOC_TR3_NODE_LVL_L1, 2, 1184 2, SOC_TR3_SCHED_MODE_WRR, 1185 { 1,1,1,1,1,1,1,1, 1186 1,1,1,1,1,1,1,1, 1187 1,1,1,1,1,1,1,1, 1188 1,1,1,1,1,1,1,1, 1189 1,1,1,1,1,1,1,1, 1190 1,1,1,1,1,1,1,1 }, 1191 0x1 /* 1 UC nodes, 1 MC node */}, 1192 /* SOC_TR3_NODE_LVL_L1 L1.3 */ 1193 { SOC_TR3_NODE_LVL_L1, 3, 1194 2, SOC_TR3_SCHED_MODE_WRR, 1195 { 1,1,1,1,1,1,1,1, 1196 1,1,1,1,1,1,1,1, 1197 1,1,1,1,1,1,1,1, 1198 1,1,1,1,1,1,1,1, 1199 1,1,1,1,1,1,1,1, 1200 1,1,1,1,1,1,1,1 }, 1201 0x1 /* 1 UC nodes, 1 MC node */}, 1202 /* SOC_TR3_NODE_LVL_L1 L1.4 */ 1203 { SOC_TR3_NODE_LVL_L1, 4, 1204 2, SOC_TR3_SCHED_MODE_WRR, 1205 { 1,1,1,1,1,1,1,1, 1206 1,1,1,1,1,1,1,1, 1207 1,1,1,1,1,1,1,1, 1208 1,1,1,1,1,1,1,1, 1209 1,1,1,1,1,1,1,1, 1210 1,1,1,1,1,1,1,1 }, 1211 0x1 /* 1 UC nodes, 1 MC node */}, 1212 /* SOC_TR3_NODE_LVL_L1 L1.5 */ 1213 { SOC_TR3_NODE_LVL_L1, 5, 1214 2, SOC_TR3_SCHED_MODE_WRR, 1215 { 1,1,1,1,1,1,1,1, 1216 1,1,1,1,1,1,1,1, 1217 1,1,1,1,1,1,1,1, 1218 1,1,1,1,1,1,1,1, 1219 1,1,1,1,1,1,1,1, 1220 1,1,1,1,1,1,1,1 }, 1221 0x1 /* 1 UC nodes, 1 MC node */}, 1222 /* SOC_TR3_NODE_LVL_L1 L1.6 */ 1223 { SOC_TR3_NODE_LVL_L1, 6, 1224 2, SOC_TR3_SCHED_MODE_WRR, 1225 { 1,1,1,1,1,1,1,1, 1226 1,1,1,1,1,1,1,1, 1227 1,1,1,1,1,1,1,1, 1228 1,1,1,1,1,1,1,1, 1229 1,1,1,1,1,1,1,1, 1230 1,1,1,1,1,1,1,1 }, 1231 0x1 /* 1 UC nodes, 1 MC node */}, 1232 /* SOC_TR3_NODE_LVL_L1 L1.7 */ 1233 { SOC_TR3_NODE_LVL_L1, 7, 1234 2, SOC_TR3_SCHED_MODE_WRR, 1235 { 1,1,1,1,1,1,1,1, 1236 1,1,1,1,1,1,1,1, 1237 1,1,1,1,1,1,1,1, 1238 1,1,1,1,1,1,1,1, 1239 1,1,1,1,1,1,1,1, 1240 1,1,1,1,1,1,1,1 }, 1241 0x1 /* 1 UC nodes, 1 MC node */}, 1242 /* SOC_TR3_NODE_LVL_L1 L1.8 */ 1243 { SOC_TR3_NODE_LVL_L1, 8, 1244 0, SOC_TR3_SCHED_MODE_STRICT, 1245 { 1,1,1,1,1,1,1,1, 1246 1,1,1,1,1,1,1,1, 1247 1,1,1,1,1,1,1,1, 1248 1,1,1,1,1,1,1,1, 1249 1,1,1,1,1,1,1,1, 1250 1,1,1,1,1,1,1,1 }, 1251 0}, 1252 /* SOC_TR3_NODE_LVL_L1 L1.9 */ 1253 { SOC_TR3_NODE_LVL_L1, 9, 1254 0, SOC_TR3_SCHED_MODE_STRICT, 1255 { 1,1,1,1,1,1,1,1, 1256 1,1,1,1,1,1,1,1, 1257 1,1,1,1,1,1,1,1, 1258 1,1,1,1,1,1,1,1, 1259 1,1,1,1,1,1,1,1, 1260 1,1,1,1,1,1,1,1 }, 1261 0}, 1262 /* SOC_TR3_NODE_LVL_L1 L1.10 */ 1263 { SOC_TR3_NODE_LVL_L1, 10, 1264 0, SOC_TR3_SCHED_MODE_STRICT, 1265 { 1,1,1,1,1,1,1,1, 1266 1,1,1,1,1,1,1,1, 1267 1,1,1,1,1,1,1,1, 1268 1,1,1,1,1,1,1,1, 1269 1,1,1,1,1,1,1,1, 1270 1,1,1,1,1,1,1,1 }, 1271 0}, 1272 /* SOC_TR3_NODE_LVL_L1 L1.11 */ 1273 { SOC_TR3_NODE_LVL_L1, 11, 1274 0, SOC_TR3_SCHED_MODE_STRICT, 1275 { 1,1,1,1,1,1,1,1, 1276 1,1,1,1,1,1,1,1, 1277 1,1,1,1,1,1,1,1, 1278 1,1,1,1,1,1,1,1, 1279 1,1,1,1,1,1,1,1, 1280 1,1,1,1,1,1,1,1 }, 1281 0}, 1282 /* SOC_TR3_NODE_LVL_L1 L1.12 */ 1283 { SOC_TR3_NODE_LVL_L1, 12, 1284 0, SOC_TR3_SCHED_MODE_STRICT, 1285 { 1,1,1,1,1,1,1,1, 1286 1,1,1,1,1,1,1,1, 1287 1,1,1,1,1,1,1,1, 1288 1,1,1,1,1,1,1,1, 1289 1,1,1,1,1,1,1,1, 1290 1,1,1,1,1,1,1,1 }, 1291 0}, 1292 /* SOC_TR3_NODE_LVL_L1 L1.13 */ 1293 { SOC_TR3_NODE_LVL_L1, 13, 1294 0, SOC_TR3_SCHED_MODE_STRICT, 1295 { 1,1,1,1,1,1,1,1, 1296 1,1,1,1,1,1,1,1, 1297 1,1,1,1,1,1,1,1, 1298 1,1,1,1,1,1,1,1, 1299 1,1,1,1,1,1,1,1, 1300 1,1,1,1,1,1,1,1 }, 1301 0}, 1302 /* SOC_TR3_NODE_LVL_L1 L1.14 */ 1303 { SOC_TR3_NODE_LVL_L1, 14, 1304 0, SOC_TR3_SCHED_MODE_STRICT, 1305 { 1,1,1,1,1,1,1,1, 1306 1,1,1,1,1,1,1,1, 1307 1,1,1,1,1,1,1,1, 1308 1,1,1,1,1,1,1,1, 1309 1,1,1,1,1,1,1,1, 1310 1,1,1,1,1,1,1,1 }, 1311 0}, 1312 /* SOC_TR3_NODE_LVL_L1 L1.15 */ 1313 { SOC_TR3_NODE_LVL_L1, 15, 1314 0, SOC_TR3_SCHED_MODE_STRICT, 1315 { 1,1,1,1,1,1,1,1, 1316 1,1,1,1,1,1,1,1, 1317 1,1,1,1,1,1,1,1, 1318 1,1,1,1,1,1,1,1, 1319 1,1,1,1,1,1,1,1, 1320 1,1,1,1,1,1,1,1 }, 1321 0}, 1322 /* SOC_TR3_NODE_LVL_L2 */ 1323 { -1, 0, 0, -1, 1324 { 1,1,1,1,1,1,1,1, 1325 1,1,1,1,1,1,1,1, 1326 1,1,1,1,1,1,1,1, 1327 1,1,1,1,1,1,1,1, 1328 1,1,1,1,1,1,1,1, 1329 1,1,1,1,1,1,1,1 }, 1330 1 } 1331 }; 1332 1333 static _soc_tr3_lls_config_t _tr3_hg_port_lls_config[] = { 1334 /* SOC_TR3_NODE_LVL_ROOT */ 1335 { SOC_TR3_NODE_LVL_ROOT, 0, 1336 1, SOC_TR3_SCHED_MODE_WRR, 1337 { 1,1,1,1,1,1,1,1, 1338 1,1,1,1,1,1,1,1, 1339 1,1,1,1,1,1,1,1, 1340 1,1,1,1,1,1,1,1, 1341 1,1,1,1,1,1,1,1, 1342 1,1,1,1,1,1,1,1 }, 1343 0}, 1344 /* SOC_TR3_NODE_LVL_L0 L0.0 */ 1345 { SOC_TR3_NODE_LVL_L0, 0, 1346 9, SOC_TR3_SCHED_MODE_WRR, 1347 { 1,1,1,1,1,1,1,1, 1348 1,1,1,1,1,1,1,1, 1349 1,1,1,1,1,1,1,1, 1350 1,1,1,1,1,1,1,1, 1351 1,1,1,1,1,1,1,1, 1352 1,1,1,1,1,1,1,1 }, 1353 0}, 1354 /* SOC_TR3_NODE_LVL_L1 L1.0 */ 1355 { SOC_TR3_NODE_LVL_L1, 0, 1356 2, SOC_TR3_SCHED_MODE_WRR, 1357 { 1,1,1,1,1,1,1,1, 1358 1,1,1,1,1,1,1,1, 1359 1,1,1,1,1,1,1,1, 1360 1,1,1,1,1,1,1,1, 1361 1,1,1,1,1,1,1,1, 1362 1,1,1,1,1,1,1,1 }, 1363 0x1 /* 1 UC nodes, 1 MC node */}, 1364 /* SOC_TR3_NODE_LVL_L1 L1.1 */ 1365 { SOC_TR3_NODE_LVL_L1, 1, 1366 2, SOC_TR3_SCHED_MODE_WRR, 1367 { 1,1,1,1,1,1,1,1, 1368 1,1,1,1,1,1,1,1, 1369 1,1,1,1,1,1,1,1, 1370 1,1,1,1,1,1,1,1, 1371 1,1,1,1,1,1,1,1, 1372 1,1,1,1,1,1,1,1 }, 1373 0x1 /* 1 UC nodes, 1 MC node */}, 1374 /* SOC_TR3_NODE_LVL_L1 L1.2 */ 1375 { SOC_TR3_NODE_LVL_L1, 2, 1376 2, SOC_TR3_SCHED_MODE_WRR, 1377 { 1,1,1,1,1,1,1,1, 1378 1,1,1,1,1,1,1,1, 1379 1,1,1,1,1,1,1,1, 1380 1,1,1,1,1,1,1,1, 1381 1,1,1,1,1,1,1,1, 1382 1,1,1,1,1,1,1,1 }, 1383 0x1 /* 1 UC nodes, 1 MC node */}, 1384 /* SOC_TR3_NODE_LVL_L1 L1.3 */ 1385 { SOC_TR3_NODE_LVL_L1, 3, 1386 2, SOC_TR3_SCHED_MODE_WRR, 1387 { 1,1,1,1,1,1,1,1, 1388 1,1,1,1,1,1,1,1, 1389 1,1,1,1,1,1,1,1, 1390 1,1,1,1,1,1,1,1, 1391 1,1,1,1,1,1,1,1, 1392 1,1,1,1,1,1,1,1 }, 1393 0x1 /* 1 UC nodes, 1 MC node */}, 1394 /* SOC_TR3_NODE_LVL_L1 L1.4 */ 1395 { SOC_TR3_NODE_LVL_L1, 4, 1396 2, SOC_TR3_SCHED_MODE_WRR, 1397 { 1,1,1,1,1,1,1,1, 1398 1,1,1,1,1,1,1,1, 1399 1,1,1,1,1,1,1,1, 1400 1,1,1,1,1,1,1,1, 1401 1,1,1,1,1,1,1,1, 1402 1,1,1,1,1,1,1,1 }, 1403 0x1 /* 1 UC nodes, 1 MC node */}, 1404 /* SOC_TR3_NODE_LVL_L1 L1.5 */ 1405 { SOC_TR3_NODE_LVL_L1, 5, 1406 2, SOC_TR3_SCHED_MODE_WRR, 1407 { 1,1,1,1,1,1,1,1, 1408 1,1,1,1,1,1,1,1, 1409 1,1,1,1,1,1,1,1, 1410 1,1,1,1,1,1,1,1, 1411 1,1,1,1,1,1,1,1, 1412 1,1,1,1,1,1,1,1 }, 1413 0x1 /* 1 UC nodes, 1 MC node */}, 1414 /* SOC_TR3_NODE_LVL_L1 L1.6 */ 1415 { SOC_TR3_NODE_LVL_L1, 6, 1416 2, SOC_TR3_SCHED_MODE_WRR, 1417 { 1,1,1,1,1,1,1,1, 1418 1,1,1,1,1,1,1,1, 1419 1,1,1,1,1,1,1,1, 1420 1,1,1,1,1,1,1,1, 1421 1,1,1,1,1,1,1,1, 1422 1,1,1,1,1,1,1,1 }, 1423 0x1 /* 1 UC nodes, 1 MC node */}, 1424 /* SOC_TR3_NODE_LVL_L1 L1.7 */ 1425 { SOC_TR3_NODE_LVL_L1, 7, 1426 2, SOC_TR3_SCHED_MODE_WRR, 1427 { 1,1,1,1,1,1,1,1, 1428 1,1,1,1,1,1,1,1, 1429 1,1,1,1,1,1,1,1, 1430 1,1,1,1,1,1,1,1, 1431 1,1,1,1,1,1,1,1, 1432 1,1,1,1,1,1,1,1 }, 1433 0x1 /* 1 UC nodes, 1 MC node */}, 1434 /* SOC_TR3_NODE_LVL_L1 L1.8 */ 1435 { SOC_TR3_NODE_LVL_L1, 8, 1436 4, SOC_TR3_SCHED_MODE_WRR, 1437 { 1,1,1,1,1,1,1,1, 1438 1,1,1,1,1,1,1,1, 1439 1,1,1,1,1,1,1,1, 1440 1,1,1,1,1,1,1,1, 1441 1,1,1,1,1,1,1,1, 1442 1,1,1,1,1,1,1,1 }, 1443 0x3 /* 2 UC nodes, 2 MC node */}, 1444 /* SOC_TR3_NODE_LVL_L2 */ 1445 { -1, 0, 0, -1, 1446 { 1,1,1,1,1,1,1,1, 1447 1,1,1,1,1,1,1,1, 1448 1,1,1,1,1,1,1,1, 1449 1,1,1,1,1,1,1,1, 1450 1,1,1,1,1,1,1,1, 1451 1,1,1,1,1,1,1,1 }, 1452 1 } 1453 }; 1454 1455 static _soc_tr3_lls_config_t _tr3_hg_port_dyn_lls_config[] = { 1456 /* SOC_TR3_NODE_LVL_ROOT */ 1457 { SOC_TR3_NODE_LVL_ROOT, 0, 1458 1, SOC_TR3_SCHED_MODE_WRR, 1459 { 1,1,1,1,1,1,1,1, 1460 1,1,1,1,1,1,1,1, 1461 1,1,1,1,1,1,1,1, 1462 1,1,1,1,1,1,1,1, 1463 1,1,1,1,1,1,1,1, 1464 1,1,1,1,1,1,1,1 }, 1465 0}, 1466 /* SOC_TR3_NODE_LVL_L0 L0.0 */ 1467 { SOC_TR3_NODE_LVL_L0, 0, 1468 17, SOC_TR3_SCHED_MODE_WRR, 1469 { 1,1,1,1,1,1,1,1, 1470 1,1,1,1,1,1,1,1, 1471 1,1,1,1,1,1,1,1, 1472 1,1,1,1,1,1,1,1, 1473 1,1,1,1,1,1,1,1, 1474 1,1,1,1,1,1,1,1 }, 1475 0}, 1476 /* SOC_TR3_NODE_LVL_L1 L1.0 */ 1477 { SOC_TR3_NODE_LVL_L1, 0, 1478 2, SOC_TR3_SCHED_MODE_WRR, 1479 { 1,1,1,1,1,1,1,1, 1480 1,1,1,1,1,1,1,1, 1481 1,1,1,1,1,1,1,1, 1482 1,1,1,1,1,1,1,1, 1483 1,1,1,1,1,1,1,1, 1484 1,1,1,1,1,1,1,1 }, 1485 0x1 /* 1 UC nodes, 1 MC node */}, 1486 /* SOC_TR3_NODE_LVL_L1 L1.1 */ 1487 { SOC_TR3_NODE_LVL_L1, 1, 1488 2, SOC_TR3_SCHED_MODE_WRR, 1489 { 1,1,1,1,1,1,1,1, 1490 1,1,1,1,1,1,1,1, 1491 1,1,1,1,1,1,1,1, 1492 1,1,1,1,1,1,1,1, 1493 1,1,1,1,1,1,1,1, 1494 1,1,1,1,1,1,1,1 }, 1495 0x1 /* 1 UC nodes, 1 MC node */}, 1496 /* SOC_TR3_NODE_LVL_L1 L1.2 */ 1497 { SOC_TR3_NODE_LVL_L1, 2, 1498 2, SOC_TR3_SCHED_MODE_WRR, 1499 { 1,1,1,1,1,1,1,1, 1500 1,1,1,1,1,1,1,1, 1501 1,1,1,1,1,1,1,1, 1502 1,1,1,1,1,1,1,1, 1503 1,1,1,1,1,1,1,1, 1504 1,1,1,1,1,1,1,1 }, 1505 0x1 /* 1 UC nodes, 1 MC node */}, 1506 /* SOC_TR3_NODE_LVL_L1 L1.3 */ 1507 { SOC_TR3_NODE_LVL_L1, 3, 1508 2, SOC_TR3_SCHED_MODE_WRR, 1509 { 1,1,1,1,1,1,1,1, 1510 1,1,1,1,1,1,1,1, 1511 1,1,1,1,1,1,1,1, 1512 1,1,1,1,1,1,1,1, 1513 1,1,1,1,1,1,1,1, 1514 1,1,1,1,1,1,1,1 }, 1515 0x1 /* 1 UC nodes, 1 MC node */}, 1516 /* SOC_TR3_NODE_LVL_L1 L1.4 */ 1517 { SOC_TR3_NODE_LVL_L1, 4, 1518 2, SOC_TR3_SCHED_MODE_WRR, 1519 { 1,1,1,1,1,1,1,1, 1520 1,1,1,1,1,1,1,1, 1521 1,1,1,1,1,1,1,1, 1522 1,1,1,1,1,1,1,1, 1523 1,1,1,1,1,1,1,1, 1524 1,1,1,1,1,1,1,1 }, 1525 0x1 /* 1 UC nodes, 1 MC node */}, 1526 /* SOC_TR3_NODE_LVL_L1 L1.5 */ 1527 { SOC_TR3_NODE_LVL_L1, 5, 1528 2, SOC_TR3_SCHED_MODE_WRR, 1529 { 1,1,1,1,1,1,1,1, 1530 1,1,1,1,1,1,1,1, 1531 1,1,1,1,1,1,1,1, 1532 1,1,1,1,1,1,1,1, 1533 1,1,1,1,1,1,1,1, 1534 1,1,1,1,1,1,1,1 }, 1535 0x1 /* 1 UC nodes, 1 MC node */}, 1536 /* SOC_TR3_NODE_LVL_L1 L1.6 */ 1537 { SOC_TR3_NODE_LVL_L1, 6, 1538 2, SOC_TR3_SCHED_MODE_WRR, 1539 { 1,1,1,1,1,1,1,1, 1540 1,1,1,1,1,1,1,1, 1541 1,1,1,1,1,1,1,1, 1542 1,1,1,1,1,1,1,1, 1543 1,1,1,1,1,1,1,1, 1544 1,1,1,1,1,1,1,1 }, 1545 0x1 /* 1 UC nodes, 1 MC node */}, 1546 /* SOC_TR3_NODE_LVL_L1 L1.7 */ 1547 { SOC_TR3_NODE_LVL_L1, 7, 1548 2, SOC_TR3_SCHED_MODE_WRR, 1549 { 1,1,1,1,1,1,1,1, 1550 1,1,1,1,1,1,1,1, 1551 1,1,1,1,1,1,1,1, 1552 1,1,1,1,1,1,1,1, 1553 1,1,1,1,1,1,1,1, 1554 1,1,1,1,1,1,1,1 }, 1555 0x1 /* 1 UC nodes, 1 MC node */}, 1556 /* SOC_TR3_NODE_LVL_L1 L1.8 */ 1557 { SOC_TR3_NODE_LVL_L1, 8, 1558 4, SOC_TR3_SCHED_MODE_WRR, 1559 { 1,1,1,1,1,1,1,1, 1560 1,1,1,1,1,1,1,1, 1561 1,1,1,1,1,1,1,1, 1562 1,1,1,1,1,1,1,1, 1563 1,1,1,1,1,1,1,1, 1564 1,1,1,1,1,1,1,1 }, 1565 0x3 /* 2 UC nodes, 2 MC node */}, 1566 /* SOC_TR3_NODE_LVL_L1 L1.9 */ 1567 { SOC_TR3_NODE_LVL_L1, 9, 1568 0, SOC_TR3_SCHED_MODE_STRICT, 1569 { 1,1,1,1,1,1,1,1, 1570 1,1,1,1,1,1,1,1, 1571 1,1,1,1,1,1,1,1, 1572 1,1,1,1,1,1,1,1, 1573 1,1,1,1,1,1,1,1, 1574 1,1,1,1,1,1,1,1 }, 1575 0x1 /* 1 UC nodes, 1 MC node */}, 1576 /* SOC_TR3_NODE_LVL_L1 L1.10 */ 1577 { SOC_TR3_NODE_LVL_L1, 10, 1578 0, SOC_TR3_SCHED_MODE_STRICT, 1579 { 1,1,1,1,1,1,1,1, 1580 1,1,1,1,1,1,1,1, 1581 1,1,1,1,1,1,1,1, 1582 1,1,1,1,1,1,1,1, 1583 1,1,1,1,1,1,1,1, 1584 1,1,1,1,1,1,1,1 }, 1585 0}, 1586 /* SOC_TR3_NODE_LVL_L1 L1.11 */ 1587 { SOC_TR3_NODE_LVL_L1, 11, 1588 0, SOC_TR3_SCHED_MODE_STRICT, 1589 { 1,1,1,1,1,1,1,1, 1590 1,1,1,1,1,1,1,1, 1591 1,1,1,1,1,1,1,1, 1592 1,1,1,1,1,1,1,1, 1593 1,1,1,1,1,1,1,1, 1594 1,1,1,1,1,1,1,1 }, 1595 0}, 1596 /* SOC_TR3_NODE_LVL_L1 L1.12 */ 1597 { SOC_TR3_NODE_LVL_L1, 12, 1598 0, SOC_TR3_SCHED_MODE_STRICT, 1599 { 1,1,1,1,1,1,1,1, 1600 1,1,1,1,1,1,1,1, 1601 1,1,1,1,1,1,1,1, 1602 1,1,1,1,1,1,1,1, 1603 1,1,1,1,1,1,1,1, 1604 1,1,1,1,1,1,1,1 }, 1605 0}, 1606 /* SOC_TR3_NODE_LVL_L1 L1.13 */ 1607 { SOC_TR3_NODE_LVL_L1, 13, 1608 0, SOC_TR3_SCHED_MODE_STRICT, 1609 { 1,1,1,1,1,1,1,1, 1610 1,1,1,1,1,1,1,1, 1611 1,1,1,1,1,1,1,1, 1612 1,1,1,1,1,1,1,1, 1613 1,1,1,1,1,1,1,1, 1614 1,1,1,1,1,1,1,1 }, 1615 0}, 1616 /* SOC_TR3_NODE_LVL_L1 L1.14 */ 1617 { SOC_TR3_NODE_LVL_L1, 14, 1618 0, SOC_TR3_SCHED_MODE_STRICT, 1619 { 1,1,1,1,1,1,1,1, 1620 1,1,1,1,1,1,1,1, 1621 1,1,1,1,1,1,1,1, 1622 1,1,1,1,1,1,1,1, 1623 1,1,1,1,1,1,1,1, 1624 1,1,1,1,1,1,1,1 }, 1625 0}, 1626 /* SOC_TR3_NODE_LVL_L1 L1.15 */ 1627 { SOC_TR3_NODE_LVL_L1, 15, 1628 0, SOC_TR3_SCHED_MODE_STRICT, 1629 { 1,1,1,1,1,1,1,1, 1630 1,1,1,1,1,1,1,1, 1631 1,1,1,1,1,1,1,1, 1632 1,1,1,1,1,1,1,1, 1633 1,1,1,1,1,1,1,1, 1634 1,1,1,1,1,1,1,1 }, 1635 0}, 1636 /* SOC_TR3_NODE_LVL_L1 L1.16 */ 1637 { SOC_TR3_NODE_LVL_L1, 16, 1638 0, SOC_TR3_SCHED_MODE_STRICT, 1639 { 1,1,1,1,1,1,1,1, 1640 1,1,1,1,1,1,1,1, 1641 1,1,1,1,1,1,1,1, 1642 1,1,1,1,1,1,1,1, 1643 1,1,1,1,1,1,1,1, 1644 1,1,1,1,1,1,1,1 }, 1645 0}, 1646 /* SOC_TR3_NODE_LVL_L2 */ 1647 { -1, 0, 0, -1, 1648 { 1,1,1,1,1,1,1,1, 1649 1,1,1,1,1,1,1,1, 1650 1,1,1,1,1,1,1,1, 1651 1,1,1,1,1,1,1,1, 1652 1,1,1,1,1,1,1,1, 1653 1,1,1,1,1,1,1,1 }, 1654 1 } 1655 }; 1656 1657 STATIC _soc_tr3_lls_config_t * 1658 _soc_tr3_get_config_for_level(_soc_tr3_lls_config_t *cfg_tbl, int lvl, 1659 int offset) 1660 { 1661 _soc_tr3_lls_config_t *en = cfg_tbl; 1662 1663 while (en->level != -1) { 1664 if ((en->level == lvl) && (en->node_id == offset)) { 1665 return en; 1666 } 1667 en++; 1668 } 1669 1670 return NULL; 1671 } 1672 1673 int _soc_tr3_invalid_parent_index(int unit, int level) 1674 { 1675 return _tr3_invalid_ptr[unit][level]; 1676 } 1677 1678 #define INVALID_PARENT(unit, level) _soc_tr3_invalid_parent_index((unit),(level)) 1679 1680 STATIC int 1681 soc_tr3_port_lls_init(int unit, int port, _soc_tr3_lls_config_t *cfg_tbl, 1682 int setup, _soc_tr3_lls_traverse_cb cb, void *cookie) 1683 { 1684 _soc_tr3_lls_config_t *pinfo, *cinfo; 1685 struct _tr3_sched_pending_setup_s { 1686 int parent; 1687 int level; 1688 int offset; 1689 int hw_index; 1690 } pending_list[64], *ppending; 1691 int list_size, lindex, child_lvl, uc; 1692 int l2_lvl_offsets[2], numq, lvl_offsets[4]; 1693 int spri, smcpri, num_spri, qnum, self_hw_index, c; 1694 uint32 ucmap, spmap, rval; 1695 int phy_port, mmu_port; 1696 soc_info_t *si; 1697 int sp_vec = soc_feature(unit, soc_feature_tr3_sp_vector_mask); 1698 int qcn_queue = 0; 1699 int rc = SOC_E_NONE; 1700 int weight; 1701 1702 si = &SOC_INFO(unit); 1703 1704 phy_port = si->port_l2p_mapping[port]; 1705 mmu_port = si->port_p2m_mapping[phy_port]; 1706 1707 if (sp_vec) { 1708 SOC_IF_ERROR_RETURN(READ_LLS_CONFIG0r(unit, &rval)); 1709 if (!soc_reg_field_get(unit, LLS_CONFIG0r, rval, SPRI_VECT_MODE_ENABLEf)) { 1710 soc_reg_field_set(unit, LLS_CONFIG0r, &rval, SPRI_VECT_MODE_ENABLEf, 1); 1711 SOC_IF_ERROR_RETURN(WRITE_LLS_CONFIG0r(unit, rval)); 1712 } 1713 } 1714 1715 /* To attach QCN cosq to AXP0*/ 1716 if (mmu_port == 58) { 1717 qcn_queue = 1; 1718 } 1719 1720 l2_lvl_offsets[0] = l2_lvl_offsets[1] = 0; 1721 lvl_offsets[0] = lvl_offsets[1] = lvl_offsets[2] = lvl_offsets[3] = 0; 1722 1723 /* setup port scheduler */ 1724 pending_list[0].parent = -1; 1725 pending_list[0].level = SOC_TR3_NODE_LVL_ROOT; 1726 pending_list[0].offset = 0; 1727 pending_list[0].hw_index = _SOC_TR3_ROOT_SCHEDULER_INDEX(unit, port); 1728 list_size = 1; 1729 lindex = 0; 1730 do { 1731 ppending = &pending_list[lindex++]; 1732 self_hw_index = ppending->hw_index; 1733 if (setup == _SOC_TR3_LLS_OP_TRAVERSE) { 1734 cb(unit, port, ppending->level, ppending->hw_index, cookie); 1735 } else if (ppending->parent != -1) { 1736 /* attach to parent */ 1737 SOC_IF_ERROR_RETURN( 1738 soc_tr3_cosq_set_sched_parent(unit, port, ppending->level, self_hw_index, 1739 (setup) ? ppending->parent : INVALID_PARENT(unit, ppending->level))); 1740 } 1741 1742 if (ppending->level == SOC_TR3_NODE_LVL_L2) { 1743 continue; 1744 } 1745 1746 pinfo = _soc_tr3_get_config_for_level(cfg_tbl, 1747 ppending->level, 1748 ppending->offset); 1749 if (!pinfo) { 1750 return SOC_E_INTERNAL; 1751 } 1752 1753 soc_tr3_get_child_type(unit, port, ppending->level, &child_lvl); 1754 ucmap = 0; 1755 spmap = 0; 1756 spri = -1; 1757 smcpri = -1; 1758 num_spri = 0; 1759 for (c = 0; c < pinfo->num_children; c++) { 1760 if ((setup != _SOC_TR3_LLS_OP_TRAVERSE) && 1761 (pinfo->level == SOC_TR3_NODE_LVL_L1) && (mmu_port == 58) && 1762 !qcn_queue) { 1763 /* connect EP redirect queues */ 1764 if (pinfo->uc_mc_map & (1 << c)) { 1765 continue; 1766 } 1767 weight = pinfo->weights[c]; 1768 if (pinfo->sched_mode == SOC_TR3_SCHED_MODE_WRR) { 1769 weight *= 2; 1770 } 1771 qnum = 560 + l2_lvl_offsets[0]; 1772 SOC_IF_ERROR_RETURN( 1773 soc_tr3_sched_weight_set(unit, SOC_TR3_NODE_LVL_L2, 1774 soc_tr3_l2_hw_index(unit, qnum, 0), 1775 weight)); 1776 SOC_IF_ERROR_RETURN( 1777 soc_tr3_cosq_set_sched_parent(unit, port, SOC_TR3_NODE_LVL_L2, 1778 soc_tr3_l2_hw_index(unit, qnum, 0), 1779 (setup) ? self_hw_index : 1780 INVALID_PARENT(unit, SOC_TR3_NODE_LVL_L2))); 1781 } 1782 1783 pending_list[list_size].parent = self_hw_index; 1784 pending_list[list_size].level = child_lvl; 1785 pending_list[list_size].offset = lvl_offsets[child_lvl]; 1786 lvl_offsets[child_lvl] += 1; 1787 if (child_lvl == SOC_TR3_NODE_LVL_L2) { 1788 uc = 0; /* default MC queue */ 1789 if (!IS_CPU_PORT(unit, port)) { 1790 uc = (pinfo->uc_mc_map & (1 << c)) ? 1 : 0; 1791 } 1792 1793 if (qcn_queue != 1) { 1794 rc = soc_tr3_get_def_qbase(unit, port, 1795 (uc ? _SOC_TR3_INDEX_STYLE_UCAST_QUEUE : 1796 _SOC_TR3_INDEX_STYLE_MCAST_QUEUE), &qnum, &numq); 1797 1798 if (rc) { 1799 return rc; 1800 } 1801 1802 if ((numq == 0) || (qnum < 0)) { 1803 continue; 1804 } 1805 qnum = soc_tr3_l2_hw_index(unit, qnum, uc); 1806 pending_list[list_size].hw_index = qnum + l2_lvl_offsets[uc]; 1807 l2_lvl_offsets[uc]++; 1808 } else { 1809 /* QCN queue details. */ 1810 qnum = 505; 1811 numq = 1; 1812 qcn_queue = 0; 1813 1814 qnum = soc_tr3_l2_hw_index(unit, qnum, uc); 1815 pending_list[list_size].hw_index = qnum; 1816 } 1817 if (uc) { 1818 if (spri == -1) { 1819 spri = pending_list[list_size].hw_index; 1820 } 1821 } else { 1822 if (smcpri == -1) { 1823 smcpri = pending_list[list_size].hw_index; 1824 } 1825 } 1826 if ((pinfo->sched_mode == SOC_TR3_SCHED_MODE_STRICT) && 1827 (!IS_CPU_PORT(unit, port))) { 1828 ucmap |= (uc) ? 0 : (1 << c); 1829 if (num_spri == 0) { 1830 if (uc) { 1831 spri = pending_list[list_size].hw_index; 1832 } else { 1833 smcpri = pending_list[list_size].hw_index; 1834 } 1835 } 1836 num_spri++; 1837 spmap |= 1 << c; 1838 } 1839 1840 if (setup == _SOC_TR3_LLS_OP_TRAVERSE) { 1841 list_size++; 1842 } else { 1843 SOC_IF_ERROR_RETURN( 1844 soc_tr3_cosq_set_sched_parent(unit, port, 1845 SOC_TR3_NODE_LVL_L2, 1846 pending_list[list_size].hw_index, 1847 (setup) ? self_hw_index : 1848 INVALID_PARENT(unit, SOC_TR3_NODE_LVL_L2))); 1849 1850 SOC_IF_ERROR_RETURN( 1851 soc_tr3_cosq_set_sched_mode(unit, port, SOC_TR3_NODE_LVL_L2, 1852 pending_list[list_size].hw_index, 1853 pinfo->sched_mode, pinfo->weights[c])); 1854 } 1855 } else { 1856 cinfo = _soc_tr3_get_config_for_level(cfg_tbl, child_lvl, 1857 pending_list[list_size].offset); 1858 if (!cinfo) { 1859 return SOC_E_INTERNAL; 1860 } 1861 SOC_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, 1862 port, child_lvl, pending_list[list_size].offset, 1863 &pending_list[list_size].hw_index)); 1864 if (spri == -1) { 1865 spri = pending_list[list_size].hw_index; 1866 } 1867 if (cinfo->sched_mode == SOC_TR3_SCHED_MODE_STRICT) { 1868 if (num_spri == 0) { 1869 spri = pending_list[list_size].hw_index; 1870 } 1871 num_spri++; 1872 spmap |= 1 << c; 1873 } 1874 1875 if (setup != _SOC_TR3_LLS_OP_TRAVERSE) { 1876 SOC_IF_ERROR_RETURN( 1877 soc_tr3_cosq_set_sched_parent(unit, port, child_lvl, 1878 pending_list[list_size].hw_index, 1879 (setup) ? self_hw_index : 1880 INVALID_PARENT(unit, child_lvl))); 1881 1882 1883 SOC_IF_ERROR_RETURN( 1884 soc_tr3_cosq_set_sched_mode(unit, port, child_lvl, 1885 pending_list[list_size].hw_index, 1886 cinfo->sched_mode, pinfo->weights[c])); 1887 } 1888 list_size++; 1889 } 1890 } 1891 1892 if (spri == -1) { 1893 spri = 0; 1894 } 1895 if (smcpri == -1) { 1896 smcpri = 1024; 1897 } 1898 1899 if (setup != _SOC_TR3_LLS_OP_TRAVERSE) { 1900 SOC_IF_ERROR_RETURN( 1901 soc_tr3_cosq_set_sched_child_config(unit, port, 1902 ppending->level, self_hw_index, 1903 num_spri, spri, smcpri, ucmap, spmap)); 1904 } 1905 } while (lindex < list_size); 1906 1907 return SOC_E_NONE; 1908 } 1909 1910 STATIC int 1911 soc_tr3_cpu_port_lls_init(int unit, int port, int setup, int reserve, 1912 _soc_tr3_lls_traverse_cb cb, void *cookie) 1913 { 1914 int l1_cnt[3], l2_cnt[3]; 1915 _soc_tr3_lls_config_t *lnc, *pnode; 1916 int max_q = 48, nc, l1off = 0, rv = SOC_E_NONE, cmc; 1917 int num_l0, num_l1, l0_0, l0_1, l0_2, num_nodes, w, ii, jj; 1918 1919 if (SOC_IS_HELIX4(unit)) { 1920 max_q = (reserve==0) ? 48 : 44; 1921 } else { 1922 max_q = (reserve==0) ? 48 : 45; 1923 } 1924 1925 /* alloc structure to hold lls node data, init it and kick off 1926 * soc_tr3_port_lls_init */ 1927 1928 l2_cnt[1] = l0_1 = NUM_CPU_ARM_COSQ(unit, SOC_ARM_CMC(unit, 0)); 1929 l2_cnt[2] = l0_2 = NUM_CPU_ARM_COSQ(unit, SOC_ARM_CMC(unit, 1)); 1930 l2_cnt[0] = l0_0 = max_q - (l0_1 + l0_2); 1931 1932 if (l0_0 <= 0) { 1933 return SOC_E_PARAM; 1934 } 1935 1936 num_l0 = 1 + (l0_1 > 0 ? 1 : 0) + (l0_2 > 0 ? 1 : 0); 1937 1938 /* keep a max of 8 nodes under each l1. */ 1939 l1_cnt[0] = l1_cnt[1] = l1_cnt[2] = 0; 1940 1941 l1_cnt[0] = (l0_0 + 7)/8; 1942 l1_cnt[1] = (l0_1 + 7)/8; 1943 l1_cnt[2] = (l0_2 + 7)/8; 1944 1945 num_l1 = l1_cnt[0] + l1_cnt[1] + l1_cnt[2]; 1946 1947 num_nodes = 1 /* root */ + num_l0 + num_l1 + 1 /* null last node */; 1948 1949 for (cmc = 0, ii = 0; cmc < 3; cmc++) { 1950 SHR_BITCLR_RANGE(CPU_ARM_QUEUE_BITMAP(unit, cmc), 0, 48); 1951 SHR_BITCLR_RANGE(CPU_ARM_RSVD_QUEUE_BITMAP(unit, cmc), 0, 48); 1952 for (jj = 0; jj < l2_cnt[cmc]; jj++, ii++) { 1953 SHR_BITSET(CPU_ARM_QUEUE_BITMAP(unit, cmc), ii); 1954 } 1955 NUM_CPU_ARM_COSQ(unit, cmc) = l2_cnt[cmc]; 1956 } 1957 /* Setting the max_q again to 45 so that RESERVED QUEUE BITMAP 1958 is set always set for 45, 46,47 for TR3 and HX4 */ 1959 if (SOC_IS_HELIX4(unit)) { 1960 max_q = (reserve==0) ? 48 : 45; 1961 } 1962 for (ii = max_q ; ii < 48; ii++) { 1963 cmc = ii - max_q; 1964 if (l1_cnt[cmc] > 0) { 1965 SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, cmc), ii); 1966 } 1967 } 1968 1969 lnc = sal_alloc(sizeof(_soc_tr3_lls_config_t)*num_nodes, "CPU LLS config"); 1970 if (!lnc) { 1971 return SOC_E_MEMORY; 1972 } 1973 1974 /* init root */ 1975 pnode = lnc; 1976 pnode->level = SOC_TR3_NODE_LVL_ROOT; 1977 pnode->node_id = 0; 1978 pnode->sched_mode = SOC_TR3_SCHED_MODE_WRR; 1979 pnode->num_children = num_l0; 1980 pnode->uc_mc_map = 0; 1981 for (w = 0; w < 48; w++) { 1982 pnode->weights[w] = 1; 1983 } 1984 1985 pnode++; 1986 l1off = 0; 1987 1988 for (ii = 0; ii < num_l0; ii++) { 1989 pnode->level = SOC_TR3_NODE_LVL_L0; 1990 pnode->node_id = ii; 1991 pnode->num_children = l1_cnt[ii]; 1992 pnode->sched_mode = SOC_TR3_SCHED_MODE_WRR; 1993 pnode->uc_mc_map = 0; 1994 for (w = 0; w < 48; w++) { 1995 pnode->weights[w] = 1; 1996 } 1997 pnode++; 1998 1999 for (nc = 0, jj = 0; jj < l1_cnt[ii]; jj++) { 2000 pnode->level = SOC_TR3_NODE_LVL_L1; 2001 pnode->node_id = l1off++; 2002 2003 if ((l2_cnt[ii] - nc) >= 8) { 2004 pnode->num_children = 8; 2005 } else { 2006 pnode->num_children = l2_cnt[ii] - nc; 2007 } 2008 nc += pnode->num_children; 2009 2010 pnode->sched_mode = SOC_TR3_SCHED_MODE_WRR; 2011 pnode->uc_mc_map = 0; 2012 for (w = 0; w < 48; w++) { 2013 pnode->weights[w] = 1; 2014 } 2015 pnode++; 2016 } 2017 } 2018 2019 /* null node */ 2020 pnode->level = -1; 2021 pnode->node_id = -1; 2022 pnode->num_children = 0; 2023 pnode->uc_mc_map = 0; 2024 2025 rv = soc_tr3_port_lls_init(unit, port, lnc, setup, cb, cookie); 2026 2027 sal_free(lnc); 2028 return rv; 2029 } 2030 2031 _soc_tr3_axp_lls_config _tr3_axp_lls_config[] = { 2032 {58, {-1, 1504, -1}, {8, 8, 0}}, 2033 {59, {-1, -1, -1}, {8, 0, 0}}, 2034 {60, {-1, 1528, -1}, {0, 1, 0}}, 2035 {61, {1529, 1512, 1584}, {1, 8, 8}} 2036 }; 2037 2038 int 2039 _soc_tr3_cosq_axp_node_validate(int unit, int local_port, int hw_index, int to_cos) 2040 { 2041 int port, node_index = -1; 2042 int axp_min, axp_max, found; 2043 int count = 0; 2044 2045 if (hw_index == -1) { 2046 return SOC_E_PARAM; 2047 } 2048 for (port = 0; port < 4; port++) { 2049 if (_tr3_axp_lls_config[port].local_port == local_port) { 2050 count = 0; 2051 found = 0; 2052 while (count < 3) { 2053 axp_min = _tr3_axp_lls_config[port].base[count]; 2054 if ((axp_min == -1) && (hw_index < 1024)) { 2055 /* Check if hw_index is a valid UC */ 2056 axp_max = _tr3_axp_lls_config[port].numq[count]; 2057 node_index = to_cos; 2058 if (node_index < axp_max) { 2059 found = 1; 2060 break; 2061 } 2062 } else if ((axp_min != -1) && (hw_index >= 1024)) { 2063 /* Check if hw_index is valid AXP MC */ 2064 node_index = hw_index; 2065 axp_max = axp_min + _tr3_axp_lls_config[port].numq[count]; 2066 if ((node_index >= axp_min) && 2067 (node_index < axp_max)) { 2068 found = 1; 2069 break; 2070 } 2071 } 2072 count++; 2073 } 2074 if (found == 1) { 2075 return SOC_E_NONE; 2076 } 2077 } 2078 } 2079 return SOC_E_PARAM; 2080 } 2081 2082 STATIC int 2083 _soc_tr3_ce_port_index(int unit, int port) 2084 { 2085 int phy_port, mmu_port; 2086 soc_info_t *si; 2087 2088 si = &SOC_INFO(unit); 2089 2090 phy_port = si->port_l2p_mapping[port]; 2091 mmu_port = si->port_p2m_mapping[phy_port]; 2092 2093 if (mmu_port == 48) { 2094 return 0; 2095 } else if (mmu_port == 52) { 2096 return 1; 2097 } 2098 return -1; 2099 } 2100 2101 #define TR3_DFL_HSP_SCHED_MODE SOC_TR3_SCHED_MODE_WDRR 2102 2103 STATIC int 2104 soc_tr3_setup_hsp_port(int unit, int port) 2105 { 2106 int ceid, hw_index, qnum; 2107 soc_field_t f; 2108 uint32 rval; 2109 static const soc_field_t hl0basef[] = { 2110 PORT0_L0_OFFSETf, PORT1_L0_OFFSETf 2111 }; 2112 static const soc_field_t hl2basef[] = { 2113 PORT0_UCQ_OFFSETf, PORT1_UCQ_OFFSETf 2114 }; 2115 static const soc_field_t hspef[] = { 2116 HSP0f, HSP1f 2117 }; 2118 2119 if (!_SOC_TR3_IS_HSP_PORT(unit, port)) { 2120 return SOC_E_PARAM; 2121 } 2122 2123 SOC_IF_ERROR_RETURN(soc_tr3_sched_hw_index_get(unit, port, 2124 SOC_TR3_NODE_LVL_L0, 0, &hw_index)); 2125 SOC_IF_ERROR_RETURN(soc_tr3_hsp_sched_hw_index_get(unit, port, 2126 SOC_TR3_NODE_LVL_L0, 0, 0, &hw_index)); 2127 ceid = _soc_tr3_ce_port_index(unit, port); 2128 if (ceid == -1) { 2129 return SOC_E_PARAM; 2130 } 2131 2132 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HSP_CONFIGr, port, 0, &rval)); 2133 f = hl0basef[ceid]; 2134 soc_reg_field_set(unit, HSP_CONFIGr, &rval, f, 2135 ((hw_index - 1) >= 0) ? (hw_index - 1) : 0); 2136 soc_tr3_get_def_qbase(unit, port, _SOC_TR3_INDEX_STYLE_UCAST_QUEUE, 2137 &qnum, NULL); 2138 f = hl2basef[ceid]; 2139 soc_reg_field_set(unit, HSP_CONFIGr, &rval, f, qnum/4); 2140 2141 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, HSP_CONFIGr, port, 0, rval)); 2142 2143 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_L0_CONFIGr, port, 0, &rval)); 2144 soc_reg_field_set(unit, HES_L0_CONFIGr, &rval, MCQ_MODEf, 1); 2145 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, HES_L0_CONFIGr, port, 0, rval)); 2146 2147 /* Ensure that when scheduling minumum bandwidth, SC and QM take precedence */ 2148 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_PORT_CONFIGr, port, 0, &rval)); 2149 soc_reg_field_set(unit, HES_PORT_CONFIGr, &rval, MINSPCONFIGf, (1 << 9)); 2150 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, HES_PORT_CONFIGr, port, 0, rval)); 2151 2152 /* Set special queue group COS (SC and QM) to strict priority */ 2153 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, L0_COSWEIGHTSr, port, 9, &rval)); 2154 soc_reg_field_set(unit, L0_COSWEIGHTSr, &rval, COSWEIGHTSf, 0); 2155 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, L0_COSWEIGHTSr, port, 9, rval)); 2156 2157 /* Enable HSP */ 2158 SOC_IF_ERROR_RETURN 2159 (soc_reg32_get(unit, MMU_CFG_HSP_CONFIGr, port, 0, &rval)); 2160 soc_reg_field_set(unit, MMU_CFG_HSP_CONFIGr, &rval, hspef[ceid], 1); 2161 SOC_IF_ERROR_RETURN 2162 (soc_reg32_set(unit, MMU_CFG_HSP_CONFIGr, port, 0, rval)); 2163 2164 return SOC_E_NONE; 2165 } 2166 2167 STATIC int _soc_tr3_lls_init(int unit) 2168 { 2169 _soc_tr3_b0_cb_t *pcb; 2170 uint32 mmu_bmp[4]; 2171 int ii, port; 2172 int phy_port, mmu_port; 2173 soc_info_t *si; 2174 2175 si = &SOC_INFO(unit); 2176 2177 if (_soc_tr3_init_done[unit]) { 2178 return SOC_E_NONE; 2179 } 2180 2181 if (soc_feature(unit, soc_feature_tr3_sp_vector_mask)) { 2182 pcb = &_tr3_b0_unit_data[unit]; 2183 pcb->lock = sal_mutex_create("tr3_b0_dyn_lock"); 2184 for (ii = 0; ii < _SOC_TR3_DYN_SET; ii++) { 2185 pcb->port[ii] = -1; 2186 } 2187 2188 if (!soc_feature(unit, soc_feature_cmic_reserved_queues)) { 2189 tr3_cpu_num_sched_at_lvl[1] += 3; 2190 } 2191 } 2192 2193 _tr3_invalid_ptr[unit][SOC_TR3_NODE_LVL_ROOT] = -1; 2194 _tr3_invalid_ptr[unit][SOC_TR3_NODE_LVL_L1] = 2195 soc_mem_index_max(unit, LLS_L0_PARENTm); 2196 _tr3_invalid_ptr[unit][SOC_TR3_NODE_LVL_L2] = 2197 soc_mem_index_max(unit, LLS_L1_PARENTm); 2198 _tr2_node_max[unit][SOC_TR3_NODE_LVL_L0] = soc_mem_index_max(unit, LLS_L0_CONFIGm); 2199 _tr2_node_max[unit][SOC_TR3_NODE_LVL_L1] = soc_mem_index_max(unit, LLS_L1_CONFIGm); 2200 2201 sal_memset(mmu_bmp, 0, sizeof(uint32)*4); 2202 PBMP_ALL_ITER(unit, port) { 2203 phy_port = si->port_l2p_mapping[port]; 2204 mmu_port = si->port_p2m_mapping[phy_port]; 2205 mmu_bmp[mmu_port/32] |= 1 << (mmu_port % 32); 2206 } 2207 2208 for (ii = 0; ii < soc_mem_index_max(unit, LLS_L0_PARENTm); ii++) { 2209 if ((mmu_bmp[ii/32] & (1 << (ii % 32))) == 0) { 2210 _tr3_invalid_ptr[unit][SOC_TR3_NODE_LVL_L0] = ii; 2211 break; 2212 } 2213 } 2214 _soc_tr3_init_done[unit] = 1; 2215 return SOC_E_NONE; 2216 } 2217 2218 int soc_tr3_lls_init(int unit) 2219 { 2220 int dyn_mode, dyn_ports = 0, lvl, i; 2221 int port, rv = SOC_E_NONE; 2222 uint32 entry[SOC_MAX_MEM_WORDS]; 2223 soc_mem_t mem; 2224 int phy_port, mmu_port; 2225 soc_info_t *si; 2226 2227 si = &SOC_INFO(unit); 2228 2229 SOC_IF_ERROR_RETURN(_soc_tr3_lls_init(unit)); 2230 2231 PBMP_ALL_ITER(unit, port) { 2232 if (soc_feature(unit, soc_feature_tr3_sp_vector_mask)) { 2233 /* For TR3 >= B0 Rev, SW workaround for Dyn update is not needed. */ 2234 _bcm_tr3_port_sdyn[unit][port] = 0; 2235 } else { 2236 _bcm_tr3_port_sdyn[unit][port] = soc_property_port_get(unit, port, 2237 spn_PORT_SCHED_DYNAMIC, 0); 2238 } 2239 2240 if (_SOC_TR3_IS_HSP_PORT(unit, port)) { 2241 continue; 2242 } else if (IS_CPU_PORT(unit, port)) { 2243 dyn_ports += 1; 2244 } else if (_bcm_tr3_port_sdyn[unit][port]) { 2245 dyn_ports += 16; 2246 } else { 2247 dyn_ports += 8; 2248 } 2249 } 2250 if (dyn_ports >= 512) { 2251 /* Too many dynamic ports for HW resources. 2252 * Use static mode instead. 2253 */ 2254 LOG_ERROR(BSL_LS_SOC_COSQ, 2255 (BSL_META_U(unit, 2256 "unit %d : Cannot configure requested dynamic scheduler ports.\n" 2257 "\tAvailable HW resources exhausted.\n"), 2258 unit)); 2259 return SOC_E_RESOURCE; 2260 } 2261 2262 /* set the parent memories to a reserved scheduler instance at each level */ 2263 for (lvl = SOC_TR3_NODE_LVL_L0; lvl <= SOC_TR3_NODE_LVL_L2; lvl++) { 2264 mem = _SOC_TR3_NODE_PARENT_MEM(lvl); 2265 2266 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 2267 soc_mem_field32_set(unit, mem, entry, C_PARENTf, INVALID_PARENT(unit, lvl)); 2268 2269 for (i = 0; i <= soc_mem_index_max(unit, mem); i++) { 2270 SOC_IF_ERROR_RETURN 2271 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, &entry)); 2272 } 2273 } 2274 2275 PBMP_ALL_ITER(unit, port) { 2276 phy_port = si->port_l2p_mapping[port]; 2277 mmu_port = si->port_p2m_mapping[phy_port]; 2278 2279 dyn_mode = _bcm_tr3_port_sdyn[unit][port]; 2280 if (_SOC_TR3_IS_HSP_PORT(unit, port)) { 2281 rv = soc_tr3_setup_hsp_port(unit, port); 2282 } else if (IS_CPU_PORT(unit, port)) { 2283 if (soc_feature(unit, soc_feature_cmic_reserved_queues)) { 2284 rv = soc_tr3_cpu_port_lls_init(unit, port, _SOC_TR3_LLS_OP_SETUP, 2285 TRUE, NULL, NULL); 2286 } else { 2287 rv = soc_tr3_cpu_port_lls_init(unit, port, _SOC_TR3_LLS_OP_SETUP, 2288 FALSE, NULL, NULL); 2289 } 2290 } else if (mmu_port == 61) { 2291 rv = soc_tr3_port_lls_init(unit, port, _tr3_port_sm_lls_config, 2292 _SOC_TR3_LLS_OP_SETUP, NULL, NULL); 2293 } else { 2294 if (soc_port_hg_capable(unit, port)) { 2295 rv = soc_tr3_port_lls_init(unit, port, 2296 (dyn_mode) ? _tr3_hg_port_dyn_lls_config : _tr3_hg_port_lls_config, 2297 _SOC_TR3_LLS_OP_SETUP, NULL, NULL); 2298 } else if (mmu_port == 58) { 2299 rv = soc_tr3_port_lls_init(unit, port, 2300 _tr3_lb_port_lls_config, 2301 _SOC_TR3_LLS_OP_SETUP, NULL, NULL); 2302 } else { 2303 rv = soc_tr3_port_lls_init(unit, port, 2304 (dyn_mode) ? _tr3_port_dyn_lls_config : _tr3_port_lls_config, 2305 _SOC_TR3_LLS_OP_SETUP, NULL, NULL); 2306 } 2307 } 2308 if (rv) { 2309 return SOC_E_INTERNAL; 2310 } 2311 } 2312 return SOC_E_NONE; 2313 } 2314 2315 int soc_tr3_lls_port_uninit(int unit, soc_port_t port) 2316 { 2317 int rv = SOC_E_INTERNAL; 2318 2319 if (_SOC_TR3_IS_HSP_PORT(unit, port)) { 2320 rv = SOC_E_UNAVAIL; 2321 } else if (IS_CPU_PORT(unit, port)) { 2322 if (soc_feature(unit, soc_feature_cmic_reserved_queues)) { 2323 rv = soc_tr3_cpu_port_lls_init(unit, port, _SOC_TR3_LLS_OP_TEAR, 1, NULL, NULL); 2324 } else { 2325 rv = soc_tr3_cpu_port_lls_init(unit, port, _SOC_TR3_LLS_OP_TEAR, 0, NULL, NULL); 2326 } 2327 } else { 2328 if (soc_port_hg_capable(unit, port)) { 2329 rv = soc_tr3_port_lls_init(unit, port, _tr3_hg_port_lls_config, 2330 _SOC_TR3_LLS_OP_TEAR, NULL, NULL); 2331 } else { 2332 rv = soc_tr3_port_lls_init(unit, port, _tr3_port_lls_config, 2333 _SOC_TR3_LLS_OP_TEAR, NULL, NULL); 2334 } 2335 } 2336 2337 return rv; 2338 } 2339 2340 /* To reinstate Queue mapping for LB(Internal ports) */ 2341 int soc_tr3_lb_lls_init(int unit) 2342 { 2343 int axp_port, phy_port, mmu_port, rv = SOC_E_NONE; 2344 soc_info_t *si; 2345 2346 si = &SOC_INFO(unit); 2347 2348 PBMP_AXP_ITER(unit, axp_port) { 2349 phy_port = si->port_l2p_mapping[axp_port]; 2350 mmu_port = si->port_p2m_mapping[phy_port]; 2351 rv = soc_tr3_port_lls_init(unit, axp_port, 2352 (mmu_port == 61) ? _tr3_port_sm_lls_config : (mmu_port == 58) ? 2353 _tr3_lb_port_lls_config : _tr3_port_lls_config, 2354 _SOC_TR3_LLS_OP_SETUP, NULL, NULL); 2355 if (rv < 0) { 2356 return SOC_E_INTERNAL; 2357 } 2358 } 2359 return 0; 2360 } 2361 2362 int soc_tr3_lb_lls_port_uninit(int unit, int axp_port) 2363 { 2364 int phy_port, mmu_port, rv = SOC_E_NONE; 2365 soc_info_t *si; 2366 2367 si = &SOC_INFO(unit); 2368 2369 if (!SOC_PBMP_MEMBER(PBMP_AXP_ALL(unit), axp_port)) { 2370 return SOC_E_PARAM; 2371 } 2372 phy_port = si->port_l2p_mapping[axp_port]; 2373 mmu_port = si->port_p2m_mapping[phy_port]; 2374 rv = soc_tr3_port_lls_init(unit, axp_port, 2375 (mmu_port == 61) ? _tr3_port_sm_lls_config : (mmu_port == 58) ? 2376 _tr3_lb_port_lls_config : _tr3_port_lls_config, 2377 _SOC_TR3_LLS_OP_TEAR, NULL, NULL); 2378 if (rv < 0) { 2379 return SOC_E_INTERNAL; 2380 } 2381 return 0; 2382 } 2383 2384 /* Disable Queuing on all L2 queues */ 2385 int soc_tr3_lls_l2_disable(int unit) 2386 { 2387 uint32 entry[SOC_MAX_MEM_WORDS]; 2388 int i, port, start_hw_index, numq = 0; 2389 soc_mem_t mem; 2390 2391 mem = MMU_THDO_Q_TO_QGRP_MAPm; 2392 2393 for (i = 0; i <= soc_mem_index_max(unit, mem); i++) { 2394 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 2395 MEM_BLOCK_ANY, i, &entry)); 2396 soc_mem_field32_set(unit, mem , entry, DISABLE_QUEUINGf, 1); 2397 SOC_IF_ERROR_RETURN 2398 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, &entry)); 2399 } 2400 2401 PBMP_ALL_ITER(unit, port) { 2402 if (!_SOC_TR3_IS_HSP_PORT(unit, port)) { 2403 continue; 2404 } 2405 start_hw_index = SOC_INFO(unit).port_uc_cosq_base[port]; 2406 numq = SOC_INFO(unit).port_num_uc_cosq[port]; 2407 for (i = start_hw_index; i < (start_hw_index + numq); i++) { 2408 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, 2409 MEM_BLOCK_ANY, i, &entry)); 2410 soc_mem_field32_set(unit, mem , entry, DISABLE_QUEUINGf, 0); 2411 SOC_IF_ERROR_RETURN 2412 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, &entry)); 2413 } 2414 } 2415 return 0; 2416 } 2417 2418 int soc_tr3_lls_reset(int unit) 2419 { 2420 int lvl, i; 2421 uint32 entry[SOC_MAX_MEM_WORDS]; 2422 soc_mem_t mem; 2423 int alloc_size, port; 2424 uint32 *bmap = NULL; 2425 2426 PBMP_ALL_ITER(unit, port) { 2427 for (lvl = SOC_TR3_NODE_LVL_L0; lvl <= SOC_TR3_NODE_LVL_L2; lvl++) { 2428 mem = _SOC_TR3_NODE_PARENT_MEM(lvl); 2429 /* coverity[negative_returns : FALSE] */ 2430 alloc_size = SHR_BITALLOCSIZE(soc_mem_index_count(unit, mem)); 2431 if (lvl == SOC_TR3_NODE_LVL_L0) { 2432 if (SOC_CONTROL(unit)->port_lls_l0_bmap[port] == NULL) { 2433 SOC_CONTROL(unit)->port_lls_l0_bmap[port] = 2434 sal_alloc(alloc_size, "LLS_L0_BMAP"); 2435 } 2436 bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 2437 } else if (lvl == SOC_TR3_NODE_LVL_L1) { 2438 if (SOC_CONTROL(unit)->port_lls_l1_bmap[port] == NULL) { 2439 SOC_CONTROL(unit)->port_lls_l1_bmap[port] = 2440 sal_alloc(alloc_size, "LLS_L1_BMAP"); 2441 } 2442 bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 2443 } else if (lvl == SOC_TR3_NODE_LVL_L2) { 2444 if (SOC_CONTROL(unit)->port_lls_l2_bmap[port] == NULL) { 2445 SOC_CONTROL(unit)->port_lls_l2_bmap[port] = 2446 sal_alloc(alloc_size, "LLS_L2_BMAP"); 2447 } 2448 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 2449 } 2450 sal_memset(bmap, 0, alloc_size); 2451 } 2452 } 2453 2454 for (lvl = SOC_TR3_NODE_LVL_L0; lvl <= SOC_TR3_NODE_LVL_L2; lvl++) { 2455 mem = _SOC_TR3_NODE_PARENT_MEM(lvl); 2456 2457 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 2458 soc_mem_field32_set(unit, mem, entry, C_PARENTf, INVALID_PARENT(unit, lvl)); 2459 2460 for (i = 0; i <= soc_mem_index_max(unit, mem); i++) { 2461 SOC_IF_ERROR_RETURN 2462 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, &entry)); 2463 } 2464 } 2465 2466 return 0; 2467 } 2468 2469 int soc_tr3_port_lls_traverse(int unit, soc_port_t port, 2470 _soc_tr3_lls_traverse_cb cb, void *cookie) 2471 { 2472 int rv = SOC_E_INTERNAL; 2473 int phy_port, mmu_port; 2474 soc_info_t *si; 2475 int dyn_mode; 2476 2477 si = &SOC_INFO(unit); 2478 phy_port = si->port_l2p_mapping[port]; 2479 mmu_port = si->port_p2m_mapping[phy_port]; 2480 dyn_mode = _bcm_tr3_port_sdyn[unit][port]; 2481 2482 if (_SOC_TR3_IS_HSP_PORT(unit, port)) { 2483 rv = SOC_E_UNAVAIL; 2484 } else if (IS_CPU_PORT(unit, port)) { 2485 if (soc_feature(unit, soc_feature_cmic_reserved_queues)) { 2486 rv = soc_tr3_cpu_port_lls_init(unit, port, _SOC_TR3_LLS_OP_TRAVERSE, 2487 1, cb, cookie); 2488 } else { 2489 rv = soc_tr3_cpu_port_lls_init(unit, port, _SOC_TR3_LLS_OP_TRAVERSE, 2490 0, cb, cookie); 2491 } 2492 }else if (mmu_port == 61) { 2493 rv = soc_tr3_port_lls_init(unit, port, _tr3_port_sm_lls_config, 2494 _SOC_TR3_LLS_OP_TRAVERSE, cb, cookie); 2495 } else { 2496 if (soc_port_hg_capable(unit, port)) { 2497 rv = soc_tr3_port_lls_init(unit, port, 2498 (dyn_mode) ? _tr3_hg_port_dyn_lls_config : _tr3_hg_port_lls_config, 2499 _SOC_TR3_LLS_OP_TRAVERSE, cb, cookie); 2500 }else if (mmu_port == 58) { 2501 rv = soc_tr3_port_lls_init(unit, port, _tr3_lb_port_lls_config, 2502 _SOC_TR3_LLS_OP_TRAVERSE, cb, cookie); 2503 } else { 2504 rv = soc_tr3_port_lls_init(unit, port, 2505 (dyn_mode) ? _tr3_port_dyn_lls_config : _tr3_port_lls_config, 2506 _SOC_TR3_LLS_OP_TRAVERSE, cb, cookie); 2507 } 2508 } 2509 2510 return rv; 2511 } 2512 int 2513 soc_tr3_hsp_sched_hw_index_get(int unit, int port, int lvl, int index, 2514 int offset, int *hw_index) 2515 { 2516 int ceid, uc_queue_base, mc_queue_base; 2517 soc_field_t f; 2518 uint32 rval; 2519 2520 static const soc_field_t hl2basef[] = { 2521 PORT0_UCQ_OFFSETf, PORT1_UCQ_OFFSETf 2522 }; 2523 2524 if (!_SOC_TR3_IS_HSP_PORT(unit, port)) { 2525 return SOC_E_PARAM; 2526 } 2527 if ((lvl != SOC_TR3_NODE_LVL_L0) && (lvl != SOC_TR3_NODE_LVL_L2)) { 2528 return SOC_E_PARAM; 2529 } 2530 2531 if (lvl == SOC_TR3_NODE_LVL_L0) { 2532 ceid = _soc_tr3_ce_port_index(unit, port); 2533 if (ceid == -1) { 2534 return SOC_E_PARAM; 2535 } 2536 if (offset >= _SOC_HSP_VALID_L0_END) { 2537 *hw_index = -1; 2538 return SOC_E_PARAM; 2539 } 2540 *hw_index = _SOC_HSP_L0_BASE_HW_INDEX + 2541 ( _SOC_HSP_L0_PER_PORT_OFFSET * ceid ) + offset; 2542 return SOC_E_NONE; 2543 } 2544 ceid = _soc_tr3_ce_port_index(unit, port); 2545 if (ceid == -1) { 2546 return SOC_E_PARAM; 2547 } 2548 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HSP_CONFIGr, port, 0, &rval)); 2549 f = hl2basef[ceid]; 2550 uc_queue_base = soc_reg_field_get(unit, HSP_CONFIGr, rval, f); 2551 uc_queue_base = uc_queue_base * 4; 2552 soc_tr3_get_def_qbase(unit, port, _SOC_TR3_INDEX_STYLE_MCAST_QUEUE, 2553 &mc_queue_base, NULL); 2554 if ((index < _SOC_HSP_VALID_L0_START) || 2555 (index > _SOC_HSP_VALID_L0_END)) { 2556 return SOC_E_PARAM; 2557 } 2558 if ((offset < _SOC_HSP_MIN_QUEUE_OFFSET) || 2559 (offset > _SOC_HSP_MAX_QUEUE_OFFSET)) { 2560 return SOC_E_PARAM; 2561 } 2562 if (index == _SOC_HSP_VALID_L0_END) { 2563 if ((offset == 0) || (offset == 1)) { 2564 /* UC Queue */ 2565 *hw_index = uc_queue_base + _SOC_HSP_LAST_L0_UC_START + offset; 2566 } else { 2567 /* MC Queue */ 2568 *hw_index = mc_queue_base + _SOC_HSP_LAST_L0_UC_START + 2569 (offset - _SOC_HSP_LAST_L0_MAX_UC_QUEUE ); 2570 } 2571 } else { 2572 if (offset > 1) { 2573 return SOC_E_PARAM; 2574 } 2575 if (offset == 0) { 2576 /* UC Queue */ 2577 *hw_index = uc_queue_base + index - _SOC_HSP_VALID_L0_START; 2578 } else { 2579 /* MC Queue */ 2580 *hw_index = mc_queue_base + index - _SOC_HSP_VALID_L0_START; 2581 } 2582 } 2583 return SOC_E_NONE; 2584 } 2585 int 2586 soc_tr3_sched_hw_index_get(int unit, int port, int lvl, int offset, 2587 int *hw_index) 2588 { 2589 int local_port, base = 0, ceid, num_at_lvl = 0; 2590 int phy_port, mmu_port; 2591 soc_info_t *si; 2592 int sp_vec = soc_feature(unit, soc_feature_tr3_sp_vector_mask); 2593 int top_offset = (_tr3_invalid_ptr[unit][lvl] == -1) ? 0 : 1; 2594 int dyn_mode = 0; 2595 2596 si = &SOC_INFO(unit); 2597 2598 if (_SOC_TR3_IS_HSP_PORT(unit, port)) { 2599 if (lvl != SOC_TR3_NODE_LVL_L0) { 2600 return SOC_E_PARAM; 2601 } 2602 ceid = _soc_tr3_ce_port_index(unit, port); 2603 if (ceid == -1) { 2604 return SOC_E_PARAM; 2605 } 2606 if (offset >= _SOC_HSP_VALID_L0_END) { 2607 *hw_index = -1; 2608 return SOC_E_PARAM; 2609 } 2610 *hw_index = _SOC_HSP_L0_BASE_HW_INDEX + 2611 ( _SOC_HSP_L0_PER_PORT_OFFSET * ceid ) + offset; 2612 return SOC_E_NONE; 2613 } 2614 2615 PBMP_ALL_ITER(unit, local_port) { 2616 dyn_mode = _bcm_tr3_port_sdyn[unit][local_port]; 2617 phy_port = si->port_l2p_mapping[local_port]; 2618 mmu_port = si->port_p2m_mapping[phy_port]; 2619 2620 if (IS_CPU_PORT(unit, local_port)) { 2621 num_at_lvl = tr3_cpu_num_sched_at_lvl[lvl]; 2622 } else if (_SOC_TR3_IS_HSP_PORT(unit, local_port)) { 2623 continue; 2624 } else if (mmu_port == 61) { 2625 num_at_lvl = tr3_sm_port_num_sched_at_lvl[lvl]; 2626 } else if (mmu_port == 58) { 2627 num_at_lvl = tr3_lb_port_num_sched_at_lvl[lvl]; 2628 } else { 2629 if (soc_port_hg_capable(unit, local_port)) { 2630 num_at_lvl = tr3_hg_port_num_sched_at_lvl[lvl]; 2631 } else { 2632 num_at_lvl = tr3_port_num_sched_at_lvl[lvl]; 2633 } 2634 } 2635 2636 if ((lvl == SOC_TR3_NODE_LVL_L1) && (dyn_mode)) { 2637 num_at_lvl += 8; 2638 } 2639 2640 if (local_port == port) { 2641 if (sp_vec && IS_CPU_PORT(unit, local_port) && 2642 (lvl == SOC_TR3_NODE_LVL_L0) && (!soc_feature(unit, soc_feature_cmic_reserved_queues))) { 2643 offset += 3; 2644 } 2645 2646 if (offset > num_at_lvl) { 2647 return SOC_E_PARAM; 2648 } 2649 2650 if ((offset >= 8) && ((!dyn_mode))) { 2651 *hw_index = _tr2_node_max[unit][lvl] - (top_offset + 1); 2652 if ((base + 8) > *hw_index) { 2653 return SOC_E_RESOURCE; 2654 } 2655 } else { 2656 *hw_index = base + offset; 2657 } 2658 return SOC_E_NONE; 2659 } else { 2660 if ((!dyn_mode) && (num_at_lvl > 8)) { 2661 top_offset += num_at_lvl - 8; 2662 num_at_lvl = 8; 2663 } 2664 base += num_at_lvl; 2665 } 2666 } 2667 2668 return SOC_E_PARAM; 2669 } 2670 2671 #define MMU_CMIC_PORT 59 2672 #define MMU_SM_PORT 61 2673 2674 int soc_tr3_get_mcq_count(int unit) 2675 { 2676 return 561; 2677 } 2678 2679 /*The architectural limit on unicast queues is 1024*/ 2680 #define _BCM_TR3_NUM_L2_UC_LEAVES 1024 2681 2682 /* 2683 * Allow upto 32 unicast queues to be allocated per ports. Some customers 2684 * have special queueing requirements that require many additional unicast 2685 * queues to be reserved at initialization time. 2686 */ 2687 #define _MAX_UNICAST_QUEUES_PER_PORT 32 2688 int 2689 soc_tr3_get_def_qbase(int unit, soc_port_t inport, int qtype, 2690 int *pbase, int *pnumq) 2691 { 2692 int base = 0, numq = 0, dflt_cnt; 2693 int port, phy_port, mmu_port = 0; 2694 soc_info_t *si; 2695 2696 si = &SOC_INFO(unit); 2697 2698 if (qtype == _SOC_TR3_INDEX_STYLE_UCAST_QUEUE) { 2699 PBMP_ALL_ITER(unit, port) { 2700 phy_port = si->port_l2p_mapping[port]; 2701 if (phy_port == -1) { 2702 continue; 2703 } 2704 mmu_port = si->port_p2m_mapping[phy_port]; 2705 if (_SOC_TR3_IS_HSP_PORT(unit, port)) { 2706 numq = 16; 2707 } else if (mmu_port == MMU_CMIC_PORT) { 2708 numq = 0; 2709 } else if (mmu_port == MMU_SM_PORT) { 2710 numq = 8; 2711 } else { 2712 dflt_cnt = soc_port_hg_capable(unit, port) ? 10 : 8; 2713 if ((!IS_LB_PORT(unit, port)) && 2714 (_bcm_tr3_port_numq[unit][port] == 0)) { 2715 numq = _bcm_tr3_port_numq[unit][port] = 2716 soc_property_port_get(unit, port, spn_LLS_NUM_L2UC, dflt_cnt); 2717 } else { 2718 numq = _bcm_tr3_port_numq[unit][port]; 2719 } 2720 2721 if ((numq < dflt_cnt) || (numq > _MAX_UNICAST_QUEUES_PER_PORT)) { 2722 numq = dflt_cnt; 2723 } 2724 } 2725 if (inport == port) { 2726 break; 2727 } 2728 numq = (numq + 3) & ~3; 2729 base += numq; 2730 if (base >= _BCM_TR3_NUM_L2_UC_LEAVES) { 2731 LOG_ERROR(BSL_LS_SOC_COSQ, 2732 (BSL_META_U(unit, 2733 "unit %d : Cannot configure requested number of unicast queues per port;\n" 2734 "Available queue resources (%d queues) exhausted.\n"), 2735 unit, _BCM_TR3_NUM_L2_UC_LEAVES)); 2736 return SOC_E_CONFIG; 2737 } 2738 } 2739 } else if (qtype == _SOC_TR3_INDEX_STYLE_MCAST_QUEUE) { 2740 mmu_port = si->port_p2m_mapping[si->port_l2p_mapping[inport]]; 2741 if (_SOC_TR3_IS_HSP_PORT(unit, inport)) { 2742 numq = 10; 2743 } else if (mmu_port == MMU_CMIC_PORT) { 2744 numq = soc_feature(unit, soc_feature_cmic_reserved_queues) ? 45 : 48; 2745 } else if (mmu_port == MMU_SM_PORT) { 2746 numq = 1; 2747 } else if ((mmu_port == 57) || (mmu_port == 62)) { 2748 numq = 0; 2749 } else { 2750 numq = ((mmu_port >= 40) && (mmu_port <= 55)) ? 10 : 8; 2751 } 2752 if (mmu_port <= 39) { 2753 base = mmu_port * 8; 2754 } else if (mmu_port <= 55) { 2755 base = 320 + (mmu_port - 40) * 10; 2756 } else if (mmu_port == 56) { 2757 base = 480; 2758 } else if (mmu_port <= 57) { 2759 base = -1; 2760 } else if (mmu_port == 58) { 2761 base = 488; 2762 } else if (mmu_port <= 59) { 2763 base = 512; 2764 } else if (mmu_port == 60) { 2765 base = 496; 2766 } else if (mmu_port == 61) { 2767 base = 504; 2768 } else if (mmu_port == 62) { 2769 base = 0; 2770 } 2771 } 2772 2773 /* Pushing the queues used for LB ports to bottom */ 2774 if (qtype == _SOC_TR3_INDEX_STYLE_UCAST_QUEUE) { 2775 if (mmu_port == 56) { 2776 base = 1008; 2777 } else if (mmu_port == 62) { 2778 base = 1016; 2779 } else if (mmu_port == 61) { 2780 base = 1000; 2781 } 2782 } 2783 2784 if (pbase) { 2785 *pbase = base; 2786 } 2787 if (pnumq) { 2788 *pnumq = numq; 2789 } 2790 return SOC_E_NONE; 2791 } 2792 2793 int soc_port_hg_capable(int unit, int port) 2794 { 2795 int phy_port, mmu_port; 2796 soc_info_t *si; 2797 2798 si = &SOC_INFO(unit); 2799 phy_port = si->port_l2p_mapping[port]; 2800 mmu_port = si->port_p2m_mapping[phy_port]; 2801 2802 if ((mmu_port >= 40) && (mmu_port <= 55)) { 2803 return 1; 2804 } 2805 return 0; 2806 } 2807 2808 int soc_tr3_l2_hw_index(int unit, int qnum, int uc) 2809 { 2810 return ((uc==0) ? 1024 : 0) + qnum; 2811 } 2812 2813 STATIC int 2814 _soc_tr3_dump_sched_at(int unit, int port, int level, int offset, int hw_index) 2815 { 2816 int num_spri, first_child, first_mc_child, rv, cindex; 2817 uint32 ucmap, spmap; 2818 soc_tr3_sched_mode_e sched_mode; 2819 soc_mem_t mem; 2820 int index_max, ii, ci, child_level, wt = 0, num_child; 2821 uint32 entry[SOC_MAX_MEM_WORDS]; 2822 char *lvl_name[] = { "Root", "L0", "L1", "L2" }; 2823 char *sched_modes[] = {"X", "SP", "WRR", "WDRR"}; 2824 2825 if ((level >= SOC_TR3_NODE_LVL_L0) && 2826 (level < SOC_TR3_NODE_LVL_L2) && (hw_index == INVALID_PARENT(unit, level + 1))) { 2827 return SOC_E_NONE; 2828 } 2829 2830 /* get sched config */ 2831 SOC_IF_ERROR_RETURN( 2832 soc_tr3_sched_get_node_config(unit, port, level, hw_index, 2833 &num_spri, &first_child, &first_mc_child, &ucmap, &spmap)); 2834 2835 sched_mode = 0; 2836 if (level != SOC_TR3_NODE_LVL_ROOT) { 2837 SOC_IF_ERROR_RETURN( 2838 soc_tr3_cosq_get_sched_mode(unit, port, level, hw_index, &sched_mode, &wt)); 2839 } 2840 2841 if (level == SOC_TR3_NODE_LVL_L1) { 2842 LOG_CLI((BSL_META_U(unit, 2843 " %s.%d : INDEX=%d NUM_SP=%d FC=%d FMC=%d " 2844 "UCMAP=0x%08x SPMAP=0x%08x MODE=%s WT=%d\n"), 2845 lvl_name[level], offset, hw_index, num_spri, 2846 first_child, first_mc_child, ucmap, spmap, 2847 sched_modes[sched_mode], wt)); 2848 } else { 2849 LOG_CLI((BSL_META_U(unit, 2850 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d SPMAP=0x%08x " 2851 "MODE=%s WT=%d\n"), 2852 lvl_name[level], offset, hw_index, num_spri, first_child, 2853 spmap, sched_modes[sched_mode], wt)); 2854 } 2855 2856 soc_tr3_get_child_type(unit, port, level, &child_level); 2857 mem = _SOC_TR3_NODE_PARENT_MEM(child_level); 2858 2859 if(mem == INVALIDm) { 2860 return SOC_E_INTERNAL; 2861 } 2862 index_max = soc_mem_index_max(unit, mem); 2863 2864 num_child = 0; 2865 for (ii = 0, ci = 0; ii <= index_max; ii++) { 2866 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &entry); 2867 if (rv) { 2868 LOG_CLI((BSL_META_U(unit, 2869 "Failed to read memory at index: %d\n"), ii)); 2870 break; 2871 } 2872 2873 cindex = soc_mem_field32_get(unit, mem, entry, C_PARENTf); 2874 if (cindex == hw_index) { 2875 if (child_level == SOC_TR3_NODE_LVL_L2) { 2876 SOC_IF_ERROR_RETURN(soc_tr3_cosq_get_sched_mode(unit, port, 2877 SOC_TR3_NODE_LVL_L2, ii, &sched_mode, &wt)); 2878 LOG_CLI((BSL_META_U(unit, 2879 " L2.%s INDEX=%d Mode=%s WEIGHT=%d\n"), 2880 ((ii < 1024) ? "uc" : "mc"), 2881 ii, sched_modes[sched_mode], wt)); 2882 } else { 2883 _soc_tr3_dump_sched_at(unit, port, child_level, ci, ii); 2884 ci += 1; 2885 } 2886 num_child += 1; 2887 } 2888 } 2889 if (num_child == 0) { 2890 LOG_CLI((BSL_META_U(unit, 2891 "*** No children \n"))); 2892 } 2893 return SOC_E_NONE; 2894 } 2895 2896 int soc_tr3_dump_port_lls(int unit, int port) 2897 { 2898 if (_SOC_TR3_IS_HSP_PORT(unit, port)) { 2899 return SOC_E_NONE; 2900 } 2901 2902 LOG_CLI((BSL_META_U(unit, 2903 "-------%s (LLS)------\n"), SOC_PORT_NAME(unit, (port)))); 2904 2905 _soc_tr3_dump_sched_at(unit, port, SOC_TR3_NODE_LVL_ROOT, 0, 2906 _SOC_TR3_ROOT_SCHEDULER_INDEX(unit, port)); 2907 return SOC_E_NONE; 2908 } 2909 2910 int soc_tr3_dump_port_hsp(int unit, int port) 2911 { 2912 soc_field_t f; 2913 int ceid; 2914 uint32 rval; 2915 int hw_index, mc_index, l2_queue, mcq_queue; 2916 int i, mcq_mode, q_spmap, wt, spmap, wrrmap , qnum, portwrr; 2917 static const soc_field_t hl0basef[] = { 2918 PORT0_L0_OFFSETf, PORT1_L0_OFFSETf 2919 }; 2920 static const soc_field_t hl2basef[] = { 2921 PORT0_UCQ_OFFSETf, PORT1_UCQ_OFFSETf 2922 }; 2923 2924 if (!_SOC_TR3_IS_HSP_PORT(unit, port)) { 2925 return SOC_E_PARAM; 2926 } 2927 2928 ceid = _soc_tr3_ce_port_index(unit, port); 2929 if (ceid == -1) { 2930 return SOC_E_PARAM; 2931 } 2932 2933 LOG_CLI((BSL_META_U(unit, 2934 "-------%s (HSP)------\n"), SOC_PORT_NAME(unit, (port)))); 2935 2936 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HSP_CONFIGr, port, 0, &rval)); 2937 f = hl0basef[ceid]; 2938 hw_index = soc_reg_field_get(unit, HSP_CONFIGr, rval, f); 2939 f = hl2basef[ceid]; 2940 qnum = soc_reg_field_get(unit, HSP_CONFIGr, rval, f); 2941 qnum *= 4; 2942 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_PORT_CONFIGr, port, 0, &rval)); 2943 spmap = soc_reg_field_get(unit, HES_PORT_CONFIGr, rval, MINSPCONFIGf); 2944 portwrr = soc_reg_field_get(unit, HES_PORT_CONFIGr, rval, SCHEDULING_SELECTf); 2945 soc_tr3_get_def_qbase(unit, port, _SOC_TR3_INDEX_STYLE_MCAST_QUEUE, 2946 &mc_index, NULL); 2947 2948 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_L0_CONFIGr, port, 0, &rval)); 2949 mcq_mode = soc_reg_field_get(unit, HES_L0_CONFIGr, rval, MCQ_MODEf); 2950 wrrmap = soc_reg_field_get(unit, HES_L0_CONFIGr, rval, SCHEDULING_SELECTf); 2951 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_MINSPr, port, 0, &rval)); 2952 q_spmap = soc_reg_field_get(unit, HES_Q_MINSPr, rval, MINSPCONFIGf); 2953 2954 LOG_CLI((BSL_META_U(unit, 2955 " Root.0 : INDEX=%d PSPMAP=0x%03x QSPMAP=0x%05x FC=%d " 2956 "MODE=%s WT=0\n"), 2957 _SOC_TR3_ROOT_SCHEDULER_INDEX(unit, port), spmap, q_spmap, 2958 hw_index, 2959 "X")); 2960 2961 2962 l2_queue = 0; 2963 mcq_queue = 0; 2964 for (i = 0; i < 10; i++ ) { 2965 2966 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, L0_COSWEIGHTSr, port, i, &rval)); 2967 wt = soc_reg_field_get(unit, L0_COSWEIGHTSr, rval, COSWEIGHTSf); 2968 2969 LOG_CLI((BSL_META_U(unit, 2970 " L0.%d : INDEX=%d FC=%d FMC=%d " 2971 "MODE=%s WT=%d\n"), 2972 i, hw_index + i , 2973 (i == 0) ? 0 : qnum + l2_queue, 2974 ((i == 0) && (mcq_mode == 1)) ? 0 : 2975 ((i > 0) && (i < 9) && (mcq_mode == 0)) ? 0 : mc_index + mcq_queue , 2976 (wt == 0) ? "SP" : (wrrmap & (1<<i)) ? "WDRR":"WRR", 2977 wt)); 2978 if (( i != 0) && (i != 9)) { 2979 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_COSWEIGHTSr, port, l2_queue, &rval)); 2980 wt = soc_reg_field_get(unit, HES_Q_COSWEIGHTSr, rval, COSWEIGHTSf); 2981 LOG_CLI((BSL_META_U(unit, 2982 " L1.uc : INDEX=%d " 2983 "MODE=%s WT=%d\n"), 2984 qnum + l2_queue , 2985 (wt == 0) ? "SP" : (portwrr ? "DWRR" :"WRR"), 2986 wt)); 2987 l2_queue++; 2988 2989 } 2990 if ((mcq_mode == 0)) { 2991 if ( i == 0 ) { 2992 for (mcq_queue = 0; mcq_queue < 8 ; mcq_queue++) { 2993 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_COSWEIGHTSr, port, mcq_queue + 10, &rval)); 2994 wt = soc_reg_field_get(unit, HES_Q_COSWEIGHTSr, rval, COSWEIGHTSf); 2995 LOG_CLI((BSL_META_U(unit, 2996 " L1.mc : INDEX=%d " 2997 "MODE=%s WT=%d\n"), 2998 mc_index + mcq_queue, 2999 (wt == 0) ? "SP" :(portwrr ? "DWRR" :"WRR"), 3000 wt)); 3001 } 3002 } 3003 } else { 3004 if (( i != 0) && (i != 9)) { 3005 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_COSWEIGHTSr, port, mcq_queue + 10, &rval)); 3006 wt = soc_reg_field_get(unit, HES_Q_COSWEIGHTSr, rval, COSWEIGHTSf); 3007 LOG_CLI((BSL_META_U(unit, 3008 " L1.mc : INDEX=%d " 3009 "MODE=%s WT=%d\n"), 3010 mc_index + mcq_queue, 3011 (wt == 0) ? "SP" :(portwrr ? "DWRR" :"WRR"), 3012 wt)); 3013 mcq_queue++; 3014 } 3015 } 3016 if (i == 9) { 3017 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_COSWEIGHTSr, port, l2_queue, &rval)); 3018 wt = soc_reg_field_get(unit, HES_Q_COSWEIGHTSr, rval, COSWEIGHTSf); 3019 LOG_CLI((BSL_META_U(unit, 3020 " L1.uc : INDEX=%d " 3021 "MODE=%s WT=%d\n"), 3022 qnum + l2_queue , 3023 (wt == 0) ? "SP" :(portwrr ? "DWRR" :"WRR"), 3024 wt)); 3025 l2_queue++; 3026 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_COSWEIGHTSr, port, l2_queue, &rval)); 3027 wt = soc_reg_field_get(unit, HES_Q_COSWEIGHTSr, rval, COSWEIGHTSf); 3028 LOG_CLI((BSL_META_U(unit, 3029 " L1.uc : INDEX=%d " 3030 "MODE=%s WT=%d\n"), 3031 qnum + l2_queue , 3032 (wt == 0) ? "SP" :(portwrr ? "DWRR" :"WRR"), 3033 wt)); 3034 l2_queue++; 3035 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_COSWEIGHTSr, port, mcq_queue + 10, &rval)); 3036 wt = soc_reg_field_get(unit, HES_Q_COSWEIGHTSr, rval, COSWEIGHTSf); 3037 LOG_CLI((BSL_META_U(unit, 3038 " L1.mc : INDEX=%d " 3039 "MODE=%s WT=%d\n"), 3040 mc_index + mcq_queue, 3041 (wt == 0) ? "SP" :(portwrr ? "DWRR" :"WRR"), 3042 wt)); 3043 mcq_queue++; 3044 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, HES_Q_COSWEIGHTSr, port, mcq_queue + 10, &rval)); 3045 wt = soc_reg_field_get(unit, HES_Q_COSWEIGHTSr, rval, COSWEIGHTSf); 3046 LOG_CLI((BSL_META_U(unit, 3047 " L1.mc : INDEX=%d " 3048 "MODE=%s WT=%d\n"), 3049 mc_index + mcq_queue, 3050 (wt == 0) ? "SP" :(portwrr ? "DWRR" :"WRR"), 3051 wt)); 3052 mcq_queue++; 3053 } 3054 3055 } 3056 return SOC_E_NONE; 3057 } 3058 3059 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */ 3060 3061