cosq.c (70581B)
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 * APACHE MMU/Cosq soc routines 8 */ 9 10 #include <sal/core/libc.h> 11 #include <shared/bsl.h> 12 #include <soc/debug.h> 13 #include <soc/util.h> 14 #include <soc/mem.h> 15 #include <soc/trident2.h> 16 #include <soc/apache.h> 17 18 #if defined(BCM_APACHE_SUPPORT) 19 20 21 #define _AP_COSQ_CPU_RESERVED_L0_BASE 261 22 #define _AP_COSQ_CPU_RESERVED_L0_NUM 4 23 24 #define _AP_HSP_PORT_MAX_COS 8 25 26 27 typedef struct soc_apache_fc_map_shadow_memory_s { 28 soc_mem_t mem; 29 uint32 *mem_shadow; 30 }soc_apache_fc_map_shadow_memory_t; 31 32 typedef struct soc_apache_fc_map_shadow_s { 33 soc_apache_fc_map_shadow_memory_t* shadow_array; 34 int mem_count; 35 }soc_apache_fc_map_shadow_t; 36 37 38 static soc_mem_t fc_map_mems[] = { 39 MMU_INTFI_XPIPE_FC_MAP_TBL0m, 40 MMU_INTFI_XPIPE_FC_MAP_TBL1m 41 }; 42 43 static soc_apache_fc_map_shadow_t soc_apache_fc_map_shadow[SOC_MAX_NUM_DEVICES]; 44 45 static int _ap_invalid_ptr[SOC_MAX_NUM_DEVICES][SOC_APACHE_NODE_LVL_MAX]; 46 #define INVALID_PARENT(unit, level) _soc_apache_invalid_parent_index((unit),(level)) 47 48 /* Programming all the entries with the Invalid Parent Pointer */ 49 STATIC int 50 soc_apache_set_invalid_parent(int unit) 51 { 52 int level, index_max, index; 53 soc_mem_t mem; 54 uint32 entry[SOC_MAX_MEM_WORDS]; 55 for (level = SOC_APACHE_NODE_LVL_S1; level <= SOC_APACHE_NODE_LVL_L2; 56 level++) { 57 mem = _SOC_APACHE_NODE_PARENT_MEM(unit, -1, level); 58 /* coverity[negative_returns : FALSE] */ 59 index_max = soc_mem_index_max(unit, mem); 60 for (index = 0; index <= index_max; index++) { 61 SOC_IF_ERROR_RETURN 62 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 63 soc_mem_field32_set(unit, mem, entry, 64 (level == SOC_APACHE_NODE_LVL_S1) ? 65 P_PORTf: C_PARENTf, INVALID_PARENT(unit,level)); 66 67 SOC_IF_ERROR_RETURN 68 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry)); 69 } 70 } 71 return SOC_E_NONE; 72 } 73 74 STATIC int 75 soc_apache_init_invalid_parents(int unit) 76 { 77 78 79 _ap_invalid_ptr[unit][SOC_APACHE_NODE_LVL_ROOT] = -1; 80 _ap_invalid_ptr[unit][SOC_APACHE_NODE_LVL_S1] = 0x7f ; 81 _ap_invalid_ptr[unit][SOC_APACHE_NODE_LVL_L0] = 82 soc_mem_index_max(unit, LLS_S1_PARENTm); 83 _ap_invalid_ptr[unit][SOC_APACHE_NODE_LVL_L1] = 84 soc_mem_index_max(unit, LLS_L0_PARENTm); 85 _ap_invalid_ptr[unit][SOC_APACHE_NODE_LVL_L2] = 86 soc_mem_index_max(unit, LLS_L1_PARENTm); 87 return SOC_E_NONE; 88 } 89 90 int _soc_apache_invalid_parent_index(int unit, int level) 91 { 92 return _ap_invalid_ptr[unit][level]; 93 } 94 95 #define _SOC_APACHE_DEF_SCHED_NODE_BASE(u,p,cfg,t) \ 96 (cfg)[(t)].base_factor * (p) 97 98 soc_apache_sched_type_t 99 _soc_apache_port_sched_type_get(int unit, soc_port_t port) 100 { 101 soc_info_t *si; 102 103 si = &SOC_INFO(unit); 104 return SOC_PBMP_MEMBER(si->eq_pbm, port) ? 105 SOC_APACHE_SCHED_HSP : SOC_APACHE_SCHED_LLS; 106 } 107 108 int soc_apache_port_common_attributes_get(int unit, int port, int *pipe, 109 int *mmu_port, int *phy_port) 110 { 111 int lphy_port, lmmu_port; 112 soc_info_t *si; 113 114 si = &SOC_INFO(unit); 115 116 if (pipe) { 117 *pipe = 0; 118 } 119 120 lphy_port = si->port_l2p_mapping[port]; 121 lmmu_port = si->port_p2m_mapping[lphy_port]; 122 123 if (phy_port) { 124 *phy_port = lphy_port; 125 } 126 127 if (mmu_port) { 128 *mmu_port = lmmu_port; 129 } 130 return 0; 131 } 132 133 int _soc_apache_root_scheduler_index(int unit, int port) 134 { 135 int mmu_port, in_pipe; 136 137 SOC_IF_ERROR_RETURN( 138 soc_apache_port_common_attributes_get(unit, port, &in_pipe, &mmu_port, NULL)); 139 140 return mmu_port; 141 } 142 143 int _soc_apache_s1_scheduler_index(int unit, int port, int level, int hw_index) 144 { 145 soc_mem_t mem; 146 int c_parent; 147 uint32 entry[SOC_MAX_MEM_WORDS]; 148 if(level == SOC_APACHE_NODE_LVL_S1) { 149 return hw_index; 150 } else if (level >= SOC_APACHE_NODE_LVL_L0) { 151 mem = _SOC_APACHE_NODE_PARENT_MEM(unit, port, level); 152 SOC_IF_ERROR_RETURN 153 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 154 c_parent = soc_mem_field32_get(unit, mem, entry, 155 C_PARENTf); 156 if(level == SOC_APACHE_NODE_LVL_L0) { 157 return c_parent; 158 } 159 mem = _SOC_APACHE_NODE_PARENT_MEM(unit, port, level - 1); 160 SOC_IF_ERROR_RETURN 161 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, c_parent, &entry)); 162 c_parent = soc_mem_field32_get(unit, mem, entry, 163 C_PARENTf); 164 if(level == SOC_APACHE_NODE_LVL_L1) { 165 return c_parent; 166 } 167 mem = _SOC_APACHE_NODE_PARENT_MEM(unit, port, level - 2); 168 SOC_IF_ERROR_RETURN 169 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, c_parent, &entry)); 170 c_parent = soc_mem_field32_get(unit, mem, entry, 171 C_PARENTf); 172 if(level == SOC_APACHE_NODE_LVL_L2) { 173 return c_parent; 174 } 175 176 } 177 return -1; 178 } 179 180 STATIC int 181 _soc_apache_flush_queue(int unit, int port, int queue_hw_index) 182 { 183 return 0; 184 } 185 186 soc_error_t 187 soc_apache_cosq_disable_hsp_sched(int unit, soc_port_t in_port) 188 { 189 int mmu_port; 190 uint32 fval, rval; 191 192 SOC_IF_ERROR_RETURN 193 (soc_apache_port_common_attributes_get(unit, in_port, NULL, &mmu_port, NULL)); 194 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval)); 195 fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, IS_HSP_PORT_IN_XPIPEf); 196 fval &= ~(1 << mmu_port); 197 soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, IS_HSP_PORT_IN_XPIPEf, fval); 198 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval)); 199 return SOC_E_NONE; 200 } 201 202 int 203 soc_apache_cosq_enable_hsp_sched(int unit, soc_port_t in_port) 204 { 205 int mmu_port; 206 uint32 fval, rval; 207 208 SOC_IF_ERROR_RETURN( 209 soc_apache_port_common_attributes_get(unit, in_port, NULL, &mmu_port, NULL)); 210 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval)); 211 fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, 212 IS_HSP_PORT_IN_XPIPEf); 213 fval |= (1 << mmu_port); 214 soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, 215 IS_HSP_PORT_IN_XPIPEf, fval); 216 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval)); 217 return SOC_E_NONE; 218 } 219 220 221 int 222 soc_apache_cosq_set_sched_parent(int unit, soc_port_t port, 223 int level, int hw_index, 224 int parent_hw_idx, int add) 225 { 226 soc_apache_sched_type_t sched_type; 227 uint32 entry[SOC_MAX_MEM_WORDS], fval, rval; 228 soc_mem_t mem; 229 int l0off, l1off; 230 uint32 *bmap = NULL; 231 soc_port_t mmu_port; 232 LOG_INFO(BSL_LS_SOC_COSQ, 233 (BSL_META_U(unit, 234 "Port:%d L%d : %d parent:%d\n"), 235 port, level - 1, hw_index, parent_hw_idx)); 236 237 sched_type = _soc_apache_port_sched_type_get(unit, port); 238 239 if (sched_type == SOC_APACHE_SCHED_LLS) { 240 mem = _SOC_APACHE_NODE_PARENT_MEM(unit, port, level); 241 if (mem == INVALIDm) { 242 return SOC_E_INTERNAL; 243 } 244 245 SOC_IF_ERROR_RETURN 246 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 247 #if 0 248 /* disconnecting the queue , flush it */ 249 if ((parent_hw_idx == INVALID_PARENT(unit, level)) && 250 (level == SOC_APACHE_NODE_LVL_L2)) { 251 SOC_IF_ERROR_RETURN(_soc_apache_flush_queue(unit, port, hw_index)); 252 } 253 #endif 254 255 soc_mem_field32_set(unit, mem, entry, 256 level == SOC_APACHE_NODE_LVL_S1 ? P_PORTf : 257 C_PARENTf, add ? parent_hw_idx: INVALID_PARENT(unit, level)); 258 SOC_IF_ERROR_RETURN 259 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 260 } else if (sched_type == SOC_APACHE_SCHED_HSP) { 261 if (level == SOC_APACHE_NODE_LVL_L1) { 262 l0off = parent_hw_idx % 5; 263 l1off = hw_index % 10; 264 SOC_IF_ERROR_RETURN( 265 soc_apache_port_common_attributes_get(unit, port, 266 NULL, &mmu_port, NULL)); 267 268 269 if (parent_hw_idx == INVALID_PARENT(unit, level)) { 270 SOC_IF_ERROR_RETURN(_soc_apache_flush_queue(unit,mmu_port, hw_index)); 271 } 272 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 273 unit, port, l0off, &rval)); 274 275 fval = soc_reg_field_get(unit, HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 276 rval, CHILDREN_CONNECTION_MAPf); 277 278 if (l1off >= 8) { 279 l1off -= 2; 280 } 281 282 if (!add) { 283 fval &= ~(1 << l1off); 284 } else { 285 fval |= 1 << l1off; 286 } 287 soc_reg_field_set(unit, HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 288 &rval, CHILDREN_CONNECTION_MAPf, fval); 289 290 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 291 unit, port, l0off, rval)); 292 293 } 294 } 295 if (level == SOC_APACHE_NODE_LVL_S1) { 296 bmap = SOC_CONTROL(unit)->port_lls_s1_bmap[port]; 297 } else if (level == SOC_APACHE_NODE_LVL_L0) { 298 bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 299 } else if (level == SOC_APACHE_NODE_LVL_L1) { 300 bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 301 } else if (level == SOC_APACHE_NODE_LVL_L2) { 302 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 303 } else { 304 return SOC_E_PARAM; 305 } 306 307 SOC_LLS_SCHEDULER_LOCK(unit); 308 if (!add) { 309 SHR_BITCLR(bmap, hw_index); 310 } else { 311 SHR_BITSET(bmap, hw_index); 312 } 313 SOC_LLS_SCHEDULER_UNLOCK(unit); 314 315 return SOC_E_NONE; 316 } 317 318 int 319 soc_apache_sched_weight_set(int unit, int port, int level, 320 int hw_index, int weight) 321 { 322 soc_apache_sched_type_t sched_type; 323 uint32 entry[SOC_MAX_MEM_WORDS], rval; 324 soc_mem_t mem = INVALIDm; 325 soc_reg_t reg = INVALIDr; 326 327 LOG_INFO(BSL_LS_SOC_COSQ, 328 (BSL_META_U(unit, 329 "sched_weight_set L%d csch_index=%d wt=%d\n"), 330 level, hw_index, weight)); 331 332 sched_type = _soc_apache_port_sched_type_get(unit, port); 333 334 if (weight > 0x7f) { 335 return SOC_E_PARAM; 336 } 337 if (sched_type == SOC_APACHE_SCHED_LLS) { 338 mem = _SOC_APACHE_NODE_WIEGHT_MEM(unit, port, level); 339 if (mem == INVALIDm) { 340 return SOC_E_INTERNAL; 341 } 342 if ((mem == LLS_L2_CHILD_WEIGHT_CFG_CNTm) && 343 (hw_index > soc_mem_index_max(unit, mem))) { 344 hw_index -= (soc_mem_index_max(unit, mem) + 1); 345 mem = LLS_L2_MC_CHILD_WEIGHT_CFG_CNTm; 346 } 347 if ((mem == LLS_S1_CHILD_WEIGHT_CFG_CNTm) && 348 (weight == 0)) { 349 return SOC_E_PARAM; 350 } 351 352 SOC_IF_ERROR_RETURN 353 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 354 soc_mem_field32_set(unit, mem, &entry, C_WEIGHTf, weight); 355 SOC_IF_ERROR_RETURN 356 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 357 } else if (sched_type == SOC_APACHE_SCHED_HSP) { 358 if ((level == SOC_APACHE_NODE_LVL_L0) || (level == SOC_APACHE_NODE_LVL_L1)) { 359 if (level == SOC_APACHE_NODE_LVL_L0) { 360 hw_index = hw_index % 5; 361 reg = HSP_SCHED_L0_NODE_WEIGHTr; 362 } else if (level == SOC_APACHE_NODE_LVL_L1) { 363 hw_index = hw_index % 10; 364 reg = HSP_SCHED_L1_NODE_WEIGHTr; 365 } 366 367 rval = 0; 368 soc_reg_field_set(unit, reg, &rval, WEIGHTf, weight); 369 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, hw_index, rval)); 370 } else if (level == SOC_APACHE_NODE_LVL_L2) { 371 if (hw_index < soc_mem_index_max(unit, LLS_L2_CHILD_WEIGHT_CFG_CNTm)) 372 { 373 reg = HSP_SCHED_L2_UC_QUEUE_WEIGHTr; 374 hw_index = hw_index % 10; 375 } else { 376 reg = HSP_SCHED_L2_MC_QUEUE_WEIGHTr; 377 hw_index = (hw_index - 16384) % 10; 378 } 379 380 rval = 0; 381 soc_reg_field_set(unit, reg, &rval, WEIGHTf, weight); 382 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, hw_index, rval)); 383 } 384 } 385 return SOC_E_NONE; 386 } 387 388 int 389 soc_apache_sched_weight_get(int unit, int port, int level, 390 int hw_index, int *weight) 391 { 392 soc_apache_sched_type_t sched_type; 393 uint32 entry[SOC_MAX_MEM_WORDS], rval; 394 soc_mem_t mem = INVALIDm; 395 soc_reg_t reg = INVALIDr; 396 397 sched_type = _soc_apache_port_sched_type_get(unit, port); 398 399 if (sched_type == SOC_APACHE_SCHED_LLS) { 400 mem = _SOC_APACHE_NODE_WIEGHT_MEM(unit, port, level); 401 if (mem == INVALIDm) { 402 return SOC_E_INTERNAL; 403 } 404 if (mem == LLS_L2_CHILD_WEIGHT_CFG_CNTm && 405 (hw_index > soc_mem_index_max(unit, mem))) { 406 hw_index -= soc_mem_index_max(unit, mem) + 1; 407 mem = LLS_L2_MC_CHILD_WEIGHT_CFG_CNTm; 408 } 409 SOC_IF_ERROR_RETURN 410 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 411 *weight = soc_mem_field32_get(unit, mem, &entry, C_WEIGHTf); 412 } else if (sched_type == SOC_APACHE_SCHED_HSP) { 413 if ((level == SOC_APACHE_NODE_LVL_L0) || (level == SOC_APACHE_NODE_LVL_L1)) { 414 if (level == SOC_APACHE_NODE_LVL_L0) { 415 hw_index = hw_index % 5; 416 reg = HSP_SCHED_L0_NODE_WEIGHTr; 417 } else if (level == SOC_APACHE_NODE_LVL_L1) { 418 hw_index = hw_index % 10; 419 reg = HSP_SCHED_L1_NODE_WEIGHTr; 420 } 421 422 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, hw_index, &rval)); 423 *weight = soc_reg_field_get(unit, reg, rval, WEIGHTf); 424 } else if (level == SOC_APACHE_NODE_LVL_L2) { 425 if (hw_index < 16384) 426 { 427 reg = HSP_SCHED_L2_UC_QUEUE_WEIGHTr; 428 hw_index = hw_index % 10; 429 } else { 430 reg = HSP_SCHED_L2_MC_QUEUE_WEIGHTr; 431 hw_index = (hw_index - 16384)% 10; 432 } 433 434 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, hw_index, &rval)); 435 *weight = soc_reg_field_get(unit, reg, rval, WEIGHTf); 436 } 437 } 438 439 LOG_INFO(BSL_LS_SOC_COSQ, 440 (BSL_META_U(unit, 441 "sched_weight_set L%d csch_index=%d wt=%d\n"), 442 level, hw_index, *weight)); 443 444 return SOC_E_NONE; 445 } 446 447 int 448 soc_apache_cosq_set_sched_child_config(int unit, soc_port_t port, 449 int level, int index, 450 int num_spri, int first_sp_child, 451 int first_sp_mc_child, uint32 ucmap) 452 { 453 soc_apache_sched_type_t sched_type; 454 uint32 entry[SOC_MAX_MEM_WORDS]; 455 soc_mem_t mem; 456 457 LOG_INFO(BSL_LS_SOC_COSQ, 458 (BSL_META_U(unit, 459 "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x\n"), 460 port, (level == 0) ? "r" : "", level - 1, 461 index, first_sp_child, first_sp_mc_child, ucmap)); 462 463 mem = INVALIDm; 464 465 sched_type = _soc_apache_port_sched_type_get(unit, port); 466 if (sched_type == SOC_APACHE_SCHED_HSP) { 467 return SOC_E_PARAM; 468 } 469 470 mem = _SOC_APACHE_NODE_CONFIG_MEM(unit, port, level); 471 if (mem == INVALIDm) { 472 return SOC_E_PARAM; 473 } 474 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 475 soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, num_spri); 476 if (mem == LLS_L1_CONFIGm) { 477 soc_mem_field32_set(unit, mem, &entry, P_START_UC_SPRIf, first_sp_child); 478 soc_mem_field32_set(unit, mem, &entry, P_START_MC_SPRIf, 479 first_sp_mc_child); 480 soc_mem_field32_set(unit, mem, &entry, P_SPRI_SELECTf, 481 (num_spri > 0) ? ucmap : 0); 482 } else { 483 soc_mem_field32_set(unit, mem, &entry, P_START_SPRIf, first_sp_child); 484 } 485 486 SOC_IF_ERROR_RETURN(soc_mem_write 487 (unit, mem, MEM_BLOCK_ANY, index, &entry)); 488 489 return SOC_E_NONE; 490 } 491 492 int 493 soc_apache_cosq_set_sched_mode(int unit, soc_port_t port, int level, int index, 494 const soc_apache_sched_mode_e mode, int weight) 495 { 496 soc_apache_sched_type_t sched_type; 497 uint32 entry[SOC_MAX_MEM_WORDS], mfval = 0, rval = 0, wrr_mask, pmap; 498 soc_mem_t mem; 499 soc_reg_t reg; 500 soc_reg_t lls_per_port[] = { 501 LLS_PER_PORT_WRR_PKT_MODE_0r, 502 LLS_PER_PORT_WRR_PKT_MODE_1r, 503 LLS_PER_PORT_WRR_PKT_MODE_2r 504 }; 505 uint32 mc_group_mode; 506 int fval, idx, parent_idx = -1; 507 508 LOG_INFO(BSL_LS_SOC_COSQ, 509 (BSL_META_U(unit, 510 "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"), 511 port, (level == 0) ? "r" : "", level - 1, 512 index, mode, weight)); 513 514 reg = INVALIDr; 515 mem = INVALIDm; 516 sched_type = _soc_apache_port_sched_type_get(unit, port); 517 if (sched_type == SOC_APACHE_SCHED_HSP) { 518 /* get the port relative index / offset */ 519 if (level == SOC_APACHE_NODE_LVL_L0) { 520 index = index % 5; 521 reg = HSP_SCHED_PORT_CONFIGr; 522 parent_idx = 0; 523 } else if (level == SOC_APACHE_NODE_LVL_L1) { 524 index = index % 10; 525 reg = HSP_SCHED_L0_NODE_CONFIGr; 526 /* Find the Parent index for the current child */ 527 for (idx = 1; idx < 5; idx++) { 528 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 529 unit, port, idx, &rval)); 530 fval = soc_reg_field_get(unit, 531 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 532 rval, CHILDREN_CONNECTION_MAPf); 533 if (idx == 4) { 534 if ((index >= 8) && (fval & (1 << (index - 2)))) { 535 parent_idx = idx; 536 break; 537 } 538 } else { 539 if (fval & (1 << index)) { 540 parent_idx = idx; 541 break; 542 } 543 } 544 } 545 } else if (level == SOC_APACHE_NODE_LVL_L2) { 546 mc_group_mode = soc_reg_field_get( unit, 547 HSP_SCHED_PORT_CONFIGr, rval, 548 MC_GROUP_MODEf); 549 reg = HSP_SCHED_L1_NODE_CONFIGr; 550 if (mc_group_mode && (index >= 16384)) { 551 parent_idx = (index - 16384) % 10; 552 if ( parent_idx < _AP_HSP_PORT_MAX_COS) { 553 reg = HSP_SCHED_L0_NODE_CONFIGr; 554 parent_idx = 0; 555 } 556 }else { 557 parent_idx = index % 10; 558 } 559 } else { 560 return SOC_E_PARAM; 561 } 562 563 if (parent_idx == -1) { 564 return SOC_E_INTERNAL; 565 } 566 567 if (mode == SOC_APACHE_SCHED_MODE_STRICT) { 568 weight = 0; 569 } else if (mode == SOC_APACHE_SCHED_MODE_WRR) { 570 mfval = 1; 571 } else if (mode == SOC_APACHE_SCHED_MODE_WDRR) { 572 mfval = 0; 573 } else { 574 return SOC_E_PARAM; 575 } 576 577 /* selection between SP and WxRR is based on weight property. */ 578 SOC_IF_ERROR_RETURN(soc_apache_sched_weight_set(unit, port, 579 level, index, weight)); 580 581 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 582 wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf); 583 wrr_mask &= ~(1 << parent_idx); 584 wrr_mask |= (mfval << parent_idx); 585 soc_reg_field_set(unit, reg, &rval, ENABLE_WRRf, wrr_mask); 586 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 587 588 } else { 589 if (mode == SOC_APACHE_SCHED_MODE_STRICT) { 590 weight = 0; 591 } 592 593 SOC_IF_ERROR_RETURN(soc_apache_sched_weight_set(unit, port, 594 level, index, weight)); 595 596 if (mode != SOC_APACHE_SCHED_MODE_STRICT) { 597 mem = _SOC_APACHE_NODE_CONFIG_MEM(unit, port, SOC_APACHE_NODE_LVL_S1); 598 index = _soc_apache_s1_scheduler_index(unit, port, level, index); 599 if (index == -1) { 600 return SOC_E_INTERNAL; 601 } 602 SOC_IF_ERROR_RETURN( 603 soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 604 soc_mem_field32_set(unit, mem, entry, 605 PACKET_MODE_WRR_ACCOUNTING_ENABLEf, 606 (mode == SOC_APACHE_SCHED_MODE_WRR) ? 1 : 0); 607 SOC_IF_ERROR_RETURN( 608 soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry)); 609 } 610 } 611 if ((mode == SOC_APACHE_SCHED_MODE_WRR) && (!IS_CPU_PORT(unit, port))) { 612 reg = lls_per_port[port/32]; 613 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 614 pmap = soc_reg_field_get(unit, reg, rval, WRR_PKT_MODEf); 615 pmap = pmap | (1 << port); 616 soc_reg_field_set(unit, reg, &rval,WRR_PKT_MODEf, pmap); 617 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 618 } 619 return SOC_E_NONE; 620 } 621 622 /* number of registers in the set to support Dynamic Scheduling */ 623 #define _SOC_APACHE_DYN_REGISTER_SET 4 624 625 /* Structure to maintain the ports that are undergoing dyn sched*/ 626 typedef struct _soc_apache_port_dyn_sched_s { 627 sal_mutex_t lock; 628 int port[_SOC_APACHE_DYN_REGISTER_SET]; 629 int _soc_apache_init_done[SOC_MAX_NUM_DEVICES]; 630 } _soc_apache_port_dyn_sched_t; 631 632 static _soc_apache_port_dyn_sched_t _apache_dyn_sched_unit_data[SOC_MAX_NUM_DEVICES]; 633 634 /* 635 * Function: 636 * _soc_apache_alloc_dyn_set 637 * Purpose: 638 * This function allocates the register available from 639 * the set of SP_WERR_DYN_CHANGEnA/nB/nC (n=0,1,2,3) to the port and 640 * updates the structure _apache_dyn_sched_unit_data to keep track 641 * of the used registers from the set. 642 * Parameters: 643 * unit - (IN) unit number 644 * port - (IN) local port number 645 * r_a - (OUT) SP_WERR_DYN_CHANGEnA register 646 * r_b - (OUT) SP_WERR_DYN_CHANGEnB register 647 * r_ctrl - (OUT) SP_WERR_DYN_CHANGEnC register 648 * Returns: 649 * SOC_E_XXX 650 */ 651 STATIC int _soc_apache_alloc_dyn_set(int unit, int port, 652 soc_reg_t *r_a, soc_reg_t *r_b, soc_reg_t *r_ctrl) 653 { 654 _soc_apache_port_dyn_sched_t *pcb; 655 int i, empty_at = -1, rv = SOC_E_NONE; 656 657 soc_reg_t dyn_change_a_x[] = { 658 LLS_SP_WERR_DYN_CHANGE_0Ar, 659 LLS_SP_WERR_DYN_CHANGE_1Ar, 660 LLS_SP_WERR_DYN_CHANGE_2Ar, 661 LLS_SP_WERR_DYN_CHANGE_3Ar 662 }; 663 soc_reg_t dyn_change_b_x[] = { 664 LLS_SP_WERR_DYN_CHANGE_0Br, 665 LLS_SP_WERR_DYN_CHANGE_1Br, 666 LLS_SP_WERR_DYN_CHANGE_2Br, 667 LLS_SP_WERR_DYN_CHANGE_3Br 668 }; 669 670 soc_reg_t dyn_change_ctrl_x[] = { 671 LLS_SP_WERR_DYN_CHANGE_0Cr, 672 LLS_SP_WERR_DYN_CHANGE_1Cr, 673 LLS_SP_WERR_DYN_CHANGE_2Cr, 674 LLS_SP_WERR_DYN_CHANGE_3Cr 675 }; 676 677 pcb = &_apache_dyn_sched_unit_data[unit]; 678 679 sal_mutex_take(pcb->lock, sal_sem_FOREVER); 680 for (i = 0; i < _SOC_APACHE_DYN_REGISTER_SET; i++) { 681 if (pcb->port[i] == -1) { 682 empty_at = i; 683 break; 684 } else if (pcb->port[i] == port) { 685 rv = SOC_E_BUSY; 686 break; 687 } 688 } 689 690 if (!rv && (empty_at >= 0)) { 691 pcb->port[empty_at] = port; 692 } 693 694 sal_mutex_give(pcb->lock); 695 696 if (rv) { 697 return rv; 698 } 699 700 if (empty_at == -1) { 701 return SOC_E_BUSY; 702 } 703 *r_a = dyn_change_a_x[empty_at]; 704 *r_b = dyn_change_b_x[empty_at]; 705 *r_ctrl = dyn_change_ctrl_x[empty_at]; 706 return SOC_E_NONE; 707 } 708 709 /* 710 * Function: 711 * _soc_apache_free_dyn_set 712 * Purpose: 713 * This function is called after the switchover is done 714 * to update the structure _apache_dyn_sched_unit_data by 715 * removing the port from it. This makes the register 716 * used for the request available for the next request. 717 * Parameters: 718 * unit - (IN) unit number 719 * port - (IN) local port number 720 * Returns: 721 * SOC_E_XXX 722 */ 723 STATIC int _soc_apache_free_dyn_set(int unit, int port) 724 { 725 _soc_apache_port_dyn_sched_t *pcb; 726 int i; 727 728 pcb = &_apache_dyn_sched_unit_data[unit]; 729 730 sal_mutex_take(pcb->lock, sal_sem_FOREVER); 731 for (i = 0; i < _SOC_APACHE_DYN_REGISTER_SET; i++) { 732 if (pcb->port[i] == port) { 733 pcb->port[i] = -1; 734 } 735 } 736 sal_mutex_give(pcb->lock); 737 738 return SOC_E_NONE; 739 } 740 741 /* 742 * Function: 743 * soc_apache_cosq_set_sched_child_config_dynamic 744 * Purpose: 745 * This function enables the spri_vect_mode by setting the 746 * spri_vect_mode_enable field to 1 in the LLS_CONFIG0 reg, which changes 747 * p_num_spri[3:0] to p_vect_spri[7:0]. It allocates the register from set 748 * of SP_WERR_DYN_CHNG_nA/nB/nC registers to the port. It then sets the 749 * SP_WERR_DYN_CHNG_nB/nC reg with the new value for the node id's parent. 750 * It sets the fields in SP_WERR_DYN_CHNG_nA with the info about the node 751 * to be switched like node_id, node_level and parent_id along with in_use 752 * field to 1, which triggers the request in H/W. The H/W clears in_use 753 * field to 0 once the switchover is complete, so we keep polling its 754 * to know about the completion of the request. 755 * Parameters: 756 * unit - (IN) unit number 757 * port - (IN) local port number 758 * level - (IN) level of the node 759 * index - (IN) index of the node 760 * num_spri - (IN) number of SPRI child nodes 761 * first_child - (IN) first child node 762 * first_mc_child - (IN) first multicast child node 763 * ucmap - (IN) unicast map 764 * spmap - (IN) spri map 765 * child_index - (IN) index number of the child 766 * Returns: 767 * SOC_E_XXX 768 */ 769 int 770 soc_apache_cosq_set_sched_child_config_dynamic(int unit, soc_port_t port, 771 int level, int index, 772 int num_spri, int first_child, 773 int first_mc_child, uint32 ucmap, 774 uint32 spmap, int child_index) 775 { 776 uint32 entry[SOC_MAX_MEM_WORDS], rval, d32, timeout_val, old_spmap, f1, f2; 777 soc_mem_t mem; 778 int rv = SOC_E_NONE; 779 soc_reg_t r_a = INVALIDr, r_b = INVALIDr, r_ctrl = INVALIDr; 780 soc_timeout_t timeout; 781 782 if (level == SOC_APACHE_NODE_LVL_ROOT) { 783 return SOC_E_NONE; 784 } 785 786 SOC_IF_ERROR_RETURN(_soc_apache_alloc_dyn_set(unit, port, 787 &r_a, &r_b, &r_ctrl)); 788 789 mem = _SOC_APACHE_NODE_CONFIG_MEM(unit, port, level); 790 if (mem == INVALIDm) { 791 return SOC_E_INTERNAL; 792 } 793 794 level -= 1; 795 /* Getting the old spmap */ 796 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 797 f1 = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf); 798 f2 = soc_mem_field32_get(unit, mem, &entry, P_VECT_SPRI_7_4f); 799 old_spmap = f1 | (f2 << 4); 800 801 LOG_INFO(BSL_LS_SOC_COSQ, 802 (BSL_META_U(unit, 803 "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x NUMSP=%d\n"), 804 port, (level==0) ? "r" : "", level, 805 index, first_child, first_mc_child, ucmap, num_spri)); 806 807 /* Setting the memory fields based on the new spmap */ 808 soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, spmap & 0xf); 809 soc_mem_field32_set(unit, mem, &entry, P_VECT_SPRI_7_4f, (spmap >> 4) & 0xf); 810 811 if (mem == LLS_L1_CONFIGm) { 812 soc_mem_field32_set(unit, mem, &entry, P_START_UC_SPRIf, first_child); 813 soc_mem_field32_set(unit, mem, &entry, P_START_MC_SPRIf, first_mc_child); 814 soc_mem_field32_set(unit, mem, &entry, P_SPRI_SELECTf, 815 (num_spri > 0) ? ucmap : 0); 816 } else { 817 soc_mem_field32_set(unit, mem, &entry, P_START_SPRIf, first_child); 818 } 819 820 SOC_IF_ERROR_RETURN( 821 soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry)); 822 823 rval = 0; 824 soc_bits_get(entry, 0, 31, &d32); 825 soc_reg_field_set(unit, r_ctrl, &rval, LLS_PARENT_CONFIGf, d32); 826 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_ctrl, REG_PORT_ANY, 0, rval)); 827 828 rval = 0; 829 soc_bits_get(entry, 32, 45, &d32); 830 soc_reg_field_set(unit, r_b, &rval, LLS_PARENT_CONFIGf, d32); 831 soc_reg_field_set(unit, r_b, &rval, LLS_PARENT_CONFIG_ORIGINAL_SP_VECTORf, 832 old_spmap); 833 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_b, REG_PORT_ANY, 0, rval)); 834 835 rval = 0; 836 soc_reg_field_set(unit, r_a, &rval, NODE_LEVELf, level + 1); 837 soc_reg_field_set(unit, r_a, &rval, NODE_IDf, child_index); 838 soc_reg_field_set(unit, r_a, &rval, PARENT_IDf, index); 839 soc_reg_field_set(unit, r_a, &rval, IN_USEf, 1); 840 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_a, REG_PORT_ANY, 0, rval)); 841 842 if (!SAL_BOOT_SIMULATION) { 843 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 2000000); 844 soc_timeout_init(&timeout, timeout_val, 0); 845 846 do { 847 SOC_IF_ERROR_RETURN( 848 soc_reg32_get(unit, r_a, REG_PORT_ANY, 0, &rval)); 849 850 if (soc_timeout_check(&timeout)) { 851 rv = SOC_E_TIMEOUT; 852 break; 853 } 854 } while (soc_reg_field_get(unit, r_a, rval, IN_USEf)); 855 } 856 857 SOC_IF_ERROR_RETURN(_soc_apache_free_dyn_set(unit, port)); 858 859 return rv; 860 } 861 862 int 863 soc_apache_cosq_set_sched_config(int unit, soc_port_t port, 864 int level, int index, int child_index, 865 int num_spri, int first_child, 866 int first_mc_child, uint32 ucmap, uint32 spmap, 867 const soc_apache_sched_mode_e mode, int weight) 868 { 869 int child_level; 870 871 if (level >= SOC_APACHE_NODE_LVL_L2) { 872 return SOC_E_PARAM; 873 } 874 875 SOC_IF_ERROR_RETURN( 876 soc_apache_cosq_set_sched_child_config_dynamic(unit, port, 877 level, index, num_spri, first_child, 878 first_mc_child, ucmap, spmap, child_index)); 879 if (child_index >= 0) { 880 soc_apache_get_child_type(unit, port, level, &child_level); 881 SOC_IF_ERROR_RETURN(soc_apache_cosq_set_sched_mode(unit, port, 882 child_level, 883 child_index, mode, weight)); 884 } 885 886 return SOC_E_NONE; 887 } 888 889 int 890 soc_apache_cosq_get_sched_child_config(int unit, soc_port_t port, 891 int level, int index, 892 int *pnum_spri, int *pfirst_sp_child, 893 int *pfirst_sp_mc_child, uint32 *pucmap, uint32 *pspmap) 894 { 895 soc_apache_sched_type_t sched_type; 896 uint32 entry[SOC_MAX_MEM_WORDS]; 897 uint32 num_spri = 0, ucmap = 0, f1, f2; 898 int first_sp_child = -1, first_sp_mc_child = -1,ii; 899 soc_mem_t mem; 900 901 sched_type = _soc_apache_port_sched_type_get(unit, port); 902 903 mem = INVALIDm; 904 905 if (sched_type == SOC_APACHE_SCHED_HSP) { 906 return SOC_E_PARAM; 907 } 908 909 mem = _SOC_APACHE_NODE_CONFIG_MEM(unit, port, level); 910 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 911 num_spri = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf); 912 913 f1 = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf); 914 f2 = soc_mem_field32_get(unit, mem, &entry, P_VECT_SPRI_7_4f); 915 *pspmap = f1 | (f2 << 4); 916 for (ii = 0; ii < 8; ii++) { 917 if ((1 << ii) & *pspmap) { 918 num_spri++; 919 } 920 } 921 if (mem == LLS_L1_CONFIGm) { 922 first_sp_child = soc_mem_field32_get(unit, mem, &entry, P_START_UC_SPRIf); 923 first_sp_mc_child = soc_mem_field32_get(unit, mem, 924 &entry, P_START_MC_SPRIf); 925 ucmap = soc_mem_field32_get(unit, mem, &entry, P_SPRI_SELECTf); 926 } else { 927 first_sp_child = soc_mem_field32_get(unit, mem, &entry, P_START_SPRIf); 928 first_sp_mc_child = 0; 929 } 930 931 if (num_spri == 0) { 932 ucmap = 0; 933 } 934 935 if (pnum_spri) { 936 *pnum_spri = num_spri; 937 } 938 939 if (pucmap) { 940 *pucmap = ucmap; 941 } 942 943 if (pfirst_sp_child) { 944 *pfirst_sp_child = first_sp_child; 945 } 946 947 if (pfirst_sp_mc_child) { 948 *pfirst_sp_mc_child = first_sp_mc_child; 949 } 950 951 LOG_INFO(BSL_LS_SOC_COSQ, 952 (BSL_META_U(unit, 953 "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x\n"), 954 port, (level == 0) ? "r" : "", level - 1, 955 index, first_sp_child, first_sp_mc_child, ucmap)); 956 957 return SOC_E_NONE; 958 } 959 960 int 961 soc_apache_cosq_get_sched_mode(int unit, soc_port_t port, int level, 962 int index, soc_apache_sched_mode_e *pmode, int *weight) 963 { 964 soc_apache_sched_type_t sched_type; 965 uint32 entry[SOC_MAX_MEM_WORDS], rval, wrr_mask; 966 soc_apache_sched_mode_e mode = SOC_APACHE_SCHED_MODE_UNKNOWN; 967 soc_mem_t mem; 968 soc_reg_t reg; 969 int parent_idx = 0; 970 int idx, fval; 971 uint32 mc_group_mode = 0; 972 reg = INVALIDr; 973 mem = INVALIDm; 974 sched_type = _soc_apache_port_sched_type_get(unit, port); 975 976 if (sched_type == SOC_APACHE_SCHED_HSP) { 977 /* get the port relative index / offset */ 978 if (level == SOC_APACHE_NODE_LVL_L0) { 979 index = index % 5; 980 reg = HSP_SCHED_PORT_CONFIGr; 981 parent_idx = 0; 982 } else if (level == SOC_APACHE_NODE_LVL_L1) { 983 index = index % 10; 984 reg = HSP_SCHED_L0_NODE_CONFIGr; 985 /* Find the Parent index for the current child */ 986 for (idx = 1; idx < 5; idx++) { 987 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 988 unit, port, idx, &rval)); 989 fval = soc_reg_field_get(unit, 990 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 991 rval, CHILDREN_CONNECTION_MAPf); 992 if (idx == 4) { 993 if ((index >= 8) && (fval & (1 << (index - 2)))) { 994 parent_idx = idx; 995 break; 996 } 997 } else { 998 if (fval & (1 << index)) { 999 parent_idx = idx; 1000 break; 1001 } 1002 } 1003 } 1004 } else if (level == SOC_APACHE_NODE_LVL_L2) { 1005 SOC_IF_ERROR_RETURN( 1006 READ_HSP_SCHED_PORT_CONFIGr( unit, port, &rval)); 1007 mc_group_mode = soc_reg_field_get( unit, 1008 HSP_SCHED_PORT_CONFIGr, rval, 1009 MC_GROUP_MODEf); 1010 reg = HSP_SCHED_L1_NODE_CONFIGr; 1011 1012 if (mc_group_mode && (index >= 16384)) { 1013 parent_idx = (index - 16384) % 10; 1014 if ( parent_idx < _AP_HSP_PORT_MAX_COS) { 1015 reg = HSP_SCHED_L0_NODE_CONFIGr; 1016 parent_idx = 0; 1017 } 1018 }else { 1019 parent_idx = index % 10; 1020 } 1021 1022 } else { 1023 return SOC_E_PARAM; 1024 } 1025 1026 /* selection between SP and WxRR is based on weight property. */ 1027 SOC_IF_ERROR_RETURN(soc_apache_sched_weight_get(unit, port, 1028 level, index, weight)); 1029 if (*weight == 0) { 1030 mode = SOC_APACHE_SCHED_MODE_STRICT; 1031 } else { 1032 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 1033 wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf); 1034 if (wrr_mask & (1 << parent_idx)) { 1035 mode = SOC_APACHE_SCHED_MODE_WRR; 1036 } else { 1037 mode = SOC_APACHE_SCHED_MODE_WDRR; 1038 } 1039 } 1040 } else { 1041 SOC_IF_ERROR_RETURN(soc_apache_sched_weight_get(unit, port, 1042 level, index, weight)); 1043 if (*weight == 0) { 1044 mode = SOC_APACHE_SCHED_MODE_STRICT; 1045 } else { 1046 mem = _SOC_APACHE_NODE_CONFIG_MEM(unit, port, SOC_APACHE_NODE_LVL_S1); 1047 index = _soc_apache_s1_scheduler_index(unit, port, level, index); 1048 if (index == -1) { 1049 return SOC_E_INTERNAL; 1050 } 1051 SOC_IF_ERROR_RETURN( 1052 soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 1053 if (soc_mem_field32_get(unit, mem, 1054 entry, PACKET_MODE_WRR_ACCOUNTING_ENABLEf)) { 1055 mode = SOC_APACHE_SCHED_MODE_WRR; 1056 } else { 1057 mode = SOC_APACHE_SCHED_MODE_WDRR; 1058 } 1059 } 1060 } 1061 1062 if (pmode) { 1063 *pmode = mode; 1064 } 1065 1066 LOG_INFO(BSL_LS_SOC_COSQ, 1067 (BSL_META_U(unit, 1068 "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"), 1069 port, (level == 0) ? "r" : "", level - 1, index, mode, *weight)); 1070 1071 return SOC_E_NONE; 1072 } 1073 1074 int 1075 soc_apache_cosq_get_sched_config(int unit, soc_port_t port, 1076 int level, int index, int child_index, 1077 int *pnum_spri, int *pfirst_child, 1078 int *pfirst_mc_child, uint32 *pucmap, uint32 *pspmap, 1079 soc_apache_sched_mode_e *pmode, int *weight) 1080 { 1081 int child_level; 1082 1083 if (level >= SOC_APACHE_NODE_LVL_L2) { 1084 return SOC_E_PARAM; 1085 } 1086 1087 if (level != SOC_APACHE_NODE_LVL_ROOT) { 1088 SOC_IF_ERROR_RETURN(soc_apache_cosq_get_sched_child_config(unit, port, level, 1089 index, pnum_spri, pfirst_child, pfirst_mc_child, pucmap, pspmap)); 1090 } 1091 1092 if (child_index >= 0) { 1093 soc_apache_get_child_type(unit, port, level, &child_level); 1094 SOC_IF_ERROR_RETURN( 1095 soc_apache_cosq_get_sched_mode(unit, port, child_level, child_index, 1096 pmode, weight)); 1097 } 1098 1099 return SOC_E_NONE; 1100 } 1101 1102 int soc_apache_get_child_type(int unit, soc_port_t port, int level, 1103 int *child_type) 1104 { 1105 *child_type = -1; 1106 if (level == SOC_APACHE_NODE_LVL_ROOT) { 1107 *child_type = SOC_APACHE_NODE_LVL_S1; 1108 } else if (level == SOC_APACHE_NODE_LVL_S1) { 1109 *child_type = SOC_APACHE_NODE_LVL_L0; 1110 } else if (level == SOC_APACHE_NODE_LVL_L0) { 1111 *child_type = SOC_APACHE_NODE_LVL_L1; 1112 } else if (level == SOC_APACHE_NODE_LVL_L1) { 1113 *child_type = SOC_APACHE_NODE_LVL_L2; 1114 } 1115 return SOC_E_NONE; 1116 } 1117 int 1118 soc_ap_is_skip_default_lls_creation(int unit) { 1119 int skip = 0; 1120 soc_pbmp_t skip_default_lls_pbmp; 1121 1122 skip_default_lls_pbmp = soc_property_get_pbmp(unit, spn_PBMP_SKIP_DEFAULT_LLS, 0); 1123 if (SOC_PBMP_NOT_NULL(skip_default_lls_pbmp)) { 1124 skip = 1; 1125 } 1126 1127 return skip; 1128 } 1129 1130 STATIC int 1131 _soc_apache_alloc_sched(int unit, soc_port_t in_port, soc_apache_node_lvl_e lvl, 1132 int offset, int *hw_index) 1133 { 1134 int in_pipe, tlm = -1; 1135 int mmu_port, max = -1; 1136 soc_apache_sched_type_t stype; 1137 uint32 sched_bmap[32]; 1138 1139 sal_memset(sched_bmap, 0, sizeof(uint32)*32); 1140 1141 SOC_IF_ERROR_RETURN( 1142 soc_apache_port_common_attributes_get(unit, in_port, &in_pipe, &mmu_port, NULL)); 1143 1144 stype = _soc_apache_port_sched_type_get(unit, in_port); 1145 1146 if (lvl == SOC_APACHE_NODE_LVL_ROOT) { 1147 tlm = 1; 1148 max = 106; 1149 } else if (lvl == SOC_APACHE_NODE_LVL_L0) { 1150 tlm = 5; /* max 4 L0 under HSP */ 1151 max = 272; 1152 } else if (lvl == SOC_APACHE_NODE_LVL_L1) { 1153 tlm = 10; 1154 max = 1024; 1155 } 1156 1157 if ((max < 0) || (tlm < 0)) { 1158 return SOC_E_PARAM; 1159 } 1160 1161 if (stype == SOC_APACHE_SCHED_HSP) { 1162 /* For HSP ports, the indexes of the scheduler and queues are fixed.*/ 1163 if (offset >= tlm) { 1164 return SOC_E_PARAM; 1165 } 1166 mmu_port += (mmu_port >= 74) ? -74 : 0; 1167 *hw_index = (mmu_port * tlm) + offset; 1168 return SOC_E_NONE; 1169 } 1170 1171 return SOC_E_RESOURCE; 1172 } 1173 1174 int soc_apache_l2_hw_index(int unit, int qnum, int uc) 1175 { 1176 if (uc) { 1177 qnum -= (qnum >= 16384) ? 16384 : 0; 1178 } else { 1179 qnum -= (qnum >= 778) ? 778 : 0; 1180 qnum += 16384; 1181 } 1182 return qnum; 1183 } 1184 1185 /* 1186 * Function: 1187 * soc_apache_hw_index_logical_num 1188 * Purpose: 1189 * Get the logical queue number according to hw index 1190 * Parameters: 1191 * unit - (IN) unit number 1192 * port - (IN) local port number 1193 * index -(IN) The index of Queue management related memory Tables 1194 * uc - (IN) unicast indicator 1195 * Returns: 1196 * logical queue number: queue number in logical view 1197 * In logical view, 1198 * the range of unicast queue number is: [0,16384) 1199 * the range of multicast queue number is: [0,778) 1200 */ 1201 int 1202 soc_apache_hw_index_logical_num(int unit,int port,int index,int uc) 1203 { 1204 int qnum; 1205 if (uc) { 1206 qnum = index; 1207 } else { 1208 1209 qnum = index - 16384; 1210 } 1211 1212 return qnum; 1213 } 1214 1215 1216 #define AP_DFL_HSP_SCHED_MODE SOC_APACHE_SCHED_MODE_WDRR 1217 1218 int 1219 soc_apache_setup_hsp_port(int unit, int port) 1220 { 1221 uint32 rval, fval = 0, pbmf; 1222 int mmu_port, pipe, l0_index, l1_index, l0_1, l0_4, hw_index, index; 1223 1224 1225 SOC_IF_ERROR_RETURN( 1226 soc_apache_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL)); 1227 1228 for (index = 0; index < 5; index++) { 1229 SHR_BITSET(SOC_CONTROL(unit)->port_lls_l0_bmap[port], 1230 (mmu_port & 0x3f) * 5 + index); 1231 } 1232 for (index = 0; index < 10; index++) { 1233 SHR_BITSET(SOC_CONTROL(unit)->port_lls_l1_bmap[port], 1234 (mmu_port & 0x3f) * 10 + index); 1235 } 1236 for (index = 0; index < 10; index++) { 1237 SHR_BITSET(SOC_CONTROL(unit)->port_lls_l2_bmap[port], 1238 (mmu_port & 0x3f) * 10 + index); 1239 } 1240 1241 rval = 0; 1242 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_PORT_CONFIGr(unit, port, rval)); 1243 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_CONFIGr(unit, port, rval)); 1244 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L1_NODE_CONFIGr(unit, port, rval)); 1245 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L2_UC_QUEUE_CONFIGr(unit, port, rval)); 1246 1247 l0_1 = 0; 1248 l0_4 = 0; 1249 for (l0_index = 0; l0_index < 5; l0_index++) { 1250 SOC_IF_ERROR_RETURN(soc_apache_sched_hw_index_get(unit, port, 1251 SOC_APACHE_NODE_LVL_L0, l0_index, &hw_index)); 1252 SOC_IF_ERROR_RETURN(soc_apache_cosq_set_sched_parent(unit, port, 1253 SOC_APACHE_NODE_LVL_L0, hw_index, mmu_port, 1)); 1254 1255 if (l0_index == 1) { 1256 l0_1 = hw_index; 1257 } else if (l0_index == 4) { 1258 l0_4 = hw_index; 1259 } 1260 } 1261 1262 for (l1_index = 0; l1_index < 10; l1_index++) { 1263 SOC_IF_ERROR_RETURN(soc_apache_sched_hw_index_get(unit, port, 1264 SOC_APACHE_NODE_LVL_L1, l1_index, &hw_index)); 1265 1266 SOC_IF_ERROR_RETURN(soc_apache_cosq_set_sched_parent(unit, port, 1267 SOC_APACHE_NODE_LVL_L1, hw_index, (l1_index < 8) ? l0_1 : l0_4, 1)); 1268 1269 SOC_IF_ERROR_RETURN(soc_apache_cosq_set_sched_mode(unit, port, 1270 SOC_APACHE_NODE_LVL_L1, l1_index, SOC_APACHE_SCHED_MODE_WDRR, 1)); 1271 } 1272 1273 pbmf = IS_HSP_PORT_IN_XPIPEf; 1274 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval)); 1275 fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, pbmf); 1276 fval |= (1 << mmu_port); 1277 soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, pbmf, fval); 1278 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval)); 1279 return SOC_E_NONE; 1280 } 1281 1282 int 1283 soc_apache_delete_hsp_port(int unit, int port) 1284 { 1285 uint32 rval, fval = 0, pbmf; 1286 int mmu_port, pipe, l0_index, index; 1287 1288 SOC_IF_ERROR_RETURN( 1289 soc_apache_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL)); 1290 1291 for (index = 0; index < 5; index++) { 1292 SHR_BITCLR(SOC_CONTROL(unit)->port_lls_l0_bmap[port], 1293 (mmu_port & 0x3f) * 5 + index); 1294 } 1295 for (index = 0; index < 10; index++) { 1296 SHR_BITCLR(SOC_CONTROL(unit)->port_lls_l1_bmap[port], 1297 (mmu_port & 0x3f) * 10 + index); 1298 } 1299 for (index = 0; index < 10; index++) { 1300 SHR_BITCLR(SOC_CONTROL(unit)->port_lls_l2_bmap[port], 1301 (mmu_port & 0x3f) * 10 + index); 1302 } 1303 1304 rval = 0; 1305 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_PORT_CONFIGr(unit, port, rval)); 1306 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_CONFIGr(unit, port, rval)); 1307 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L1_NODE_CONFIGr(unit, port, rval)); 1308 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L2_UC_QUEUE_CONFIGr(unit, port, rval)); 1309 1310 for (l0_index = 0; l0_index < 5; l0_index++) { 1311 SOC_IF_ERROR_RETURN( 1312 WRITE_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(unit, port, 1313 l0_index, rval)); 1314 } 1315 1316 pbmf = IS_HSP_PORT_IN_XPIPEf; 1317 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval)); 1318 fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, pbmf); 1319 fval &= (~(1 << mmu_port)); 1320 soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, pbmf, fval); 1321 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval)); 1322 return SOC_E_NONE; 1323 } 1324 1325 /* 1326 * Function: 1327 * _soc_apache_lls_init 1328 * Purpose: 1329 * This function initialises the structure _apache_dyn_sched_unit_data, which is 1330 * used later to allocate the register available from the set of 1331 * SP_WERR_DYN_CHANGEnA/nB/nC (n=0,1,2,3) to the port and to keep track 1332 * of the used registers from the set for the port 1333 * Parameters: 1334 * unit - (IN) unit number 1335 * Returns: 1336 * SOC_E_XXX 1337 */ 1338 STATIC int _soc_apache_lls_init(int unit) 1339 { 1340 _soc_apache_port_dyn_sched_t *pcb = NULL; 1341 int i; 1342 1343 if (soc_feature(unit, soc_feature_vector_based_spri)) { 1344 pcb = &_apache_dyn_sched_unit_data[unit]; 1345 1346 if (pcb->_soc_apache_init_done[unit] == 1) { 1347 return SOC_E_NONE; 1348 } 1349 1350 pcb->lock = sal_mutex_create("apache_dyn_lock"); 1351 for (i = 0; i < _SOC_APACHE_DYN_REGISTER_SET; i++) { 1352 pcb->port[i] = -1; 1353 } 1354 pcb->_soc_apache_init_done[unit] = 1; 1355 } 1356 1357 return SOC_E_NONE; 1358 } 1359 1360 int soc_apache_lls_init(int unit) 1361 { 1362 1363 SOC_IF_ERROR_RETURN(_soc_apache_lls_init(unit)); 1364 1365 1366 SOC_IF_ERROR_RETURN(soc_apache_init_invalid_parents(unit)); 1367 1368 SOC_IF_ERROR_RETURN(soc_apache_set_invalid_parent(unit)); 1369 1370 1371 return SOC_E_NONE; 1372 } 1373 1374 int 1375 soc_apache_sched_hw_index_get(int unit, int port, int lvl, int offset, 1376 int *hw_index) 1377 { 1378 int rv; 1379 1380 rv = _soc_apache_alloc_sched(unit, port, lvl, offset, hw_index); 1381 1382 LOG_INFO(BSL_LS_SOC_COSQ, 1383 (BSL_META_U(unit, 1384 "Alloced : port=%d lvl=%d ofst=%d Index=%d\n"), 1385 port, lvl, offset, *hw_index)); 1386 return rv; 1387 } 1388 1389 int 1390 soc_apache_qcn_counter_hw_index_get(int unit, soc_port_t port, 1391 int index, int *qindex) 1392 { 1393 soc_mem_t mem; 1394 mmu_qcn_enable_entry_t entry; 1395 int resolved_index = -1; 1396 1397 if (qindex == NULL) { 1398 return SOC_E_PARAM; 1399 } 1400 1401 mem = MMU_QCN_ENABLE_0m; 1402 1403 resolved_index = soc_apache_l2_hw_index(unit, index, 1); 1404 SOC_IF_ERROR_RETURN 1405 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, resolved_index, &entry)); 1406 if (soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 1407 *qindex = soc_mem_field32_get(unit, mem, &entry, CPQ_IDf); 1408 } else { 1409 *qindex = -1; 1410 } 1411 1412 return SOC_E_NONE; 1413 } 1414 1415 1416 int 1417 soc_apache_get_def_qbase(int unit, soc_port_t inport, int qtype, 1418 int *pbase, int *pnumq) 1419 { 1420 soc_info_t *si; 1421 int base, numq; 1422 1423 si = &SOC_INFO(unit); 1424 1425 if (qtype == _SOC_TD2_INDEX_STYLE_UCAST_QUEUE) { 1426 base = si->port_uc_cosq_base[inport]; 1427 numq = si->port_num_uc_cosq[inport]; 1428 } else if (qtype == _SOC_TD2_INDEX_STYLE_MCAST_QUEUE) { 1429 base = si->port_cosq_base[inport]; 1430 numq = si->port_num_cosq[inport]; 1431 } else { 1432 return SOC_E_INTERNAL; 1433 } 1434 1435 if (pbase) { 1436 *pbase = base; 1437 } 1438 if (pnumq) { 1439 *pnumq = numq; 1440 } 1441 return SOC_E_NONE; 1442 } 1443 1444 STATIC int 1445 _soc_apache_dump_hsp_sched_at(int unit, int port, int level, int offset, int index) 1446 { 1447 uint32 rval = 0; 1448 uint32 conn_map; 1449 uint32 l0_index, l1_index; 1450 uint32 mc_group_mode = 0; 1451 char *lvl_name[] = { "Root","S1","L0", "L1", "UC", "MC" }; 1452 char *sched_modes[] = {"X", "SP", "WRR", "WERR"}; 1453 uint32 num_spri =0; 1454 uint32 first_child =0; 1455 uint32 first_mc_child =0; 1456 uint32 ucmap =0; 1457 uint32 sched_mode =0; 1458 int uc_cosq, mc_cosq; 1459 int uc_cosq_base, mc_cosq_base; 1460 int uc_hw_index, mc_hw_index; 1461 int hw_index; 1462 int wt =0; 1463 int mmu_port; 1464 1465 1466 SOC_IF_ERROR_RETURN(soc_apache_sched_hw_index_get(unit, 1467 port, SOC_APACHE_NODE_LVL_L1, 0, &uc_cosq_base)); 1468 mc_cosq_base = uc_cosq_base; 1469 1470 uc_cosq = soc_apache_logical_qnum_hw_qnum(unit, port, uc_cosq_base, 1); 1471 mc_cosq = soc_apache_logical_qnum_hw_qnum(unit, port, mc_cosq_base, 0); 1472 1473 if (level != SOC_APACHE_NODE_LVL_ROOT) { 1474 return SOC_E_PARAM; 1475 } 1476 1477 soc_apache_port_common_attributes_get(unit, port, NULL, &mmu_port, NULL); 1478 /* Root Node */ 1479 LOG_CLI((BSL_META_U(unit, 1480 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 1481 lvl_name[level], offset, index, num_spri, first_child, 1482 sched_modes[sched_mode], wt)); 1483 1484 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval)); 1485 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 1486 rval, MC_GROUP_MODEf); 1487 /* L0 Node */ 1488 for (l0_index = 0; l0_index < 5; l0_index++) { 1489 /* print the L0 Nodes*/ 1490 level = SOC_APACHE_NODE_LVL_L0; 1491 SOC_IF_ERROR_RETURN(soc_apache_sched_hw_index_get(unit, 1492 port, level, l0_index, &hw_index)); 1493 soc_apache_cosq_get_sched_mode(unit, port, SOC_APACHE_NODE_LVL_L0, 1494 hw_index, &sched_mode, &wt); 1495 LOG_CLI((BSL_META_U(unit, 1496 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 1497 lvl_name[level], l0_index, hw_index, num_spri, first_child, 1498 sched_modes[sched_mode], wt)); 1499 1500 /* read Connection map for the L0.1, L0.2, L0.3, L0.4, L0.5 1501 * by default connection map should be set to all zeros for L0.0 1502 */ 1503 1504 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 1505 unit, port, l0_index, &rval)); 1506 conn_map = soc_reg_field_get(unit, 1507 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 1508 rval, CHILDREN_CONNECTION_MAPf); 1509 if ((l0_index >= 1) && (l0_index <= 4)) { 1510 for (l1_index = 0; l1_index < 8; l1_index++) { 1511 if (conn_map & (1U<<l1_index)) { 1512 if (l0_index == 4) { 1513 offset = l1_index + 2; 1514 } else { 1515 offset = l1_index; 1516 } 1517 /* print L1 node */ 1518 level = SOC_APACHE_NODE_LVL_L1; 1519 SOC_IF_ERROR_RETURN(soc_apache_sched_hw_index_get(unit, 1520 port, level, offset, &hw_index)); 1521 soc_apache_cosq_get_sched_mode(unit, port, SOC_APACHE_NODE_LVL_L1, 1522 hw_index, &sched_mode, &wt); 1523 LOG_CLI((BSL_META_U(unit, 1524 " %s.%d : INDEX=%d NUM_SP=%d FC=%d " 1525 "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"), 1526 lvl_name[level], offset, hw_index, num_spri, 1527 first_child, first_mc_child, ucmap, 1528 sched_modes[sched_mode], wt)); 1529 1530 /* print L2 UC node attached to L1 */ 1531 uc_hw_index = soc_apache_l2_hw_index(unit, uc_cosq_base, 1); 1532 soc_apache_cosq_get_sched_mode(unit, port, 1533 SOC_APACHE_NODE_LVL_L2, 1534 uc_hw_index, &sched_mode, &wt); 1535 LOG_CLI((BSL_META_U(unit, 1536 " L2.uc : INDEX=%d Mode=%s WEIGHT=%d\n"), 1537 uc_cosq, sched_modes[sched_mode], wt)); 1538 uc_cosq_base++; 1539 uc_cosq++; 1540 1541 if (((mc_group_mode == 1) && (l0_index == 4)) || 1542 (mc_group_mode == 0)) { 1543 /* print L2 MC node attached to L1 */ 1544 /* MC_GROUP_MODE = 1 then 8 MC Cos queues are 1545 * grouped together and shared the parent (L0.0) bandwidth. 1546 * MC_QM and MC_SC queues are still paired with 1547 * UC_QM and UC_SC respectivly 1548 */ 1549 mc_hw_index = soc_apache_l2_hw_index(unit, mc_cosq_base, 0); 1550 soc_apache_cosq_get_sched_mode(unit, port, 1551 SOC_APACHE_NODE_LVL_L2, 1552 mc_hw_index, &sched_mode, &wt); 1553 LOG_CLI((BSL_META_U(unit, 1554 " L2.mc : INDEX=%d Mode=%s WEIGHT=%d\n"), 1555 mc_cosq, sched_modes[sched_mode], wt)); 1556 mc_cosq_base++; 1557 mc_cosq++; 1558 } 1559 } 1560 } 1561 } else if (l0_index == 0) { 1562 if (mc_group_mode) { 1563 for (l1_index = 0; l1_index < 8; l1_index++) { 1564 /* 8 MC Cos queues are grouped together and shared 1565 * the parent (L0.0) bandwidth. 1566 */ 1567 mc_hw_index = soc_apache_l2_hw_index(unit, mc_cosq_base, 0); 1568 soc_apache_cosq_get_sched_mode(unit, port, 1569 SOC_APACHE_NODE_LVL_L2, 1570 mc_hw_index, &sched_mode, &wt); 1571 LOG_CLI((BSL_META_U(unit, 1572 " L2.mc : INDEX=%d Mode=%s WEIGHT=%d\n"), 1573 mc_cosq, sched_modes[sched_mode], wt)); 1574 mc_cosq_base++; 1575 mc_cosq++; 1576 } 1577 1578 } 1579 } 1580 } 1581 1582 return SOC_E_NONE; 1583 } 1584 1585 STATIC int 1586 _soc_apache_child_num_get(int unit, int port, int level, int hw_index, int *count) 1587 { 1588 soc_mem_t mem; 1589 int cindex, index_max, ii, child_level, num_child = 0; 1590 uint32 entry[SOC_MAX_MEM_WORDS]; 1591 1592 soc_apache_get_child_type(unit, port, level, &child_level); 1593 mem = _SOC_APACHE_NODE_PARENT_MEM(unit, port, child_level); 1594 1595 if (mem == INVALIDm) { 1596 return SOC_E_INTERNAL; 1597 } 1598 index_max = soc_mem_index_max(unit, mem); 1599 1600 for (ii = 0; ii <= index_max; ii++) { 1601 SOC_IF_ERROR_RETURN( 1602 soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &entry)); 1603 1604 cindex = soc_mem_field32_get(unit, mem, entry, C_PARENTf); 1605 1606 if (cindex == hw_index) { 1607 num_child += 1; 1608 } 1609 } 1610 1611 if (count != NULL) { 1612 *count = num_child; 1613 } 1614 1615 return SOC_E_NONE; 1616 } 1617 1618 1619 STATIC int 1620 _soc_apache_dump_sched_at(int unit, int port, int level, int offset, int hw_index) 1621 { 1622 int num_spri = 0, first_child = 0, first_mc_child, rv, cindex; 1623 uint32 ucmap, spmap; 1624 soc_apache_sched_mode_e sched_mode; 1625 soc_mem_t mem; 1626 int index_max, ii, ci, child_level, wt = 0, num_child; 1627 uint32 entry[SOC_MAX_MEM_WORDS]; 1628 char *lvl_name[] = { "Root", "S1", "L0", "L1", "L2" }; 1629 char *sched_modes[] = {"X", "SP", "WRR", "WDRR"}; 1630 int num_s1_children = 0; 1631 1632 if (level < SOC_APACHE_NODE_LVL_L2) { 1633 soc_apache_get_child_type(unit, port, level, &child_level); 1634 if (hw_index == INVALID_PARENT(unit, child_level)) { 1635 /* 1636 * INVALID_PARENT(L0) may be zero. 1637 * When this condition occurs, 1638 * we need to do further check instead of returning. 1639 */ 1640 if (!((child_level == SOC_APACHE_NODE_LVL_S1) && 1641 (hw_index == 0))) { 1642 return SOC_E_NONE; 1643 } 1644 } 1645 } 1646 1647 if (level != SOC_APACHE_NODE_LVL_ROOT) { 1648 /* get sched config */ 1649 SOC_IF_ERROR_RETURN( 1650 soc_apache_cosq_get_sched_child_config(unit, port, level, hw_index, 1651 &num_spri, &first_child, &first_mc_child, &ucmap, &spmap)); 1652 } 1653 1654 sched_mode = 0; 1655 if (level != SOC_APACHE_NODE_LVL_ROOT) { 1656 SOC_IF_ERROR_RETURN( 1657 soc_apache_cosq_get_sched_mode(unit, port, level, hw_index, &sched_mode, &wt)); 1658 } 1659 1660 if (level == SOC_APACHE_NODE_LVL_L1) { 1661 LOG_CLI((BSL_META_U(unit, 1662 " %s.%d : INDEX=%d NUM_SP=%d FC=%d " 1663 "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"), 1664 lvl_name[level], offset, hw_index, num_spri, 1665 first_child, first_mc_child, ucmap, 1666 sched_modes[sched_mode], wt)); 1667 } else { 1668 if (soc_feature(unit, soc_feature_mmu_hqos_four_level)) 1669 { 1670 LOG_CLI((BSL_META_U(unit, 1671 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 1672 lvl_name[level], offset, hw_index, num_spri, first_child, 1673 sched_modes[sched_mode], 1674 wt)); 1675 } else 1676 { 1677 if (level != SOC_APACHE_NODE_LVL_ROOT) 1678 { 1679 if (level == SOC_APACHE_NODE_LVL_S1) { 1680 LOG_CLI((BSL_META_U(unit, 1681 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 1682 lvl_name[level-1 ], offset, hw_index, num_spri, first_child, 1683 sched_modes[sched_mode], 1684 wt)); 1685 } 1686 else 1687 { 1688 LOG_CLI((BSL_META_U(unit, 1689 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 1690 lvl_name[level], offset, hw_index, num_spri, first_child, 1691 sched_modes[sched_mode], 1692 wt)); 1693 1694 } 1695 } 1696 } 1697 } 1698 1699 soc_apache_get_child_type(unit, port, level, &child_level); 1700 mem = _SOC_APACHE_NODE_PARENT_MEM(unit, port, child_level); 1701 1702 if(mem == INVALIDm) { 1703 return SOC_E_INTERNAL; 1704 } 1705 index_max = soc_mem_index_max(unit, mem); 1706 1707 num_child = 0; 1708 for (ii = 0, ci = 0; ii <= index_max; ii++) { 1709 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &entry); 1710 if (rv) { 1711 LOG_CLI((BSL_META_U(unit, 1712 "Failed to read memory at index: %d\n"), ii)); 1713 break; 1714 } 1715 1716 cindex = soc_mem_field32_get(unit, mem, entry, 1717 child_level == SOC_APACHE_NODE_LVL_S1 ? P_PORTf : 1718 C_PARENTf); 1719 1720 /* 1721 * INVALID_PARENT(L0) may be zero. 1722 * When this condition occurs, 1723 * we should get the node`s child count to decide 1724 * if it is a valid node or not. 1725 */ 1726 if ((cindex == 0) && (child_level == SOC_APACHE_NODE_LVL_S1)) { 1727 _soc_apache_child_num_get(unit, port, child_level, 1728 ii, &num_s1_children); 1729 if (num_s1_children == 0) { 1730 continue; 1731 } 1732 } 1733 1734 if (cindex == hw_index) { 1735 if (child_level == SOC_APACHE_NODE_LVL_L2) { 1736 SOC_IF_ERROR_RETURN(soc_apache_cosq_get_sched_mode(unit, port, 1737 SOC_APACHE_NODE_LVL_L2, ii, &sched_mode, &wt)); 1738 LOG_CLI((BSL_META_U(unit, 1739 " L2.%s INDEX=%d Mode=%s WEIGHT=%d\n"), 1740 ((ii < 16384) ? "uc" : "mc"), 1741 ii, sched_modes[sched_mode], wt)); 1742 } else { 1743 _soc_apache_dump_sched_at(unit, port, child_level, ci, ii); 1744 ci += 1; 1745 } 1746 num_child += 1; 1747 } 1748 } 1749 if (num_child == 0) { 1750 LOG_CLI((BSL_META_U(unit, 1751 "*** No children \n"))); 1752 } 1753 return SOC_E_NONE; 1754 } 1755 1756 int soc_apache_dump_port_lls(int unit, int port) 1757 { 1758 int mmu_port, index; 1759 1760 if (_soc_apache_port_sched_type_get(unit, port) == SOC_APACHE_SCHED_HSP) { 1761 return SOC_E_NONE; 1762 } 1763 1764 soc_apache_port_common_attributes_get(unit, port, NULL, &mmu_port, NULL); 1765 1766 LOG_CLI((BSL_META_U(unit, 1767 "-------%s (LLS)------\n"), SOC_PORT_NAME(unit, (port)))); 1768 index = _soc_apache_root_scheduler_index(unit, port); 1769 _soc_apache_dump_sched_at(unit, port, SOC_APACHE_NODE_LVL_ROOT, 0, index); 1770 return SOC_E_NONE; 1771 } 1772 int soc_apache_dump_port_hsp(int unit, int port) 1773 { 1774 int mmu_port, index; 1775 1776 if (_soc_apache_port_sched_type_get(unit, port) == SOC_APACHE_SCHED_LLS) { 1777 return SOC_E_NONE; 1778 } 1779 1780 soc_apache_port_common_attributes_get(unit, port, NULL, &mmu_port, NULL); 1781 1782 LOG_CLI((BSL_META_U(unit, 1783 "-------%s (HSP)------\n"), SOC_PORT_NAME(unit, (port)))); 1784 index = _soc_apache_root_scheduler_index(unit, port); 1785 _soc_apache_dump_hsp_sched_at(unit, port, SOC_APACHE_NODE_LVL_ROOT, 0, index); 1786 return SOC_E_NONE; 1787 } 1788 1789 int soc_apache_logical_qnum_hw_qnum(int unit, int port, int lqnum, int uc) 1790 { 1791 if (uc) { 1792 return lqnum; 1793 } else { 1794 return lqnum + 16384; 1795 } 1796 return -1; 1797 } 1798 1799 int soc_apache_mmu_get_shared_size(int unit, int *shared_size) 1800 { 1801 uint32 entry0[SOC_MAX_MEM_WORDS]; 1802 1803 sal_memset(entry0, 0, sizeof(mmu_thdu_xpipe_config_queue_entry_t)); 1804 SOC_IF_ERROR_RETURN 1805 (soc_mem_read(unit, MMU_THDU_XPIPE_CONFIG_QUEUEm, MEM_BLOCK_ALL, 0, entry0)); 1806 *shared_size = soc_mem_field32_get(unit, MMU_THDU_XPIPE_CONFIG_QUEUEm, entry0, Q_SHARED_LIMIT_CELLf); 1807 return 1; 1808 } 1809 1810 int soc_apache_mmu_config_res_limits_update(int unit, uint32 spid, 1811 uint32 shared_size, int flags) 1812 { 1813 return soc_apache_mmu_config_shared_buf_recalc(unit, spid, shared_size, flags); 1814 } 1815 1816 void 1817 soc_apache_fc_map_shadow_free(int unit) 1818 { 1819 int mem_idx; 1820 soc_apache_fc_map_shadow_memory_t * shadow_info; 1821 soc_apache_fc_map_shadow_t* shadow_ctrl = &soc_apache_fc_map_shadow[unit]; 1822 1823 if (shadow_ctrl->shadow_array != NULL) { 1824 for (mem_idx = 0; mem_idx < shadow_ctrl->mem_count; mem_idx++){ 1825 shadow_info = &(shadow_ctrl->shadow_array[mem_idx]); 1826 if (shadow_info->mem_shadow != NULL){ 1827 sal_free(shadow_info->mem_shadow); 1828 } 1829 } 1830 sal_free(shadow_ctrl->shadow_array); 1831 shadow_ctrl->shadow_array = NULL; 1832 shadow_ctrl->mem_count = 0; 1833 } 1834 } 1835 1836 int 1837 soc_apache_fc_map_shadow_create(int unit) 1838 { 1839 int mem_idx, alloc_size, num_entries, entry_size; 1840 soc_apache_fc_map_shadow_memory_t* shadow_info = NULL; 1841 uint32* shadow = NULL; 1842 1843 if (soc_apache_fc_map_shadow[unit].shadow_array == NULL) { 1844 alloc_size = sizeof(soc_apache_fc_map_shadow_memory_t) * 1845 COUNTOF(fc_map_mems); 1846 shadow_info = sal_alloc(alloc_size, "fc map shadow control"); 1847 if (shadow_info == NULL) { 1848 return SOC_E_MEMORY; 1849 } 1850 1851 sal_memset(shadow_info, 0, alloc_size); 1852 soc_apache_fc_map_shadow[unit].shadow_array = shadow_info; 1853 1854 for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) { 1855 num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]); 1856 entry_size = soc_mem_entry_words(unit, fc_map_mems[mem_idx]); 1857 alloc_size = entry_size * num_entries * sizeof(uint32); 1858 shadow = sal_alloc(alloc_size, "fc map shadow tbl"); 1859 if (shadow == NULL) { 1860 soc_apache_fc_map_shadow_free(unit); 1861 return SOC_E_MEMORY; 1862 } 1863 sal_memset(shadow, 0, alloc_size); 1864 soc_apache_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow = shadow; 1865 soc_apache_fc_map_shadow[unit].shadow_array[mem_idx].mem = fc_map_mems[mem_idx]; 1866 soc_apache_fc_map_shadow[unit].mem_count++; 1867 } 1868 } 1869 return SOC_E_NONE; 1870 } 1871 1872 int 1873 soc_apache_fc_map_shadow_entry_get (int unit, soc_mem_t mem, int index, 1874 void* entry_data) 1875 { 1876 int mem_idx, entry_words; 1877 uint32 * shadow = NULL; 1878 1879 switch(mem){ 1880 case MMU_INTFI_XPIPE_FC_MAP_TBL0m: 1881 mem_idx = 0; 1882 break; 1883 case MMU_INTFI_XPIPE_FC_MAP_TBL1m: 1884 mem_idx = 1; 1885 break; 1886 default: 1887 return SOC_E_NOT_FOUND; 1888 1889 } 1890 1891 shadow = soc_apache_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow; 1892 entry_words = soc_mem_entry_words(unit, mem); 1893 sal_memcpy(entry_data, shadow + index * entry_words, 1894 entry_words * sizeof(uint32)); 1895 return SOC_E_NONE; 1896 } 1897 1898 int 1899 soc_apache_fc_map_shadow_entry_set (int unit, soc_mem_t mem, int index, 1900 void* entry_data) 1901 { 1902 int mem_idx, entry_words; 1903 uint32 * shadow = NULL; 1904 1905 switch(mem){ 1906 case MMU_INTFI_XPIPE_FC_MAP_TBL0m: 1907 mem_idx = 0; 1908 break; 1909 case MMU_INTFI_XPIPE_FC_MAP_TBL1m: 1910 mem_idx = 1; 1911 break; 1912 default: 1913 return SOC_E_NOT_FOUND; 1914 1915 } 1916 shadow = soc_apache_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow; 1917 entry_words = soc_mem_entry_words(unit, mem); 1918 sal_memcpy(shadow + index * entry_words, entry_data, 1919 entry_words * sizeof(uint32)); 1920 return SOC_E_NONE; 1921 } 1922 1923 int 1924 soc_apache_fc_map_shadow_clear (int unit, soc_mem_t mem) 1925 { 1926 uint32 * shadow = NULL; 1927 int entry_words, tbl_size, mem_idx, num_entries; 1928 switch(mem){ 1929 case MMU_INTFI_XPIPE_FC_MAP_TBL0m: 1930 mem_idx = 0; 1931 break; 1932 case MMU_INTFI_XPIPE_FC_MAP_TBL1m: 1933 mem_idx = 1; 1934 break; 1935 default: 1936 return SOC_E_NOT_FOUND; 1937 } 1938 entry_words = soc_mem_entry_words(unit, mem); 1939 shadow = soc_apache_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow; 1940 num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]); 1941 tbl_size = entry_words * num_entries; 1942 if (shadow != NULL) { 1943 sal_memset(shadow, 0, tbl_size * sizeof(uint32)); 1944 } 1945 return SOC_E_NONE; 1946 } 1947 #ifdef BCM_WARM_BOOT_SUPPORT 1948 int 1949 soc_apache_fc_map_shadow_size_get (int unit, uint32 * size) 1950 { 1951 int alloc_size = 0, mem_idx, num_entries, entry_size; 1952 for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) { 1953 num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]); 1954 entry_size = soc_mem_entry_words(unit, fc_map_mems[mem_idx]); 1955 alloc_size += entry_size * num_entries * sizeof(uint32); 1956 } 1957 *size = alloc_size; 1958 return SOC_E_NONE; 1959 } 1960 1961 int 1962 soc_apache_fc_map_shadow_sync (int unit, uint32 **sync_addr) 1963 { 1964 int mem_idx, num_entries, tbl_size, entry_size; 1965 1966 for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) { 1967 num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]); 1968 entry_size = soc_mem_entry_words(unit, fc_map_mems[mem_idx]); 1969 tbl_size = entry_size * num_entries; 1970 sal_memcpy(*sync_addr, soc_apache_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow, 1971 tbl_size * sizeof(uint32)); 1972 *sync_addr += tbl_size; 1973 } 1974 return SOC_E_NONE; 1975 } 1976 1977 int 1978 soc_apache_fc_map_shadow_load (int unit, uint32 **load_addr) 1979 { 1980 int blk, mem_idx, num_entries; 1981 int tbl_size, entry_size, vmap_size; 1982 uint32 *cache; 1983 uint32 *shadow; 1984 uint8 *vmap; 1985 int index_min; 1986 soc_mem_t mem; 1987 1988 for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) { 1989 mem = fc_map_mems[mem_idx]; 1990 num_entries = soc_mem_index_count(unit, mem); 1991 entry_size = soc_mem_entry_words(unit, mem); 1992 index_min = soc_mem_index_min(unit, mem); 1993 tbl_size = entry_size * num_entries; 1994 sal_memcpy(soc_apache_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow, *load_addr, 1995 tbl_size * sizeof(uint32)); 1996 *load_addr += tbl_size; 1997 /* restore memory cache */ 1998 vmap_size = (num_entries + 7) / 8; 1999 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 2000 if (SOC_MEM_STATE(unit, mem).cache[blk] == NULL) { 2001 continue; 2002 } 2003 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 2004 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 2005 shadow = soc_apache_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow; 2006 sal_memcpy(cache, shadow, tbl_size * sizeof(uint32)); 2007 2008 sal_memset(&vmap[index_min / 8], 0xff, 2009 (num_entries + 7 - index_min) / 8); 2010 2011 /* Clear invalid bits at the left and right ends */ 2012 vmap[index_min / 8] &= 0xff00 >> (8 - index_min % 8); 2013 vmap[vmap_size - 1] &= 0x00ff >> ((8 - num_entries % 8) % 8); 2014 } 2015 } 2016 return SOC_E_NONE; 2017 } 2018 #endif 2019 2020 #undef _ERR_MSG_MODULE_NAME /* debug */ 2021 2022 #endif /* BCM_APACHE_SUPPORT */ 2023