cosq.c (112748B)
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 <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 #if defined(BCM_TRIDENT2_SUPPORT) 17 #include <soc/td2_td2p.h> 18 19 #define _TD2_XPIPE 0 20 #define _TD2_YPIPE 1 21 22 #define _TD2_HSP_PORT_MAX_L0 5 23 #define _TD2_HSP_PORT_MAX_L1 10 24 #define _TD2_HSP_PORT_MAX_COS 8 25 26 #define _SOC_TD2_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 typedef enum { 31 _SOC_TD2_LLS_OP_TEAR = 0, 32 _SOC_TD2_LLS_OP_SETUP, 33 _SOC_TD2_LLS_OP_TRAVERSE 34 } _soc_td2p_lls_op_mode_t; 35 36 /* number of registers in the set to support Dynamic Scheduling */ 37 #define _SOC_TD2PLUS_DYN_REGISTER_SET 4 38 39 typedef struct soc_td2_fc_map_shadow_memory_s { 40 soc_mem_t mem; 41 uint32 *mem_shadow; 42 }soc_td2_fc_map_shadow_memory_t; 43 44 typedef struct soc_td2_fc_map_shadow_s { 45 soc_td2_fc_map_shadow_memory_t* shadow_array; 46 int mem_count; 47 }soc_td2_fc_map_shadow_t; 48 49 50 static soc_mem_t fc_map_mems[] = { 51 MMU_INTFI_XPIPE_FC_MAP_TBL0m, 52 MMU_INTFI_XPIPE_FC_MAP_TBL1m, 53 MMU_INTFI_YPIPE_FC_MAP_TBL0m, 54 MMU_INTFI_YPIPE_FC_MAP_TBL1m 55 }; 56 57 static soc_td2_fc_map_shadow_t soc_td2_fc_map_shadow[SOC_MAX_NUM_DEVICES]; 58 59 static int _td2_invalid_ptr[SOC_MAX_NUM_DEVICES][SOC_TD2_NODE_LVL_MAX]; 60 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 61 static int _td2p_prev_invalid_ptr[SOC_MAX_NUM_DEVICES][SOC_TD2_NODE_LVL_MAX]; 62 #endif 63 64 /* Structure to maintain the ports that are undergoing dyn sched*/ 65 typedef struct _soc_td2p_port_dyn_sched_s { 66 sal_mutex_t lock; 67 int port[_SOC_TD2PLUS_DYN_REGISTER_SET]; 68 int _soc_td2plus_init_done[SOC_MAX_NUM_DEVICES]; 69 } _soc_td2p_port_dyn_sched_t; 70 71 static _soc_td2p_port_dyn_sched_t _td2p_dyn_sched_unit_data[SOC_MAX_NUM_DEVICES]; 72 73 /* 74 * Function: 75 * _soc_td2plus_alloc_dyn_set 76 * Purpose: 77 * This function allocates the register available from 78 * the set of SP_WERR_DYN_CHANGEnA/nB/nC (n=0,1,2,3) to the port and 79 * updates the structure _td2p_dyn_sched_unit_data to keep track 80 * of the used registers from the set. 81 * Parameters: 82 * unit - (IN) unit number 83 * port - (IN) local port number 84 * r_a - (OUT) SP_WERR_DYN_CHANGEnA register 85 * r_b - (OUT) SP_WERR_DYN_CHANGEnB register 86 * r_ctrl - (OUT) SP_WERR_DYN_CHANGEnC register 87 * Returns: 88 * SOC_E_XXX 89 */ 90 STATIC int _soc_td2plus_alloc_dyn_set(int unit, int port, 91 soc_reg_t *r_a, soc_reg_t *r_b, soc_reg_t *r_ctrl) 92 { 93 _soc_td2p_port_dyn_sched_t *pcb; 94 int i, empty_at = -1, rv = SOC_E_NONE, pipe; 95 soc_info_t *si; 96 97 soc_reg_t dyn_change_a_x[] = { 98 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_0Ar, 99 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_1Ar, 100 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_2Ar, 101 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_3Ar 102 }; 103 soc_reg_t dyn_change_b_x[] = { 104 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_0Br, 105 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_1Br, 106 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_2Br, 107 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_3Br 108 }; 109 110 soc_reg_t dyn_change_ctrl_x[] = { 111 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_0Cr, 112 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_1Cr, 113 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_2Cr, 114 ES_PIPE0_LLS_SP_WERR_DYN_CHANGE_3Cr 115 }; 116 117 soc_reg_t dyn_change_a_y[] = { 118 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_0Ar, 119 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_1Ar, 120 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_2Ar, 121 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_3Ar 122 }; 123 soc_reg_t dyn_change_b_y[] = { 124 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_0Br, 125 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_1Br, 126 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_2Br, 127 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_3Br 128 }; 129 130 soc_reg_t dyn_change_ctrl_y[] = { 131 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_0Cr, 132 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_1Cr, 133 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_2Cr, 134 ES_PIPE1_LLS_SP_WERR_DYN_CHANGE_3Cr 135 }; 136 137 si = &SOC_INFO(unit); 138 pipe = (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) ? 0 : 1; 139 140 pcb = &_td2p_dyn_sched_unit_data[unit]; 141 142 sal_mutex_take(pcb->lock, sal_sem_FOREVER); 143 for (i = 0; i < _SOC_TD2PLUS_DYN_REGISTER_SET; i++) { 144 if (pcb->port[i] == -1) { 145 empty_at = i; 146 break; 147 } else if (pcb->port[i] == port) { 148 rv = SOC_E_BUSY; 149 break; 150 } 151 } 152 153 if (!rv && (empty_at >= 0)) { 154 pcb->port[empty_at] = port; 155 } 156 157 sal_mutex_give(pcb->lock); 158 159 if (rv) { 160 return rv; 161 } 162 163 if (empty_at == -1) { 164 return SOC_E_BUSY; 165 } 166 if (!pipe) { 167 *r_a = dyn_change_a_x[empty_at]; 168 *r_b = dyn_change_b_x[empty_at]; 169 *r_ctrl = dyn_change_ctrl_x[empty_at]; 170 } else { 171 *r_a = dyn_change_a_y[empty_at]; 172 *r_b = dyn_change_b_y[empty_at]; 173 *r_ctrl = dyn_change_ctrl_y[empty_at]; 174 } 175 return SOC_E_NONE; 176 } 177 178 /* 179 * Function: 180 * _soc_td2plus_free_dyn_set 181 * Purpose: 182 * This function is called after the switchover is done 183 * to update the structure _td2p_dyn_sched_unit_data by 184 * removing the port from it. This makes the register 185 * used for the request available for the next request. 186 * Parameters: 187 * unit - (IN) unit number 188 * port - (IN) local port number 189 * Returns: 190 * SOC_E_XXX 191 */ 192 STATIC int _soc_td2plus_free_dyn_set(int unit, int port) 193 { 194 _soc_td2p_port_dyn_sched_t *pcb; 195 int i; 196 197 pcb = &_td2p_dyn_sched_unit_data[unit]; 198 199 sal_mutex_take(pcb->lock, sal_sem_FOREVER); 200 for (i = 0; i < _SOC_TD2PLUS_DYN_REGISTER_SET; i++) { 201 if (pcb->port[i] == port) { 202 pcb->port[i] = -1; 203 } 204 } 205 sal_mutex_give(pcb->lock); 206 207 return SOC_E_NONE; 208 } 209 210 STATIC int 211 soc_td2_init_invalid_pointers(int unit) 212 { 213 uint32 mmu_bmp[4]; 214 int ii, port; 215 int phy_port, mmu_port; 216 soc_info_t *si; 217 218 si = &SOC_INFO(unit); 219 220 sal_memset(mmu_bmp, 0, sizeof(uint32)*4); 221 222 _td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_ROOT] = -1; 223 _td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_L1] = 224 soc_mem_index_max(unit, ES_PIPE0_LLS_L0_PARENTm); 225 _td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_L2] = 226 soc_mem_index_max(unit, ES_PIPE0_LLS_L1_PARENTm); 227 228 PBMP_ALL_ITER(unit, port) { 229 phy_port = si->port_l2p_mapping[port]; 230 mmu_port = si->port_p2m_mapping[phy_port]; 231 mmu_bmp[mmu_port/32] |= 1 << (mmu_port % 32); 232 } 233 234 /*PIPE0 & PIPE1 use the same base*/ 235 mmu_bmp[0] |= mmu_bmp[2]; 236 mmu_bmp[1] |= mmu_bmp[3]; 237 for (ii = 0; ii < (4 * 32); ii++) { 238 if ((mmu_bmp[ii/32] & (1 << (ii % 32))) == 0) { 239 _td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_L0] = ii; 240 break; 241 } 242 } 243 244 if (!soc_feature(unit, soc_feature_lls_port_mema_config_match)) { 245 /*Change invalid_ptr to 0 when it is over 52, avoid parity error*/ 246 if (_td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_L0] > 247 SOC_TD2_NUM_MMU_PORTS_PER_PIPE - 1) { 248 _td2_invalid_ptr[unit][SOC_TD2_NODE_LVL_L0] = 0; 249 } 250 } 251 return SOC_E_NONE; 252 } 253 254 int _soc_td2_invalid_parent_index(int unit, int level) 255 { 256 return _td2_invalid_ptr[unit][level]; 257 } 258 259 #define INVALID_PARENT(unit, level) _soc_td2_invalid_parent_index((unit),(level)) 260 261 #define _SOC_TD2_DEF_SCHED_NODE_BASE(u,p,cfg,t) \ 262 (cfg)[(t)].base_factor * (p) 263 264 /* 265 * Function: 266 * _soc_trident2_port_sched_type_get 267 * Purpose: 268 * Gets the scheduling type of a port. 269 * Parameters: 270 * unit - (IN) Device Number 271 * port - (IN) logical port 272 * Returns: 273 * SOC_TD2_SCHED_HSP if HSP, SOC_TD2_SCHED_LLS if LLS, 274 * SOC_TD2_SCHED_UNKNOWN else. 275 */ 276 soc_trident2_sched_type_t 277 _soc_trident2_port_sched_type_get(int unit, soc_port_t port) 278 { 279 int smode, speed; 280 soc_info_t *si; 281 282 si = &SOC_INFO(unit); 283 284 speed = si->port_speed_max[port]; 285 #ifdef BCM_TRIDENT2PLUS_SUPPORT 286 if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_TITAN2PLUS(unit)) { 287 SOC_IF_ERROR_RETURN(soc_td2p_port_speed_get(unit, port, &speed)); 288 } 289 #endif 290 291 if (speed >= 100000 || 292 (speed >= 40000 && si->frequency < 760) || 293 SOC_PBMP_MEMBER(si->eq_pbm, port)) { 294 return SOC_TD2_SCHED_HSP; 295 } else if (speed < 40000) { 296 return SOC_TD2_SCHED_LLS; 297 } else { 298 #ifdef BCM_TRIDENT2PLUS_SUPPORT 299 /* Get the current state of port_sched_hsp. Flexport overrides this 300 since the config parameter is based on logical port so when 301 we flex, the config parameter is no longer valid. */ 302 if (SOC_IS_TRIDENT2PLUS(unit)) { 303 SOC_IF_ERROR_RETURN(soc_td2p_port_sched_hsp_get(unit, port, &smode)); 304 } else 305 #endif 306 { 307 smode = soc_property_port_get(unit, port, spn_PORT_SCHED_HSP, 0); 308 } 309 return (smode == 0) ? SOC_TD2_SCHED_LLS : SOC_TD2_SCHED_HSP; 310 } 311 return SOC_TD2_SCHED_UNKNOWN; 312 } 313 314 int soc_td2_port_common_attributes_get(int unit, int port, int *pipe, 315 int *mmu_port, int *phy_port) 316 { 317 int lphy_port, lmmu_port; 318 soc_info_t *si; 319 320 si = &SOC_INFO(unit); 321 322 if (pipe) { 323 *pipe = (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) ? 0 : 1; 324 } 325 326 lphy_port = si->port_l2p_mapping[port]; 327 /* lmmu_port = si->max_port_p2m_mapping[lphy_port]; */ 328 lmmu_port = si->port_p2m_mapping[lphy_port]; 329 330 if (phy_port) { 331 *phy_port = lphy_port; 332 } 333 334 if (mmu_port) { 335 *mmu_port = lmmu_port; 336 } 337 return 0; 338 } 339 340 int _soc_trident2_root_scheduler_index(int unit, int port) 341 { 342 int mmu_port, in_pipe; 343 344 SOC_IF_ERROR_RETURN( 345 soc_td2_port_common_attributes_get(unit, port, &in_pipe, &mmu_port, NULL)); 346 return (in_pipe == 0) ? mmu_port : mmu_port - 64; 347 } 348 STATIC int 349 _soc_td2_flush_queue(int unit, int port, int queue_hw_index) 350 { 351 352 return 0; 353 } 354 355 int 356 soc_td2_cosq_set_sched_parent(int unit, soc_port_t port, 357 int level, int hw_index, 358 int parent_hw_idx) 359 { 360 soc_trident2_sched_type_t sched_type; 361 uint32 entry[SOC_MAX_MEM_WORDS], fval, fval1, rval; 362 soc_mem_t mem; 363 int l0off, l1off, idx; 364 uint32 *bmap = NULL; 365 int parent_index = 0; 366 367 LOG_INFO(BSL_LS_SOC_COSQ, 368 (BSL_META_U(unit, 369 "Port:%d L%d : %d parent:%d\n"), 370 port, level - 1, hw_index, parent_hw_idx)); 371 372 sched_type = _soc_trident2_port_sched_type_get(unit, port); 373 374 if (sched_type == SOC_TD2_SCHED_LLS) { 375 mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, level); 376 if (mem == INVALIDm) { 377 return SOC_E_INTERNAL; 378 } 379 380 SOC_IF_ERROR_RETURN 381 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 382 if (soc_mem_field32_get(unit, mem, entry, C_PARENTf) == parent_hw_idx) { 383 return SOC_E_NONE; 384 } 385 386 /* disconnecting the queue , flush it */ 387 if ((parent_hw_idx == INVALID_PARENT(unit, level)) && 388 (level == SOC_TD2_NODE_LVL_L2)) { 389 SOC_IF_ERROR_RETURN(_soc_td2_flush_queue(unit, port, hw_index)); 390 } 391 392 soc_mem_field32_set(unit, mem, entry, C_PARENTf, parent_hw_idx); 393 SOC_IF_ERROR_RETURN 394 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 395 if (level == SOC_TD2_NODE_LVL_L0) { 396 bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 397 } else if (level == SOC_TD2_NODE_LVL_L1) { 398 bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 399 } else if (level == SOC_TD2_NODE_LVL_L2) { 400 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 401 } 402 parent_index = _soc_td2_invalid_parent_index(unit, level); 403 /* SDK has allocated memory space according to value of "bmap" 404 * during process of "_soc_egress_metering_freeze". 405 * If we set a new number during process of "_soc_egress_metering_freeze", the buffer 406 * may overflow. So we add a lock at this. We should add other actions 407 * between lock and unklock. 408 */ 409 SOC_LLS_SCHEDULER_LOCK(unit); 410 if (parent_hw_idx == parent_index) { 411 SHR_BITCLR(bmap, hw_index); 412 } else { 413 SHR_BITSET(bmap, hw_index); 414 } 415 SOC_LLS_SCHEDULER_UNLOCK(unit); 416 } else if (sched_type == SOC_TD2_SCHED_HSP) { 417 if (level == SOC_TD2_NODE_LVL_L1) { 418 l0off = parent_hw_idx % 5; 419 l1off = hw_index % 10; 420 421 /* disconnect from any existing node */ 422 for (idx = 0; idx < 5; idx++) { 423 if ((l0off == idx) && 424 (parent_hw_idx != INVALID_PARENT(unit, level))) { 425 continue; 426 } 427 428 /* 429 * For L0.1, L0.2, and L0.3 nodes: 430 * The bitmap is organized as {L1.7, L1.6, ..., L1.0}, 431 * For L0.4 node: 432 * The bit 7 selects L1.9 and bit6 selects L1.8. 433 * The rest bits are not used and should be set to 0. 434 */ 435 if ((l1off >= 8) && (idx != 4)) { 436 continue; 437 } else if ((l1off < 8) && (idx == 4)) { 438 continue; 439 } 440 441 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 442 unit, port, idx, &rval)); 443 fval1 = fval = soc_reg_field_get(unit, 444 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 445 rval, CHILDREN_CONNECTION_MAPf); 446 /* L1.8 & L1.9 need to adjust hw offset */ 447 if (l1off >= 8) { 448 l1off -= 2; 449 } 450 fval &= ~(1 << l1off); 451 if (fval1 == fval) { 452 continue; 453 } 454 soc_reg_field_set(unit, 455 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 456 &rval, CHILDREN_CONNECTION_MAPf, fval); 457 SOC_IF_ERROR_RETURN( 458 WRITE_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr(unit, port, 459 idx, rval)); 460 break; 461 } 462 463 if (parent_hw_idx == INVALID_PARENT(unit, level)) { 464 SOC_IF_ERROR_RETURN(_soc_td2_flush_queue(unit, port, hw_index)); 465 } else { 466 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 467 unit, port, l0off, &rval)); 468 469 fval = soc_reg_field_get(unit, HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 470 rval, CHILDREN_CONNECTION_MAPf); 471 472 /* L1.8 & L1.9 need to adjust hw offset */ 473 if (l1off >= 8) { 474 l1off -= 2; 475 } 476 fval |= 1 << l1off; 477 soc_reg_field_set(unit, HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 478 &rval, CHILDREN_CONNECTION_MAPf, fval); 479 480 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 481 unit, port, l0off, rval)); 482 } 483 } 484 } 485 486 return SOC_E_NONE; 487 } 488 489 int 490 soc_td2_sched_weight_set(int unit, int port, int level, 491 int hw_index, int weight) 492 { 493 soc_trident2_sched_type_t sched_type; 494 uint32 entry[SOC_MAX_MEM_WORDS], rval; 495 soc_mem_t mem = INVALIDm; 496 soc_reg_t reg = INVALIDr; 497 498 LOG_INFO(BSL_LS_SOC_COSQ, 499 (BSL_META_U(unit, 500 "sched_weight_set L%d csch_index=%d wt=%d\n"), 501 level, hw_index, weight)); 502 503 sched_type = _soc_trident2_port_sched_type_get(unit, port); 504 505 if (weight > 0x7f) { 506 return SOC_E_PARAM; 507 } 508 if (sched_type == SOC_TD2_SCHED_LLS) { 509 mem = _SOC_TD2_NODE_WIEGHT_MEM(unit, port, level); 510 if (mem == INVALIDm) { 511 return SOC_E_INTERNAL; 512 } 513 SOC_IF_ERROR_RETURN 514 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 515 soc_mem_field32_set(unit, mem, &entry, C_WEIGHTf, weight); 516 SOC_IF_ERROR_RETURN 517 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 518 } else if (sched_type == SOC_TD2_SCHED_HSP) { 519 if ((level == SOC_TD2_NODE_LVL_L0) || (level == SOC_TD2_NODE_LVL_L1)) { 520 if (level == SOC_TD2_NODE_LVL_L0) { 521 hw_index = hw_index % 5; 522 reg = HSP_SCHED_L0_NODE_WEIGHTr; 523 } else if (level == SOC_TD2_NODE_LVL_L1) { 524 hw_index = hw_index % 10; 525 reg = HSP_SCHED_L1_NODE_WEIGHTr; 526 } 527 528 rval = 0; 529 soc_reg_field_set(unit, reg, &rval, WEIGHTf, weight); 530 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, hw_index, rval)); 531 } else if (level == SOC_TD2_NODE_LVL_L2) { 532 if (hw_index < 1480) 533 { 534 reg = HSP_SCHED_L2_UC_QUEUE_WEIGHTr; 535 } else { 536 reg = HSP_SCHED_L2_MC_QUEUE_WEIGHTr; 537 } 538 539 rval = 0; 540 hw_index = hw_index % 10; 541 soc_reg_field_set(unit, reg, &rval, WEIGHTf, weight); 542 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, hw_index, rval)); 543 } 544 } 545 return SOC_E_NONE; 546 } 547 548 int 549 soc_td2_sched_weight_get(int unit, int port, int level, 550 int hw_index, int *weight) 551 { 552 soc_trident2_sched_type_t sched_type; 553 uint32 entry[SOC_MAX_MEM_WORDS], rval; 554 soc_mem_t mem = INVALIDm; 555 soc_reg_t reg = INVALIDr; 556 557 sched_type = _soc_trident2_port_sched_type_get(unit, port); 558 559 if (sched_type == SOC_TD2_SCHED_LLS) { 560 mem = _SOC_TD2_NODE_WIEGHT_MEM(unit, port, level); 561 if (mem == INVALIDm) { 562 return SOC_E_INTERNAL; 563 } 564 SOC_IF_ERROR_RETURN 565 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 566 *weight = soc_mem_field32_get(unit, mem, &entry, C_WEIGHTf); 567 } else if (sched_type == SOC_TD2_SCHED_HSP) { 568 if ((level == SOC_TD2_NODE_LVL_L0) || (level == SOC_TD2_NODE_LVL_L1)) { 569 if (level == SOC_TD2_NODE_LVL_L0) { 570 hw_index = hw_index % 5; 571 reg = HSP_SCHED_L0_NODE_WEIGHTr; 572 } else if (level == SOC_TD2_NODE_LVL_L1) { 573 hw_index = hw_index % 10; 574 reg = HSP_SCHED_L1_NODE_WEIGHTr; 575 } 576 577 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, hw_index, &rval)); 578 *weight = soc_reg_field_get(unit, reg, rval, WEIGHTf); 579 } else if (level == SOC_TD2_NODE_LVL_L2) { 580 if (hw_index < 1480) 581 { 582 reg = HSP_SCHED_L2_UC_QUEUE_WEIGHTr; 583 } else { 584 reg = HSP_SCHED_L2_MC_QUEUE_WEIGHTr; 585 } 586 587 hw_index = hw_index % 10; 588 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, hw_index, &rval)); 589 *weight = soc_reg_field_get(unit, reg, rval, WEIGHTf); 590 } 591 } 592 593 LOG_INFO(BSL_LS_SOC_COSQ, 594 (BSL_META_U(unit, 595 "sched_weight_get L%d csch_index=%d wt=%d\n"), 596 level, hw_index, *weight)); 597 598 return SOC_E_NONE; 599 } 600 601 /* 602 * Function: 603 * soc_td2_cosq_set_sched_child_config_dynamic 604 * Purpose: 605 * This function enables the spri_vect_mode by setting the 606 * spri_vect_mode_enable field to 1 in the LLS_CONFIG0 reg, which changes 607 * p_num_spri[3:0] to p_vect_spri[7:0]. It allocates the register from set 608 * of SP_WERR_DYN_CHNG_nA/nB/nC registers to the port. It then sets the 609 * SP_WERR_DYN_CHNG_nB/nC reg with the new value for the node id's parent. 610 * It sets the fields in SP_WERR_DYN_CHNG_nA with the info about the node 611 * to be switched like node_id, node_level and parent_id along with in_use 612 * field to 1, which triggers the request in H/W. The H/W clears in_use 613 * field to 0 once the switchover is complete, so we keep polling its 614 * to know about the completion of the request. 615 * Parameters: 616 * unit - (IN) unit number 617 * port - (IN) local port number 618 * level - (IN) level of the node 619 * index - (IN) index of the node 620 * num_spri - (IN) number of SPRI child nodes 621 * first_child - (IN) first child node 622 * first_mc_child - (IN) first multicast child node 623 * ucmap - (IN) unicast map 624 * spmap - (IN) spri map 625 * child_index - (IN) index number of the child 626 * Returns: 627 * SOC_E_XXX 628 */ 629 int 630 soc_td2_cosq_set_sched_child_config_dynamic(int unit, soc_port_t port, 631 int level, int index, 632 int num_spri, int first_child, 633 int first_mc_child, uint32 ucmap, 634 uint32 spmap, int child_index) 635 { 636 uint32 entry[SOC_MAX_MEM_WORDS], rval, d32, timeout_val, old_spmap, f1, f2; 637 soc_mem_t mem, mem2; 638 int rv = SOC_E_NONE; 639 soc_reg_t r_a = INVALIDr, r_b = INVALIDr, r_ctrl = INVALIDr; 640 soc_timeout_t timeout; 641 SOC_IF_ERROR_RETURN(READ_ES_PIPE0_LLS_CONFIG0r(unit, &rval)); 642 643 soc_reg_field_get(unit, ES_PIPE0_LLS_CONFIG0r, rval, SPRI_VECT_MODE_ENABLEf); 644 if (!soc_reg_field_get(unit, ES_PIPE0_LLS_CONFIG0r, rval, SPRI_VECT_MODE_ENABLEf)) { 645 soc_reg_field_set(unit, ES_PIPE0_LLS_CONFIG0r, &rval, SPRI_VECT_MODE_ENABLEf, 1); 646 SOC_IF_ERROR_RETURN(WRITE_ES_PIPE0_LLS_CONFIG0r(unit, rval)); 647 SOC_IF_ERROR_RETURN(WRITE_ES_PIPE1_LLS_CONFIG0r(unit, rval)); 648 } 649 650 SOC_IF_ERROR_RETURN(_soc_td2plus_alloc_dyn_set(unit, port, 651 &r_a, &r_b, &r_ctrl)); 652 653 mem = _SOC_TD2_NODE_CONFIG_MEM(unit, port, level); 654 mem2 = _SOC_TD2_NODE_CONFIG_MEM2(unit, port, level); 655 if (mem == INVALIDm || mem2 == INVALIDm) { 656 return SOC_E_INTERNAL; 657 } 658 659 /* Getting the old spmap */ 660 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 661 f1 = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf); 662 f2 = soc_mem_field32_get(unit, mem, &entry, P_VECT_SPRI_7_4f); 663 old_spmap = f1 | (f2 << 4); 664 665 LOG_INFO(BSL_LS_SOC_COSQ, 666 (BSL_META_U(unit, 667 "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x NUMSP=%d\n"), 668 port, (level==0) ? "r" : "", level - 1, 669 index, first_child, first_mc_child, ucmap, num_spri)); 670 671 /* Setting the memory fields based on the new spmap */ 672 soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, spmap & 0xf); 673 soc_mem_field32_set(unit, mem, &entry, P_VECT_SPRI_7_4f, (spmap >> 4) & 0xf); 674 675 if ((mem == ES_PIPE0_LLS_L1_MEMA_CONFIGm) || 676 (mem == ES_PIPE1_LLS_L1_MEMA_CONFIGm)) { 677 soc_mem_field32_set(unit, mem, &entry, P_START_UC_SPRIf, first_child); 678 soc_mem_field32_set(unit, mem, &entry, P_START_MC_SPRIf, first_mc_child); 679 soc_mem_field32_set(unit, mem, &entry, P_SPRI_SELECTf, 680 (num_spri > 0) ? ucmap : 0); 681 } else { 682 soc_mem_field32_set(unit, mem, &entry, P_START_SPRIf, first_child); 683 } 684 685 SOC_IF_ERROR_RETURN( 686 soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry)); 687 SOC_IF_ERROR_RETURN( 688 soc_mem_write(unit, mem2, MEM_BLOCK_ANY, index, &entry)); 689 690 691 rval = 0; 692 soc_bits_get(entry, 0, 31, &d32); 693 soc_reg_field_set(unit, r_ctrl, &rval, LLS_PARENT_CONFIGf, d32); 694 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_ctrl, REG_PORT_ANY, 0, rval)); 695 696 rval = 0; 697 soc_bits_get(entry, 32, 40, &d32); 698 soc_reg_field_set(unit, r_b, &rval, LLS_PARENT_CONFIGf, d32); 699 soc_reg_field_set(unit, r_b, &rval, LLS_PARENT_CONFIG_ORIGINAL_SP_VECTORf, 700 old_spmap); 701 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_b, REG_PORT_ANY, 0, rval)); 702 703 rval = 0; 704 soc_reg_field_set(unit, r_a, &rval, NODE_LEVELf, level + 1); 705 soc_reg_field_set(unit, r_a, &rval, NODE_IDf, child_index); 706 soc_reg_field_set(unit, r_a, &rval, PARENT_IDf, index); 707 soc_reg_field_set(unit, r_a, &rval, IN_USEf, 1); 708 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, r_a, REG_PORT_ANY, 0, rval)); 709 710 if (!SAL_BOOT_SIMULATION) { 711 timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 20000); 712 soc_timeout_init(&timeout, timeout_val, 0); 713 714 do { 715 SOC_IF_ERROR_RETURN( 716 soc_reg32_get(unit, r_a, REG_PORT_ANY, 0, &rval)); 717 718 if (soc_timeout_check(&timeout)) { 719 rv = SOC_E_TIMEOUT; 720 break; 721 } 722 } while (soc_reg_field_get(unit, r_a, rval, IN_USEf)); 723 } 724 725 SOC_IF_ERROR_RETURN(_soc_td2plus_free_dyn_set(unit, port)); 726 727 return rv; 728 } 729 730 int 731 soc_td2_cosq_set_sched_child_config(int unit, soc_port_t port, 732 int level, int index, 733 int num_spri, int first_sp_child, 734 int first_sp_mc_child, uint32 ucmap, uint32 spmap) 735 { 736 soc_trident2_sched_type_t sched_type; 737 uint32 entry[SOC_MAX_MEM_WORDS], rval; 738 soc_mem_t mem, mem2; 739 740 LOG_INFO(BSL_LS_SOC_COSQ, 741 (BSL_META_U(unit, 742 "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x\n"), 743 port, (level == 0) ? "r" : "", level - 1, 744 index, first_sp_child, first_sp_mc_child, ucmap)); 745 746 mem = INVALIDm; 747 748 sched_type = _soc_trident2_port_sched_type_get(unit, port); 749 if (sched_type == SOC_TD2_SCHED_HSP) { 750 return SOC_E_PARAM; 751 } 752 753 if (soc_feature(unit, soc_feature_vector_based_spri)) { 754 SOC_IF_ERROR_RETURN(READ_ES_PIPE0_LLS_CONFIG0r(unit, &rval)); 755 if (!soc_reg_field_get(unit, ES_PIPE0_LLS_CONFIG0r, rval, SPRI_VECT_MODE_ENABLEf)) { 756 soc_reg_field_set(unit, ES_PIPE0_LLS_CONFIG0r, &rval, 757 SPRI_VECT_MODE_ENABLEf, 1); 758 SOC_IF_ERROR_RETURN(WRITE_ES_PIPE0_LLS_CONFIG0r(unit, rval)); 759 SOC_IF_ERROR_RETURN(WRITE_ES_PIPE1_LLS_CONFIG0r(unit, rval)); 760 } 761 } 762 763 mem = _SOC_TD2_NODE_CONFIG_MEM(unit, port, level); 764 mem2 = _SOC_TD2_NODE_CONFIG_MEM2(unit, port, level); 765 /* coverity[negative_returns : FALSE] */ 766 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 767 if (soc_feature(unit, soc_feature_vector_based_spri)) { 768 /* Setting the memory fields based on the new spmap */ 769 soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, spmap & 0xf); 770 soc_mem_field32_set(unit, mem, &entry, P_VECT_SPRI_7_4f, 771 (spmap >> 4) & 0xf); 772 } else { 773 soc_mem_field32_set(unit, mem, &entry, P_NUM_SPRIf, num_spri); 774 } 775 776 if ((mem == ES_PIPE0_LLS_L1_MEMA_CONFIGm) || 777 (mem == ES_PIPE1_LLS_L1_MEMA_CONFIGm)) { 778 soc_mem_field32_set(unit, mem, &entry, P_START_UC_SPRIf, first_sp_child); 779 soc_mem_field32_set(unit, mem, &entry, P_START_MC_SPRIf, 780 first_sp_mc_child); 781 soc_mem_field32_set(unit, mem, &entry, P_SPRI_SELECTf, 782 (num_spri > 0) ? ucmap : 0); 783 } else { 784 soc_mem_field32_set(unit, mem, &entry, P_START_SPRIf, first_sp_child); 785 } 786 787 SOC_IF_ERROR_RETURN(soc_mem_write 788 (unit, mem, MEM_BLOCK_ANY, index, &entry)); 789 SOC_IF_ERROR_RETURN 790 (soc_mem_write(unit, mem2, MEM_BLOCK_ANY, index, &entry)); 791 792 return SOC_E_NONE; 793 } 794 795 int 796 soc_td2_cosq_set_sched_mode(int unit, soc_port_t port, int level, int index, 797 const soc_td2_sched_mode_e mode, int weight) 798 { 799 soc_trident2_sched_type_t sched_type; 800 uint32 entry[SOC_MAX_MEM_WORDS], mfval = 0, rval, wrr_mask, sp_mask; 801 soc_mem_t mem, mem2; 802 soc_reg_t reg, reg2; 803 int fval, idx, parent_idx = -1; 804 805 LOG_INFO(BSL_LS_SOC_COSQ, 806 (BSL_META_U(unit, 807 "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"), 808 port, (level == 0) ? "r" : "", level - 1, 809 index, mode, weight)); 810 811 reg = INVALIDr; 812 reg2 = INVALIDr; 813 mem = INVALIDm; 814 sched_type = _soc_trident2_port_sched_type_get(unit, port); 815 if (sched_type == SOC_TD2_SCHED_HSP) { 816 /* get the port relative index / offset */ 817 if (level == SOC_TD2_NODE_LVL_L0) { 818 index = index % 5; 819 reg = HSP_SCHED_PORT_CONFIGr; 820 reg2 = HSP_SCHED_L0_NODE_CONFIGr; 821 parent_idx = 0; 822 } else if (level == SOC_TD2_NODE_LVL_L1) { 823 index = index % 10; 824 reg = HSP_SCHED_L0_NODE_CONFIGr; 825 reg2 = HSP_SCHED_L1_NODE_CONFIGr; 826 /* Find the Parent index for the current child */ 827 for (idx = 1; idx < 5; idx++) { 828 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 829 unit, port, idx, &rval)); 830 fval = soc_reg_field_get(unit, 831 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 832 rval, CHILDREN_CONNECTION_MAPf); 833 if (idx == 4) { 834 if ((index >= 8) && (fval & (1 << (index - 2)))) { 835 parent_idx = idx; 836 break; 837 } 838 } else { 839 if (fval & (1 << index)) { 840 parent_idx = idx; 841 break; 842 } 843 } 844 } 845 } else if (level == SOC_TD2_NODE_LVL_L2) { 846 uint32 rval = 0; 847 uint32 mc_group_mode = 0; 848 SOC_IF_ERROR_RETURN( 849 READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval)); 850 mc_group_mode = soc_reg_field_get(unit, 851 HSP_SCHED_PORT_CONFIGr, 852 rval, MC_GROUP_MODEf); 853 reg = HSP_SCHED_L1_NODE_CONFIGr; 854 if (index >= 1480) { 855 reg2 = HSP_SCHED_L2_MC_QUEUE_CONFIGr; 856 } else { 857 reg2 = HSP_SCHED_L2_UC_QUEUE_CONFIGr; 858 } 859 parent_idx = index % 10; 860 861 if (mc_group_mode && (index >= 1480)) { 862 if ((index % 10) < _TD2_HSP_PORT_MAX_COS) { 863 reg= HSP_SCHED_L0_NODE_CONFIGr; 864 parent_idx = 0; 865 } 866 } 867 } else { 868 return SOC_E_PARAM; 869 } 870 871 if (parent_idx == -1) { 872 return SOC_E_INTERNAL; 873 } 874 875 if (mode == SOC_TD2_SCHED_MODE_STRICT) { 876 weight = 0; 877 } else if (mode == SOC_TD2_SCHED_MODE_WRR) { 878 mfval = 1; 879 } else if (mode == SOC_TD2_SCHED_MODE_WDRR) { 880 mfval = 0; 881 } else { 882 return SOC_E_PARAM; 883 } 884 885 /* selection between SP and WxRR is based on weight property. */ 886 SOC_IF_ERROR_RETURN(soc_td2_sched_weight_set(unit, port, 887 level, index, weight)); 888 889 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 890 wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf); 891 wrr_mask &= ~(1 << parent_idx); 892 wrr_mask |= (mfval << parent_idx); 893 soc_reg_field_set(unit, reg, &rval, ENABLE_WRRf, wrr_mask); 894 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 895 896 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg2, port, 0, &rval)); 897 sp_mask = soc_reg_field_get(unit, reg2, rval, ENABLE_SP_IN_MINf); 898 if (mode == SOC_TD2_SCHED_MODE_STRICT) { 899 sp_mask |= (1 << (index % 10)); 900 } else { 901 sp_mask &= ~(1 << (index % 10)); 902 } 903 soc_reg_field_set(unit, reg2, &rval, ENABLE_SP_IN_MINf, sp_mask); 904 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg2, port, 0, rval)); 905 } else { 906 if (mode == SOC_TD2_SCHED_MODE_STRICT) { 907 weight = 0; 908 } 909 910 SOC_IF_ERROR_RETURN(soc_td2_sched_weight_set(unit, port, 911 level, index, weight)); 912 913 if (mode != SOC_TD2_SCHED_MODE_STRICT) { 914 mem = _SOC_TD2_NODE_CONFIG_MEM(unit, port, SOC_TD2_NODE_LVL_ROOT); 915 mem2 = _SOC_TD2_NODE_CONFIG_MEM2(unit, port, SOC_TD2_NODE_LVL_ROOT); 916 index = _soc_trident2_root_scheduler_index(unit, port); 917 SOC_IF_ERROR_RETURN( 918 soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 919 soc_mem_field32_set(unit, mem, entry, 920 PACKET_MODE_WRR_ACCOUNTING_ENABLEf, 921 (mode == SOC_TD2_SCHED_MODE_WRR) ? 1 : 0); 922 SOC_IF_ERROR_RETURN( 923 soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry)); 924 SOC_IF_ERROR_RETURN 925 (soc_mem_write(unit, mem2, MEM_BLOCK_ANY, index, &entry)); 926 } 927 } 928 return SOC_E_NONE; 929 } 930 931 int 932 soc_td2_cosq_set_sched_config(int unit, soc_port_t port, 933 int level, int index, int child_index, 934 int num_spri, int first_child, 935 int first_mc_child, uint32 ucmap, uint32 spmap, 936 const soc_td2_sched_mode_e mode, int weight) 937 { 938 int child_level = -1, wt = 0; 939 soc_td2_sched_mode_e cur_sched_mode = SOC_TD2_SCHED_MODE_UNKNOWN; 940 int sp_vec = soc_feature(unit, soc_feature_vector_based_spri); 941 942 if (level >= SOC_TD2_NODE_LVL_L2) { 943 return SOC_E_PARAM; 944 } 945 946 if (child_index >= 0) { 947 soc_td2_get_child_type(unit, port, level, &child_level); 948 SOC_IF_ERROR_RETURN(soc_td2_cosq_get_sched_mode(unit, port, child_level, 949 child_index, &cur_sched_mode, &wt)); 950 } 951 952 /* If dynamice switchover feature is enabled, we configure the child 953 based on the switchover request and trigger the switchover in H/W */ 954 if (sp_vec && (cur_sched_mode != mode)) { 955 SOC_IF_ERROR_RETURN( 956 soc_td2_cosq_set_sched_child_config_dynamic(unit, port, 957 level, index, num_spri, first_child, 958 first_mc_child, ucmap, spmap, child_index)); 959 } else { 960 SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_child_config(unit, port, 961 level, index, num_spri, first_child, first_mc_child, ucmap, spmap)); 962 963 } 964 965 if (child_index >= 0) { 966 SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_mode(unit, port, child_level, 967 child_index, mode, weight)); 968 } 969 970 return SOC_E_NONE; 971 } 972 973 int 974 soc_td2_cosq_get_sched_child_config(int unit, soc_port_t port, 975 int level, int index, 976 int *pnum_spri, int *pfirst_sp_child, 977 int *pfirst_sp_mc_child, uint32 *pucmap, 978 uint32 *pspmap) 979 { 980 soc_trident2_sched_type_t sched_type; 981 uint32 entry[SOC_MAX_MEM_WORDS]; 982 983 soc_mem_t mem; 984 uint32 num_spri = 0, ucmap = 0, f1, f2; 985 int first_sp_child = -1, first_sp_mc_child = -1, ii; 986 int sp_vec = soc_feature(unit, soc_feature_vector_based_spri); 987 988 *pspmap = 0; 989 990 sched_type = _soc_trident2_port_sched_type_get(unit, port); 991 992 mem = INVALIDm; 993 994 if (sched_type == SOC_TD2_SCHED_HSP) { 995 return SOC_E_PARAM; 996 } 997 998 mem = _SOC_TD2_NODE_CONFIG_MEM(unit, port, level); 999 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 1000 1001 /* If dynamic switchover feature is enabled, we calculate the spmap based 1002 on the 8 bit p_vect_spri[7:0] and also the number of SPRI nodes */ 1003 if (sp_vec) { 1004 f1 = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf); 1005 f2 = soc_mem_field32_get(unit, mem, &entry, P_VECT_SPRI_7_4f); 1006 *pspmap = f1 | (f2 << 4); 1007 if ( (f1 >> 1) == 0 && f1 > 0) { 1008 num_spri = 1; 1009 } else { 1010 1011 for (ii = 0; ii < 8; ii++) { 1012 if ((1 << ii) & *pspmap) { 1013 num_spri++; 1014 } 1015 } 1016 } 1017 } else { 1018 num_spri = soc_mem_field32_get(unit, mem, &entry, P_NUM_SPRIf); 1019 } 1020 1021 if ((mem == ES_PIPE0_LLS_L1_MEMA_CONFIGm) || 1022 (mem == ES_PIPE1_LLS_L1_MEMA_CONFIGm)) { 1023 first_sp_child = soc_mem_field32_get(unit, mem, &entry, P_START_UC_SPRIf); 1024 first_sp_mc_child = soc_mem_field32_get(unit, mem, 1025 &entry, P_START_MC_SPRIf); 1026 ucmap = soc_mem_field32_get(unit, mem, &entry, P_SPRI_SELECTf); 1027 } else { 1028 first_sp_child = soc_mem_field32_get(unit, mem, &entry, P_START_SPRIf); 1029 first_sp_mc_child = 0; 1030 } 1031 1032 if (num_spri == 0) { 1033 ucmap = 0; 1034 } 1035 1036 if (pnum_spri) { 1037 *pnum_spri = num_spri; 1038 } 1039 1040 if (pucmap) { 1041 *pucmap = ucmap; 1042 } 1043 1044 if (pfirst_sp_child) { 1045 *pfirst_sp_child = first_sp_child; 1046 } 1047 1048 if (pfirst_sp_mc_child) { 1049 *pfirst_sp_mc_child = first_sp_mc_child; 1050 } 1051 1052 LOG_INFO(BSL_LS_SOC_COSQ, 1053 (BSL_META_U(unit, 1054 "Port:%d L%s%d config : index=%d FC=%d FMC=%d UMAP=0x%x\n"), 1055 port, (level == 0) ? "r" : "", level - 1, 1056 index, first_sp_child, first_sp_mc_child, ucmap)); 1057 1058 return SOC_E_NONE; 1059 } 1060 1061 int 1062 soc_td2_cosq_get_sched_mode(int unit, soc_port_t port, int level, 1063 int index, soc_td2_sched_mode_e *pmode, int *weight) 1064 { 1065 soc_trident2_sched_type_t sched_type; 1066 uint32 entry[SOC_MAX_MEM_WORDS], rval, wrr_mask; 1067 soc_td2_sched_mode_e mode = SOC_TD2_SCHED_MODE_UNKNOWN; 1068 soc_mem_t mem; 1069 soc_reg_t reg; 1070 int parent_idx = 0; 1071 int idx, fval; 1072 1073 reg = INVALIDr; 1074 mem = INVALIDm; 1075 sched_type = _soc_trident2_port_sched_type_get(unit, port); 1076 1077 if (sched_type == SOC_TD2_SCHED_HSP) { 1078 /* get the port relative index / offset */ 1079 if (level == SOC_TD2_NODE_LVL_L0) { 1080 index = index % 5; 1081 reg = HSP_SCHED_PORT_CONFIGr; 1082 parent_idx = 0; 1083 } else if (level == SOC_TD2_NODE_LVL_L1) { 1084 index = index % 10; 1085 reg = HSP_SCHED_L0_NODE_CONFIGr; 1086 /* Find the Parent index for the current child */ 1087 for (idx = 1; idx < 5; idx++) { 1088 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 1089 unit, port, idx, &rval)); 1090 fval = soc_reg_field_get(unit, 1091 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 1092 rval, CHILDREN_CONNECTION_MAPf); 1093 if (idx == 4) { 1094 if ((index >= 8) && (fval & (1 << (index - 2)))) { 1095 parent_idx = idx; 1096 break; 1097 } 1098 } else { 1099 if (fval & (1 << index)) { 1100 parent_idx = idx; 1101 break; 1102 } 1103 } 1104 } 1105 } else if (level == SOC_TD2_NODE_LVL_L2) { 1106 uint32 rval = 0; 1107 uint32 mc_group_mode = 0; 1108 SOC_IF_ERROR_RETURN( 1109 READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval)); 1110 mc_group_mode = soc_reg_field_get(unit, 1111 HSP_SCHED_PORT_CONFIGr, 1112 rval, MC_GROUP_MODEf); 1113 reg = HSP_SCHED_L1_NODE_CONFIGr; 1114 parent_idx = index % 10; 1115 1116 if (mc_group_mode && (index >= 1480)) { 1117 if ((index % 10) < _TD2_HSP_PORT_MAX_COS) { 1118 reg= HSP_SCHED_L0_NODE_CONFIGr; 1119 parent_idx = 0; 1120 } 1121 } 1122 } else { 1123 return SOC_E_PARAM; 1124 } 1125 1126 /* selection between SP and WxRR is based on weight property. */ 1127 SOC_IF_ERROR_RETURN(soc_td2_sched_weight_get(unit, port, 1128 level, index, weight)); 1129 if (*weight == 0) { 1130 mode = SOC_TD2_SCHED_MODE_STRICT; 1131 } else { 1132 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 1133 wrr_mask = soc_reg_field_get(unit, reg, rval, ENABLE_WRRf); 1134 if (wrr_mask & (1 << parent_idx)) { 1135 mode = SOC_TD2_SCHED_MODE_WRR; 1136 } else { 1137 mode = SOC_TD2_SCHED_MODE_WDRR; 1138 } 1139 } 1140 } else { 1141 SOC_IF_ERROR_RETURN(soc_td2_sched_weight_get(unit, port, 1142 level, index, weight)); 1143 1144 if (*weight == 0) { 1145 mode = SOC_TD2_SCHED_MODE_STRICT; 1146 } else { 1147 mem = _SOC_TD2_NODE_CONFIG_MEM(unit, port, SOC_TD2_NODE_LVL_ROOT); 1148 index = _soc_trident2_root_scheduler_index(unit, port); 1149 SOC_IF_ERROR_RETURN( 1150 soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 1151 if (soc_mem_field32_get(unit, mem, 1152 entry, PACKET_MODE_WRR_ACCOUNTING_ENABLEf)) { 1153 mode = SOC_TD2_SCHED_MODE_WRR; 1154 } else { 1155 mode = SOC_TD2_SCHED_MODE_WDRR; 1156 } 1157 } 1158 } 1159 1160 if (pmode) { 1161 *pmode = mode; 1162 } 1163 1164 LOG_INFO(BSL_LS_SOC_COSQ, 1165 (BSL_META_U(unit, 1166 "Port:%d L%s%d config : index=%d MODE=%d WT=%d\n"), 1167 port, (level == 0) ? "r" : "", level - 1, index, mode, *weight)); 1168 1169 return SOC_E_NONE; 1170 } 1171 1172 int 1173 soc_td2_cosq_get_sched_config(int unit, soc_port_t port, 1174 int level, int index, int child_index, 1175 int *pnum_spri, int *pfirst_child, 1176 int *pfirst_mc_child, uint32 *pucmap, uint32 *pspmap, 1177 soc_td2_sched_mode_e *pmode, int *weight) 1178 { 1179 int child_level; 1180 1181 if (level >= SOC_TD2_NODE_LVL_L2) { 1182 return SOC_E_PARAM; 1183 } 1184 1185 SOC_IF_ERROR_RETURN(soc_td2_cosq_get_sched_child_config(unit, port, level, 1186 index, pnum_spri, pfirst_child, pfirst_mc_child, pucmap, 1187 pspmap)); 1188 1189 if (child_index >= 0) { 1190 soc_td2_get_child_type(unit, port, level, &child_level); 1191 1192 SOC_IF_ERROR_RETURN( 1193 soc_td2_cosq_get_sched_mode(unit, port, child_level, child_index, 1194 pmode, weight)); 1195 } 1196 1197 return SOC_E_NONE; 1198 } 1199 1200 int soc_td2_get_child_type(int unit, soc_port_t port, int level, 1201 int *child_type) 1202 { 1203 *child_type = -1; 1204 1205 if (level == SOC_TD2_NODE_LVL_ROOT) { 1206 *child_type = SOC_TD2_NODE_LVL_L0; 1207 } else if (level == SOC_TD2_NODE_LVL_L0) { 1208 *child_type = SOC_TD2_NODE_LVL_L1; 1209 } else if (level == SOC_TD2_NODE_LVL_L1) { 1210 *child_type = SOC_TD2_NODE_LVL_L2; 1211 } 1212 return SOC_E_NONE; 1213 } 1214 1215 typedef struct _soc_td2_lls_config_s { 1216 int level; 1217 int node_id; 1218 int num_children; 1219 int sched_mode; 1220 int weights[48]; 1221 uint32 uc_mc_map; 1222 } _soc_td2_lls_config_t; 1223 1224 /* CPU lls tree is dynamically generated */ 1225 static _soc_td2_lls_config_t *_td2_cpu_port_lls_config[SOC_MAX_NUM_DEVICES]; 1226 1227 static _soc_td2_lls_config_t _td2_port_lls_config[] = { 1228 /* SOC_TD2_NODE_LVL_ROOT */ 1229 { SOC_TD2_NODE_LVL_ROOT, 0, 1230 1, SOC_TD2_SCHED_MODE_WRR, 1231 { 1,1,1,1,1,1,1,1, 1232 1,1,1,1,1,1,1,1, 1233 1,1,1,1,1,1,1,1, 1234 1,1,1,1,1,1,1,1, 1235 1,1,1,1,1,1,1,1, 1236 1,1,1,1,1,1,1,1 }, 1237 0}, 1238 /* SOC_TD2_NODE_LVL_L0 L0.0 */ 1239 { SOC_TD2_NODE_LVL_L0, 0, 1240 10, SOC_TD2_SCHED_MODE_WRR, 1241 { 1,1,1,1,1,1,1,1, 1242 1,1,1,1,1,1,1,1, 1243 1,1,1,1,1,1,1,1, 1244 1,1,1,1,1,1,1,1, 1245 1,1,1,1,1,1,1,1, 1246 1,1,1,1,1,1,1,1 }, 1247 0}, 1248 /* SOC_TD2_NODE_LVL_L1 L1.0 */ 1249 { SOC_TD2_NODE_LVL_L1, 0, 1250 2, SOC_TD2_SCHED_MODE_WRR, 1251 { 1,1,1,1,1,1,1,1, 1252 1,1,1,1,1,1,1,1, 1253 1,1,1,1,1,1,1,1, 1254 1,1,1,1,1,1,1,1, 1255 1,1,1,1,1,1,1,1, 1256 1,1,1,1,1,1,1,1 }, 1257 0x1 /* 1 UC nodes, 1 MC node */}, 1258 /* SOC_TD2_NODE_LVL_L1 L1.1 */ 1259 { SOC_TD2_NODE_LVL_L1, 1, 1260 2, SOC_TD2_SCHED_MODE_WRR, 1261 { 1,1,1,1,1,1,1,1, 1262 1,1,1,1,1,1,1,1, 1263 1,1,1,1,1,1,1,1, 1264 1,1,1,1,1,1,1,1, 1265 1,1,1,1,1,1,1,1, 1266 1,1,1,1,1,1,1,1 }, 1267 0x1 /* 1 UC nodes, 1 MC node */}, 1268 /* SOC_TD2_NODE_LVL_L1 L1.2 */ 1269 { SOC_TD2_NODE_LVL_L1, 2, 1270 2, SOC_TD2_SCHED_MODE_WRR, 1271 { 1,1,1,1,1,1,1,1, 1272 1,1,1,1,1,1,1,1, 1273 1,1,1,1,1,1,1,1, 1274 1,1,1,1,1,1,1,1, 1275 1,1,1,1,1,1,1,1, 1276 1,1,1,1,1,1,1,1 }, 1277 0x1 /* 1 UC nodes, 1 MC node */}, 1278 /* SOC_TD2_NODE_LVL_L1 L1.3 */ 1279 { SOC_TD2_NODE_LVL_L1, 3, 1280 2, SOC_TD2_SCHED_MODE_WRR, 1281 { 1,1,1,1,1,1,1,1, 1282 1,1,1,1,1,1,1,1, 1283 1,1,1,1,1,1,1,1, 1284 1,1,1,1,1,1,1,1, 1285 1,1,1,1,1,1,1,1, 1286 1,1,1,1,1,1,1,1 }, 1287 0x1 /* 1 UC nodes, 1 MC node */}, 1288 /* SOC_TD2_NODE_LVL_L1 L1.4 */ 1289 { SOC_TD2_NODE_LVL_L1, 4, 1290 2, SOC_TD2_SCHED_MODE_WRR, 1291 { 1,1,1,1,1,1,1,1, 1292 1,1,1,1,1,1,1,1, 1293 1,1,1,1,1,1,1,1, 1294 1,1,1,1,1,1,1,1, 1295 1,1,1,1,1,1,1,1, 1296 1,1,1,1,1,1,1,1 }, 1297 0x1 /* 1 UC nodes, 1 MC node */}, 1298 /* SOC_TD2_NODE_LVL_L1 L1.5 */ 1299 { SOC_TD2_NODE_LVL_L1, 5, 1300 2, SOC_TD2_SCHED_MODE_WRR, 1301 { 1,1,1,1,1,1,1,1, 1302 1,1,1,1,1,1,1,1, 1303 1,1,1,1,1,1,1,1, 1304 1,1,1,1,1,1,1,1, 1305 1,1,1,1,1,1,1,1, 1306 1,1,1,1,1,1,1,1 }, 1307 0x1 /* 1 UC nodes, 1 MC node */}, 1308 /* SOC_TD2_NODE_LVL_L1 L1.6 */ 1309 { SOC_TD2_NODE_LVL_L1, 6, 1310 2, SOC_TD2_SCHED_MODE_WRR, 1311 { 1,1,1,1,1,1,1,1, 1312 1,1,1,1,1,1,1,1, 1313 1,1,1,1,1,1,1,1, 1314 1,1,1,1,1,1,1,1, 1315 1,1,1,1,1,1,1,1, 1316 1,1,1,1,1,1,1,1 }, 1317 0x1 /* 1 UC nodes, 1 MC node */}, 1318 /* SOC_TD2_NODE_LVL_L1 L1.7 */ 1319 { SOC_TD2_NODE_LVL_L1, 7, 1320 2, SOC_TD2_SCHED_MODE_WRR, 1321 { 1,1,1,1,1,1,1,1, 1322 1,1,1,1,1,1,1,1, 1323 1,1,1,1,1,1,1,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 0x1 /* 1 UC nodes, 1 MC node */}, 1328 /* SOC_TD2_NODE_LVL_L1 L1.8 */ 1329 { SOC_TD2_NODE_LVL_L1, 8, 1330 2, SOC_TD2_SCHED_MODE_WRR, 1331 { 1,1,1,1,1,1,1,1, 1332 1,1,1,1,1,1,1,1, 1333 1,1,1,1,1,1,1,1, 1334 1,1,1,1,1,1,1,1, 1335 1,1,1,1,1,1,1,1, 1336 1,1,1,1,1,1,1,1 }, 1337 0x1 /* 1 UC nodes, 1 MC node */}, 1338 /* SOC_TD2_NODE_LVL_L1 L1.7 */ 1339 { SOC_TD2_NODE_LVL_L1, 9, 1340 2, SOC_TD2_SCHED_MODE_WRR, 1341 { 1,1,1,1,1,1,1,1, 1342 1,1,1,1,1,1,1,1, 1343 1,1,1,1,1,1,1,1, 1344 1,1,1,1,1,1,1,1, 1345 1,1,1,1,1,1,1,1, 1346 1,1,1,1,1,1,1,1 }, 1347 0x1 /* 1 UC nodes, 1 MC node */}, 1348 /* SOC_TD2_NODE_LVL_L2 */ 1349 { -1, 0, 0, -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 1,1,1,1,1,1,1,1, 1354 1,1,1,1,1,1,1,1, 1355 1,1,1,1,1,1,1,1 }, 1356 1 } 1357 }; 1358 1359 static _soc_td2_lls_config_t _td2_lb_port_lls_config[] = { 1360 /* SOC_TD2_NODE_LVL_ROOT */ 1361 { SOC_TD2_NODE_LVL_ROOT, 0, 1362 1, SOC_TD2_SCHED_MODE_WRR, 1363 { 1,1,1,1,1,1,1,1, 1364 1,1,1,1,1,1,1,1, 1365 1,1,1,1,1,1,1,1, 1366 1,1,1,1,1,1,1,1, 1367 1,1,1,1,1,1,1,1, 1368 1,1,1,1,1,1,1,1 }, 1369 0}, 1370 /* SOC_TD2_NODE_LVL_L0 L0.0 */ 1371 { SOC_TD2_NODE_LVL_L0, 0, 1372 9, SOC_TD2_SCHED_MODE_WRR, 1373 { 1,1,1,1,1,1,1,1, 1374 1,1,1,1,1,1,1,1, 1375 1,1,1,1,1,1,1,1, 1376 1,1,1,1,1,1,1,1, 1377 1,1,1,1,1,1,1,1, 1378 1,1,1,1,1,1,1,1 }, 1379 0}, 1380 /* SOC_TD2_NODE_LVL_L1 L1.0 */ 1381 { SOC_TD2_NODE_LVL_L1, 0, 1382 1, SOC_TD2_SCHED_MODE_WRR, 1383 { 1,1,1,1,1,1,1,1, 1384 1,1,1,1,1,1,1,1, 1385 1,1,1,1,1,1,1,1, 1386 1,1,1,1,1,1,1,1, 1387 1,1,1,1,1,1,1,1, 1388 1,1,1,1,1,1,1,1 }, 1389 0 /* 1 MC node */}, 1390 /* SOC_TD2_NODE_LVL_L1 L1.1 */ 1391 { SOC_TD2_NODE_LVL_L1, 1, 1392 1, SOC_TD2_SCHED_MODE_WRR, 1393 { 1,1,1,1,1,1,1,1, 1394 1,1,1,1,1,1,1,1, 1395 1,1,1,1,1,1,1,1, 1396 1,1,1,1,1,1,1,1, 1397 1,1,1,1,1,1,1,1, 1398 1,1,1,1,1,1,1,1 }, 1399 0 /* 1 MC node */}, 1400 /* SOC_TD2_NODE_LVL_L1 L1.2 */ 1401 { SOC_TD2_NODE_LVL_L1, 2, 1402 1, SOC_TD2_SCHED_MODE_WRR, 1403 { 1,1,1,1,1,1,1,1, 1404 1,1,1,1,1,1,1,1, 1405 1,1,1,1,1,1,1,1, 1406 1,1,1,1,1,1,1,1, 1407 1,1,1,1,1,1,1,1, 1408 1,1,1,1,1,1,1,1 }, 1409 0 /* 1 MC node */}, 1410 /* SOC_TD2_NODE_LVL_L1 L1.3 */ 1411 { SOC_TD2_NODE_LVL_L1, 3, 1412 1, SOC_TD2_SCHED_MODE_WRR, 1413 { 1,1,1,1,1,1,1,1, 1414 1,1,1,1,1,1,1,1, 1415 1,1,1,1,1,1,1,1, 1416 1,1,1,1,1,1,1,1, 1417 1,1,1,1,1,1,1,1, 1418 1,1,1,1,1,1,1,1 }, 1419 0 /* 1 MC node */}, 1420 /* SOC_TD2_NODE_LVL_L1 L1.4 */ 1421 { SOC_TD2_NODE_LVL_L1, 4, 1422 1, SOC_TD2_SCHED_MODE_WRR, 1423 { 1,1,1,1,1,1,1,1, 1424 1,1,1,1,1,1,1,1, 1425 1,1,1,1,1,1,1,1, 1426 1,1,1,1,1,1,1,1, 1427 1,1,1,1,1,1,1,1, 1428 1,1,1,1,1,1,1,1 }, 1429 0 /* 1 MC node */}, 1430 /* SOC_TD2_NODE_LVL_L1 L1.5 */ 1431 { SOC_TD2_NODE_LVL_L1, 5, 1432 1, SOC_TD2_SCHED_MODE_WRR, 1433 { 1,1,1,1,1,1,1,1, 1434 1,1,1,1,1,1,1,1, 1435 1,1,1,1,1,1,1,1, 1436 1,1,1,1,1,1,1,1, 1437 1,1,1,1,1,1,1,1, 1438 1,1,1,1,1,1,1,1 }, 1439 0 /* 1 MC node */}, 1440 /* SOC_TD2_NODE_LVL_L1 L1.6 */ 1441 { SOC_TD2_NODE_LVL_L1, 6, 1442 1, SOC_TD2_SCHED_MODE_WRR, 1443 { 1,1,1,1,1,1,1,1, 1444 1,1,1,1,1,1,1,1, 1445 1,1,1,1,1,1,1,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 0 /* 1 MC node */}, 1450 /* SOC_TD2_NODE_LVL_L1 L1.7 */ 1451 { SOC_TD2_NODE_LVL_L1, 7, 1452 1, SOC_TD2_SCHED_MODE_WRR, 1453 { 1,1,1,1,1,1,1,1, 1454 1,1,1,1,1,1,1,1, 1455 1,1,1,1,1,1,1,1, 1456 1,1,1,1,1,1,1,1, 1457 1,1,1,1,1,1,1,1, 1458 1,1,1,1,1,1,1,1 }, 1459 0 /* 1 MC node */}, 1460 /* SOC_TD2_NODE_LVL_L1 L1.8 */ 1461 { SOC_TD2_NODE_LVL_L1, 8, 1462 1, SOC_TD2_SCHED_MODE_WRR, 1463 { 1,1,1,1,1,1,1,1, 1464 1,1,1,1,1,1,1,1, 1465 1,1,1,1,1,1,1,1, 1466 1,1,1,1,1,1,1,1, 1467 1,1,1,1,1,1,1,1, 1468 1,1,1,1,1,1,1,1 }, 1469 0 /* 1 QCN node */}, 1470 /* SOC_TD2_NODE_LVL_L2 */ 1471 { -1, 0, 0, -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 1,1,1,1,1,1,1,1, 1476 1,1,1,1,1,1,1,1, 1477 1,1,1,1,1,1,1,1 }, 1478 0 } 1479 }; 1480 1481 STATIC _soc_td2_lls_config_t * 1482 _soc_td2_get_config_for_level(_soc_td2_lls_config_t *cfg_tbl, int lvl, 1483 int offset) 1484 { 1485 _soc_td2_lls_config_t *en = cfg_tbl; 1486 1487 while (en->level != -1) { 1488 if ((en->level == lvl) && (en->node_id == offset)) { 1489 return en; 1490 } 1491 en++; 1492 } 1493 1494 return NULL; 1495 } 1496 1497 STATIC int 1498 _soc_td2_get_sched_count(int unit, soc_port_t port, 1499 _soc_td2_lls_config_t *cfgtbl, int lvl) 1500 { 1501 int cnt = 0; 1502 1503 while (_soc_td2_get_config_for_level(cfgtbl, lvl, cnt)) { 1504 cnt++; 1505 } 1506 return cnt; 1507 } 1508 1509 STATIC int 1510 _soc_td2_alloc_sched(int unit, soc_port_t in_port, soc_td2_node_lvl_e lvl, 1511 int offset, int *hw_index) 1512 { 1513 1514 int port, in_pipe, port_in_pipe, tlm = -1, cpu_tlm; 1515 int mmu_port, empty, base, max = -1, jj; 1516 soc_trident2_sched_type_t stype; 1517 uint32 sched_bmap[32]; 1518 int base_hsp = 0; 1519 1520 COMPILER_REFERENCE(base_hsp); 1521 1522 sal_memset(sched_bmap, 0, sizeof(uint32)*32); 1523 1524 SOC_IF_ERROR_RETURN( 1525 soc_td2_port_common_attributes_get(unit, in_port, &in_pipe, &mmu_port, NULL)); 1526 1527 stype = _soc_trident2_port_sched_type_get(unit, in_port); 1528 1529 if (lvl == SOC_TD2_NODE_LVL_ROOT) { 1530 tlm = 1; 1531 max = 106; 1532 } else if (lvl == SOC_TD2_NODE_LVL_L0) { 1533 tlm = 5; /* max 4 L0 under HSP */ 1534 max = 265; 1535 } else if (lvl == SOC_TD2_NODE_LVL_L1) { 1536 tlm = 10; 1537 max = 1024; 1538 } 1539 1540 if ((max < 0) || (tlm < 0)) { 1541 return SOC_E_PARAM; 1542 } 1543 1544 base = 0; 1545 cpu_tlm = _soc_td2_get_sched_count(unit, in_port, _td2_cpu_port_lls_config[unit], lvl); 1546 if (lvl == SOC_TD2_NODE_LVL_L0) { 1547 if (cpu_tlm < SOC_TD2_COSQ_NUM_CPU_L0_NODES(unit)) { 1548 cpu_tlm = SOC_TD2_COSQ_NUM_CPU_L0_NODES(unit); 1549 } 1550 } 1551 1552 if (stype == SOC_TD2_SCHED_HSP) { 1553 /* For HSP ports, the indexes of the scheduler and queues are fixed.*/ 1554 if (offset >= tlm) { 1555 return SOC_E_PARAM; 1556 } 1557 mmu_port += (mmu_port >= 64) ? -64 : 0; 1558 *hw_index = (mmu_port * tlm) + offset; 1559 return SOC_E_NONE; 1560 } else { 1561 /* reserve all the scheduler and queus that are prefixed for hsp. */ 1562 PBMP_ALL_ITER(unit, port) { 1563 SOC_IF_ERROR_RETURN(soc_td2_port_common_attributes_get(unit, port, 1564 &port_in_pipe, &mmu_port, NULL)); 1565 if (in_pipe != port_in_pipe) { 1566 continue; 1567 } 1568 1569 if (_soc_trident2_port_sched_type_get(unit, port) == SOC_TD2_SCHED_HSP) { 1570 mmu_port += (mmu_port >= 64) ? -64 : 0; 1571 base = mmu_port * tlm; 1572 for (jj = 0; jj < tlm; jj++) { 1573 sched_bmap[(base + jj)/32] |= 1 << ((base + jj) % 32); 1574 } 1575 if (base + tlm > base_hsp) { 1576 base_hsp = base + tlm; 1577 } 1578 } 1579 } 1580 1581 if (lvl == SOC_TD2_NODE_LVL_L0) { 1582 base = SOC_TD2_COSQ_CPU_RESERVED_L0_BASE(unit); 1583 if (IS_CPU_PORT(unit, in_port)) { 1584 if (offset >= cpu_tlm) { 1585 return SOC_E_PARAM; 1586 } 1587 base += offset; 1588 sched_bmap[base/32] |= 1 << (base % 32); 1589 *hw_index = base; 1590 return SOC_E_NONE; 1591 } else { 1592 /* reserve the CPU L0 nodes */ 1593 for (jj = 0; jj < cpu_tlm; jj++) { 1594 sched_bmap[(base + jj)/32] |= 1 << ((base + jj) % 32); 1595 } 1596 } 1597 base = INVALID_PARENT(unit, lvl); 1598 if (base == 0) { 1599 base = 53; 1600 } 1601 sched_bmap[base/32] |= (1 << (base % 32)); 1602 } else { 1603 base = INVALID_PARENT(unit, lvl); 1604 sched_bmap[base/32] |= (1 << (base % 32)); 1605 } 1606 1607 cpu_tlm = (cpu_tlm + 3) & ~3; 1608 1609 base = 0; 1610 PBMP_ALL_ITER(unit, port) { 1611 SOC_IF_ERROR_RETURN( 1612 soc_td2_port_common_attributes_get(unit, port, 1613 &port_in_pipe, &mmu_port, NULL)); 1614 if ((in_pipe != port_in_pipe) || 1615 (_soc_trident2_port_sched_type_get(unit, port) == SOC_TD2_SCHED_HSP)) { 1616 continue; 1617 } 1618 1619 tlm = _soc_td2_get_sched_count(unit, port, 1620 ((IS_CPU_PORT(unit, port)) ? _td2_cpu_port_lls_config[unit] : 1621 _td2_port_lls_config), lvl); 1622 tlm = (tlm + 3) & ~3; 1623 1624 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 1625 if (SOC_IS_TD2P_TT2P(unit)) { 1626 if (lvl == SOC_TD2_NODE_LVL_L1) { 1627 if (IS_CPU_PORT(unit, in_port)) { 1628 if (offset >= cpu_tlm) { 1629 return SOC_E_PARAM; 1630 } 1631 base = base_hsp; 1632 base += offset; 1633 sched_bmap[base/32] |= 1 << (base % 32); 1634 *hw_index = base; 1635 return SOC_E_NONE; 1636 } 1637 } 1638 1639 mmu_port += (mmu_port >= 64) ? -64 : 0; 1640 if (lvl == SOC_TD2_NODE_LVL_L1) { 1641 base = cpu_tlm + (mmu_port * tlm); 1642 } else { 1643 base = mmu_port * tlm; 1644 } 1645 if (base >= max) { 1646 return SOC_E_RESOURCE; 1647 } 1648 if (port == in_port) { 1649 if (offset >= tlm) { 1650 return SOC_E_PARAM; 1651 } 1652 *hw_index = base + offset; 1653 return SOC_E_NONE; 1654 } else { 1655 for(jj = 0; jj < tlm; jj++) { 1656 sched_bmap[base/32] |= 1 << (base % 32); 1657 base += 1; 1658 } 1659 } 1660 } else 1661 #endif 1662 { 1663 /* step to empty resources start. */ 1664 empty = 0; 1665 while (base < max) { 1666 if ((sched_bmap[base/32] & (1 << (base % 32))) == 0) { 1667 empty += 1; 1668 } else { 1669 empty = 0; 1670 } 1671 1672 base += 1; 1673 if (empty == tlm) { 1674 base -= tlm; 1675 break; 1676 } 1677 } 1678 1679 if (base == max) { 1680 return SOC_E_RESOURCE; 1681 } 1682 1683 if (port == in_port) { 1684 if (offset >= tlm) { 1685 return SOC_E_PARAM; 1686 } 1687 *hw_index = base + offset; 1688 return SOC_E_NONE; 1689 } else { 1690 for(jj = 0; jj < tlm; jj++) { 1691 sched_bmap[base/32] |= 1 << (base % 32); 1692 base += 1; 1693 } 1694 } 1695 } 1696 } 1697 } 1698 1699 return SOC_E_RESOURCE; 1700 } 1701 1702 int soc_td2_l2_hw_index(int unit, int qnum, int uc) 1703 { 1704 if (uc) { 1705 qnum -= (qnum >= 1480) ? 1480 : 0; 1706 } else { 1707 qnum -= (qnum >= 568) ? 568 : 0; 1708 qnum += 1480; 1709 } 1710 return qnum; 1711 } 1712 1713 /* 1714 * Function: 1715 * soc_td2_hw_index_logical_num 1716 * Purpose: 1717 * Get the logical queue number according to hw index 1718 * Parameters: 1719 * unit - (IN) unit number 1720 * port - (IN) local port number 1721 * index -(IN) The index of Queue management related memory Tables 1722 * uc - (IN) unicast indicator 1723 * Returns: 1724 * logical queue number: queue number in logical view 1725 * In logical view, 1726 * the range of unicast queue number is: pipeX[0,1480),pipeY[1480,2960) 1727 * the range of multicast queue number is: pipeX[0,568),pipeY[568,1136) 1728 */ 1729 int 1730 soc_td2_hw_index_logical_num(int unit,int port,int index,int uc) 1731 { 1732 int qnum; 1733 uint32 pipe = SOC_TD2_PORT_PIPE(unit, port); 1734 if (uc) { 1735 qnum = index + ( pipe ? 1480 : 0); 1736 } else { 1737 qnum = index - 1480; 1738 qnum += pipe ? 568 : 0; 1739 } 1740 1741 return qnum; 1742 } 1743 1744 STATIC int 1745 soc_td2_port_lls_init(int unit, int port, _soc_td2_lls_config_t *cfg_tbl, 1746 int setup, _soc_td2_lls_traverse_cb cb, void *cookie) 1747 { 1748 _soc_td2_lls_config_t *pinfo, *cinfo; 1749 struct _td2_sched_pending_setup_s { 1750 int parent; 1751 int level; 1752 int offset; 1753 int hw_index; 1754 int l2_uc; 1755 } pending_list[64], *ppending; 1756 int list_size, lindex, child_lvl = 0, uc; 1757 int l2_lvl_offsets[2], rc, numq; 1758 int spri, smcpri, num_spri, qnum, self_hw_index, c; 1759 uint32 ucmap, rval; 1760 int pipe, mmu_port; 1761 int num_children, lvl_offsets[4]; 1762 int sp_vec = soc_feature(unit, soc_feature_vector_based_spri); 1763 1764 1765 /* If the dynamic switchover feature is enabled, we need to enable the 1766 spri_vect_mode by setting spri_vect_mode_enable in LLS_CONFIG0 reg */ 1767 if (sp_vec) { 1768 1769 SOC_IF_ERROR_RETURN(READ_ES_PIPE0_LLS_CONFIG0r(unit, &rval)); 1770 if (!soc_reg_field_get(unit, ES_PIPE0_LLS_CONFIG0r, rval, 1771 SPRI_VECT_MODE_ENABLEf)) { 1772 soc_reg_field_set(unit, ES_PIPE0_LLS_CONFIG0r, &rval, 1773 SPRI_VECT_MODE_ENABLEf, 1); 1774 SOC_IF_ERROR_RETURN(WRITE_ES_PIPE0_LLS_CONFIG0r(unit, rval)); 1775 SOC_IF_ERROR_RETURN(WRITE_ES_PIPE1_LLS_CONFIG0r(unit, rval)); 1776 } 1777 } 1778 1779 l2_lvl_offsets[0] = l2_lvl_offsets[1] = 0; 1780 lvl_offsets[0] = lvl_offsets[1] = lvl_offsets[2] = lvl_offsets[3] = 0; 1781 1782 SOC_IF_ERROR_RETURN( 1783 soc_td2_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL)); 1784 1785 /* setup port scheduler */ 1786 pending_list[0].parent = -1; 1787 pending_list[0].level = SOC_TD2_NODE_LVL_ROOT; 1788 pending_list[0].offset = 0; 1789 pending_list[0].hw_index = (pipe) ? mmu_port - 64 : mmu_port; 1790 1791 list_size = 1; 1792 lindex = 0; 1793 do { 1794 ppending = &pending_list[lindex++]; 1795 self_hw_index = ppending->hw_index; 1796 /* If we are just traversing the LLS heirarchy, just call the callback 1797 function, which is passed as an argument to this func */ 1798 if (setup == _SOC_TD2_LLS_OP_TRAVERSE) { 1799 if (cb != NULL) { 1800 cb(unit, port, ppending->level, ppending->hw_index, cookie); 1801 } 1802 } else if (ppending->parent != -1) { 1803 /* attach to parent */ 1804 SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_parent(unit, port, 1805 ppending->level, self_hw_index, 1806 (setup) ? ppending->parent : INVALID_PARENT(unit, ppending->level))); 1807 } 1808 1809 if (ppending->level == SOC_TD2_NODE_LVL_L2) { 1810 continue; 1811 } 1812 1813 pinfo = _soc_td2_get_config_for_level(cfg_tbl, 1814 ppending->level, 1815 ppending->offset); 1816 if (!pinfo) { 1817 return SOC_E_INTERNAL; 1818 } 1819 1820 soc_td2_get_child_type(unit, port, ppending->level, &child_lvl); 1821 ucmap = 0; 1822 spri = -1; 1823 smcpri = -1; 1824 num_spri = 0; 1825 1826 num_children = pinfo->num_children; 1827 1828 for (c = 0; c < num_children; c++) { 1829 pending_list[list_size].parent = self_hw_index; 1830 pending_list[list_size].level = child_lvl; 1831 pending_list[list_size].offset = lvl_offsets[child_lvl]; 1832 lvl_offsets[child_lvl] += 1; 1833 if (child_lvl == SOC_TD2_NODE_LVL_L2) { 1834 uc = 0; /* default MC queue */ 1835 if (!IS_CPU_PORT(unit, port) && !IS_LB_PORT(unit,port)) { 1836 uc = (pinfo->uc_mc_map & (1 << c)) ? 1 : 0; 1837 } 1838 1839 rc = soc_td2_get_def_qbase(unit, port, 1840 (uc ? _SOC_TD2_INDEX_STYLE_UCAST_QUEUE : 1841 _SOC_TD2_INDEX_STYLE_MCAST_QUEUE), &qnum, &numq); 1842 1843 if (rc) { 1844 return rc; 1845 } 1846 1847 if ((numq == 0) || (qnum < 0) || l2_lvl_offsets[uc] >= numq) { 1848 continue; 1849 } 1850 qnum = soc_td2_l2_hw_index(unit, qnum, uc); 1851 pending_list[list_size].hw_index = qnum + l2_lvl_offsets[uc]; 1852 l2_lvl_offsets[uc]++; 1853 if (uc) { 1854 if (spri == -1) { 1855 spri = pending_list[list_size].hw_index; 1856 } 1857 } else { 1858 if (smcpri == -1) { 1859 smcpri = pending_list[list_size].hw_index; 1860 } 1861 } 1862 if ((pinfo->sched_mode == SOC_TD2_SCHED_MODE_STRICT) && 1863 (!IS_CPU_PORT(unit, port))) { 1864 ucmap |= (uc) ? 0 : (1 << c); 1865 num_spri++; 1866 } 1867 /* if we are traversing the LLS, there is no need to set 1868 the scheduler parent and mode as it is to be done only 1869 during the init */ 1870 if (setup == _SOC_TD2_LLS_OP_TRAVERSE) { 1871 list_size++; 1872 } else { 1873 SOC_IF_ERROR_RETURN( 1874 soc_td2_cosq_set_sched_parent(unit, port, 1875 SOC_TD2_NODE_LVL_L2, 1876 pending_list[list_size].hw_index, 1877 self_hw_index)); 1878 1879 SOC_IF_ERROR_RETURN( 1880 soc_td2_cosq_set_sched_mode(unit, port, SOC_TD2_NODE_LVL_L2, 1881 pending_list[list_size].hw_index, 1882 pinfo->sched_mode, pinfo->weights[c])); 1883 } 1884 1885 } else { 1886 cinfo = _soc_td2_get_config_for_level(cfg_tbl, child_lvl, 1887 pending_list[list_size].offset); 1888 if (!cinfo) { 1889 return SOC_E_INTERNAL; 1890 } 1891 if (soc_td2_sched_hw_index_get(unit, port, child_lvl, 1892 pending_list[list_size].offset, 1893 &pending_list[list_size].hw_index)) { 1894 return SOC_E_INTERNAL; 1895 } 1896 if (spri == -1) { 1897 spri = pending_list[list_size].hw_index; 1898 } 1899 if (cinfo->sched_mode == SOC_TD2_SCHED_MODE_STRICT) { 1900 num_spri++; 1901 } 1902 /* if we are traversing the LLS, there is no need to set 1903 the scheduler parent and mode as it is to be done only 1904 during the init */ 1905 if (setup != _SOC_TD2_LLS_OP_TRAVERSE) { 1906 SOC_IF_ERROR_RETURN( 1907 soc_td2_cosq_set_sched_parent(unit, port, child_lvl, 1908 pending_list[list_size].hw_index, 1909 self_hw_index)); 1910 1911 SOC_IF_ERROR_RETURN( 1912 soc_td2_cosq_set_sched_mode(unit, port, child_lvl, 1913 pending_list[list_size].hw_index, 1914 cinfo->sched_mode, pinfo->weights[c])); 1915 } 1916 list_size++; 1917 } 1918 } 1919 1920 if (spri == -1) { 1921 spri = 0; 1922 } 1923 if (smcpri == -1) { 1924 smcpri = 1480; 1925 } 1926 /* if we are NOT traversing the LLS, we need to set the scheduler 1927 configuration for the child */ 1928 if (setup != _SOC_TD2_LLS_OP_TRAVERSE) { 1929 SOC_IF_ERROR_RETURN( 1930 soc_td2_cosq_set_sched_child_config(unit, port, 1931 ppending->level, self_hw_index, 1932 num_spri, spri, smcpri, ucmap, 0)); 1933 } 1934 } while (lindex < list_size); 1935 1936 return SOC_E_NONE; 1937 } 1938 1939 /* 1940 * Function: 1941 * soc_td2_hsp_sp_node_init 1942 * Purpose: 1943 * This function initialises ENABLE_SP_IN_MIN setting in 1944 * HSP_SCHED_Lx_NODE_CONFIG. 1945 * Hardware default value for sched mode is SP. SP nodes 1946 * with min bandwidth set may be scheduled in WRR manner. 1947 * To schedule SP nodes with strict priority, ENABLE_SP_IN_MIN 1948 * must be set. 1949 * Parameters: 1950 * unit - (IN) unit number 1951 * port - (IN) local port number 1952 * Returns: 1953 * SOC_E_XXX 1954 */ 1955 int 1956 soc_td2_hsp_sp_node_init(int unit, soc_port_t port) 1957 { 1958 uint32 index, rval, fval; 1959 soc_reg_t regs[4] = { 1960 HSP_SCHED_L0_NODE_CONFIGr, 1961 HSP_SCHED_L1_NODE_CONFIGr, 1962 HSP_SCHED_L2_UC_QUEUE_CONFIGr, 1963 HSP_SCHED_L2_MC_QUEUE_CONFIGr 1964 }; 1965 1966 for (index = 0; index < COUNTOF(regs); index++) { 1967 if (regs[index] == HSP_SCHED_L0_NODE_CONFIGr) { 1968 fval = 0x1f; 1969 } else { 1970 fval = 0x3ff; 1971 } 1972 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, regs[index], port, 0, &rval)); 1973 soc_reg_field_set(unit, regs[index], &rval, ENABLE_SP_IN_MINf, fval); 1974 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, regs[index], port, 0, rval)); 1975 } 1976 1977 return SOC_E_NONE; 1978 } 1979 1980 #define TD2_DFL_HSP_SCHED_MODE SOC_TD2_SCHED_MODE_WDRR 1981 1982 STATIC int 1983 soc_td2_setup_hsp_port(int unit, int port) 1984 { 1985 uint32 rval, fval = 0, pbmf; 1986 int mmu_port, pipe, l0_index, l1_index, l0_1, l0_4, hw_index; 1987 int hsp_port_index; 1988 1989 SOC_IF_ERROR_RETURN( 1990 soc_td2_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL)); 1991 1992 rval = 0; 1993 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_PORT_CONFIGr(unit, port, rval)); 1994 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L0_NODE_CONFIGr(unit, port, rval)); 1995 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L1_NODE_CONFIGr(unit, port, rval)); 1996 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_L2_UC_QUEUE_CONFIGr(unit, port, rval)); 1997 1998 SOC_IF_ERROR_RETURN(soc_td2_hsp_sp_node_init(unit, port)); 1999 2000 l0_1 = 0; 2001 l0_4 = 0; 2002 for (l0_index = 0; l0_index < 5; l0_index++) { 2003 SOC_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, port, 2004 SOC_TD2_NODE_LVL_L0, l0_index, &hw_index)); 2005 SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_parent(unit, port, 2006 SOC_TD2_NODE_LVL_L0, hw_index, mmu_port)); 2007 2008 if (l0_index == 1) { 2009 l0_1 = hw_index; 2010 } else if (l0_index == 4) { 2011 l0_4 = hw_index; 2012 } 2013 } 2014 2015 for (l1_index = 0; l1_index < 10; l1_index++) { 2016 SOC_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, port, 2017 SOC_TD2_NODE_LVL_L1, l1_index, &hw_index)); 2018 2019 SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_parent(unit, port, 2020 SOC_TD2_NODE_LVL_L1, hw_index, (l1_index < 8) ? l0_1 : l0_4)); 2021 2022 SOC_IF_ERROR_RETURN(soc_td2_cosq_set_sched_mode(unit, port, 2023 SOC_TD2_NODE_LVL_L1, l1_index, SOC_TD2_SCHED_MODE_WDRR, 1)); 2024 } 2025 2026 pbmf = pipe ? IS_HSP_PORT_IN_YPIPEf : IS_HSP_PORT_IN_XPIPEf; 2027 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval)); 2028 fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, pbmf); 2029 hsp_port_index = mmu_port - pipe * _TD2_PORTS_PER_PIPE; 2030 fval |= (1 << hsp_port_index); 2031 soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, pbmf, fval); 2032 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval)); 2033 return SOC_E_NONE; 2034 } 2035 2036 STATIC int 2037 soc_td2_reset_hsp_port(int unit, int port) 2038 { 2039 int l1_index, hw_index; 2040 2041 for (l1_index = 0; l1_index < _TD2_HSP_PORT_MAX_L1; l1_index++) { 2042 SOC_IF_ERROR_RETURN( 2043 soc_td2_sched_hw_index_get(unit, port, SOC_TD2_NODE_LVL_L1, 2044 l1_index, &hw_index)); 2045 2046 SOC_IF_ERROR_RETURN( 2047 soc_td2_cosq_set_sched_parent( 2048 unit, port, SOC_TD2_NODE_LVL_L1, hw_index, 2049 INVALID_PARENT(unit, SOC_TD2_NODE_LVL_L1))); 2050 } 2051 2052 return SOC_E_NONE; 2053 } 2054 2055 STATIC int 2056 soc_td2_cpu_port_lls_init(int unit, int port, int setup, int reserve, 2057 _soc_td2_lls_traverse_cb cb, void *cookie) 2058 2059 { 2060 int num_l0, num_l1, l0_0, l0_1, l0_2, num_nodes, w, ii, jj; 2061 int l1_cnt[3], l2_cnt[3], nc, cmc; 2062 _soc_td2_lls_config_t *lnc, *pnode; 2063 int max_q = 48, l1off; 2064 2065 if (_td2_cpu_port_lls_config[unit] != NULL) { 2066 sal_free(_td2_cpu_port_lls_config[unit]); 2067 _td2_cpu_port_lls_config[unit] = NULL; 2068 } 2069 2070 max_q = (reserve==0) ? 48 : 48 - SOC_TD2_COSQ_CPU_RESERVED_L0_NUM(unit); 2071 2072 /* alloc structure to hold lls node data, init it and kick off 2073 * soc_td2_port_lls_init */ 2074 2075 l2_cnt[1] = l0_1 = NUM_CPU_ARM_COSQ(unit, SOC_ARM_CMC(unit, 0)); 2076 l2_cnt[2] = l0_2 = NUM_CPU_ARM_COSQ(unit, SOC_ARM_CMC(unit, 1)); 2077 l2_cnt[0] = l0_0 = max_q - (l0_1 + l0_2); 2078 2079 if (l0_0 <= 0) { 2080 return SOC_E_PARAM; 2081 } 2082 2083 num_l0 = 1 + (l0_1 > 0 ? 1 : 0) + (l0_2 > 0 ? 1 : 0); 2084 2085 /* keep a max of 8 nodes under each l1. */ 2086 l1_cnt[0] = l1_cnt[1] = l1_cnt[2] = 0; 2087 2088 l1_cnt[0] = (l0_0 + 7)/8; 2089 l1_cnt[1] = (l0_1 + 7)/8; 2090 l1_cnt[2] = (l0_2 + 7)/8; 2091 2092 num_l1 = l1_cnt[0] + l1_cnt[1] + l1_cnt[2]; 2093 2094 num_nodes = 1 /* root */ + num_l0 + num_l1 + 1 /* null last node */; 2095 2096 for (cmc = 0, ii = 0; cmc < 3; cmc++) { 2097 SHR_BITCLR_RANGE(CPU_ARM_QUEUE_BITMAP(unit, cmc), 0, 48); 2098 SHR_BITCLR_RANGE(CPU_ARM_RSVD_QUEUE_BITMAP(unit, cmc), 0, 48); 2099 for (jj = 0; jj < l2_cnt[cmc]; jj++, ii++) { 2100 SHR_BITSET(CPU_ARM_QUEUE_BITMAP(unit, cmc), ii); 2101 } 2102 NUM_CPU_ARM_COSQ(unit, cmc) = l2_cnt[cmc]; 2103 } 2104 2105 if (SOC_IS_TD2P_TT2P(unit)) { 2106 /* TBD COSQ. The following should be chaneged after full solution for new queues */ 2107 /* CPU is L0.0 - bit 58 */ 2108 /* ARM0 is L0.1 - bit 59 */ 2109 /* ARM1 is L0.2 - bit 60 */ 2110 SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, 0), 58); 2111 if (l2_cnt[1]) { 2112 SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, 1), 59); 2113 } 2114 if (l2_cnt[2]) { 2115 SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, 2), 60); 2116 } 2117 } else { 2118 for (ii = max_q; ii < 48; ii++) { 2119 cmc = ii - max_q; 2120 if (l1_cnt[cmc] > 0) { 2121 SHR_BITSET(CPU_ARM_RSVD_QUEUE_BITMAP(unit, cmc), ii); 2122 } 2123 } 2124 } 2125 2126 lnc = sal_alloc(sizeof(_soc_td2_lls_config_t)*num_nodes, "CPU LLS config"); 2127 if (lnc == NULL) { 2128 /* No rollback needed */ 2129 return SOC_E_MEMORY; 2130 } 2131 2132 /* init root */ 2133 pnode = lnc; 2134 pnode->level = SOC_TD2_NODE_LVL_ROOT; 2135 pnode->node_id = 0; 2136 pnode->sched_mode = SOC_TD2_SCHED_MODE_WRR; 2137 pnode->num_children = num_l0; 2138 pnode->uc_mc_map = 0; 2139 for (w = 0; w < 48; w++) { 2140 pnode->weights[w] = 1; 2141 } 2142 2143 pnode++; 2144 l1off = 0; 2145 2146 for (ii = 0; ii < num_l0; ii++) { 2147 pnode->level = SOC_TD2_NODE_LVL_L0; 2148 pnode->node_id = ii; 2149 pnode->num_children = l1_cnt[ii]; 2150 pnode->sched_mode = SOC_TD2_SCHED_MODE_WRR; 2151 pnode->uc_mc_map = 0; 2152 for (w = 0; w < 48; w++) { 2153 pnode->weights[w] = 1; 2154 } 2155 pnode++; 2156 2157 for (nc = 0, jj = 0; jj < l1_cnt[ii]; jj++) { 2158 pnode->level = SOC_TD2_NODE_LVL_L1; 2159 pnode->node_id = l1off++; 2160 2161 if ((l2_cnt[ii] - nc) >= 8) { 2162 pnode->num_children = 8; 2163 } else { 2164 pnode->num_children = l2_cnt[ii] - nc; 2165 } 2166 2167 nc += pnode->num_children; 2168 2169 pnode->sched_mode = SOC_TD2_SCHED_MODE_WRR; 2170 pnode->uc_mc_map = 0; 2171 for (w = 0; w < 48; w++) { 2172 pnode->weights[w] = 1; 2173 } 2174 pnode++; 2175 } 2176 } 2177 2178 /* null node */ 2179 pnode->level = -1; 2180 pnode->node_id = -1; 2181 pnode->num_children = 0; 2182 pnode->uc_mc_map = 0; 2183 2184 _td2_cpu_port_lls_config[unit] = lnc; 2185 2186 SOC_IF_ERROR_RETURN(soc_td2_port_lls_init(unit, port, 2187 _td2_cpu_port_lls_config[unit], setup, 2188 cb, cookie)); 2189 return 0; 2190 } 2191 2192 int soc_td2_lls_reset(int unit) 2193 { 2194 int port, lvl, i; 2195 uint32 clrmap = 0, pipe; 2196 soc_info_t *si; 2197 int phy_port, mmu_port, index; 2198 soc_mem_t mem; 2199 uint32 entry[SOC_MAX_MEM_WORDS]; 2200 uint32 *bmap = NULL; 2201 int alloc_size; 2202 2203 si = &SOC_INFO(unit); 2204 2205 PBMP_ALL_ITER(unit, port) { 2206 pipe = SOC_TD2_PORT_PIPE(unit, port); 2207 for (lvl = SOC_TD2_NODE_LVL_L0; lvl <= SOC_TD2_NODE_LVL_L2; lvl++) { 2208 mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, lvl); 2209 /* coverity[negative_returns : FALSE] */ 2210 alloc_size = SHR_BITALLOCSIZE(soc_mem_index_count(unit, mem)); 2211 if (lvl == SOC_TD2_NODE_LVL_L0) { 2212 if (SOC_CONTROL(unit)->port_lls_l0_bmap[port] == NULL) { 2213 SOC_CONTROL(unit)->port_lls_l0_bmap[port] = 2214 sal_alloc(alloc_size, "LLS_L0_BMAP"); 2215 } 2216 bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 2217 } else if (lvl == SOC_TD2_NODE_LVL_L1) { 2218 if (SOC_CONTROL(unit)->port_lls_l1_bmap[port] == NULL) { 2219 SOC_CONTROL(unit)->port_lls_l1_bmap[port] = 2220 sal_alloc(alloc_size, "LLS_L1_BMAP"); 2221 } 2222 bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 2223 } else if (lvl == SOC_TD2_NODE_LVL_L2) { 2224 if (SOC_CONTROL(unit)->port_lls_l2_bmap[port] == NULL) { 2225 SOC_CONTROL(unit)->port_lls_l2_bmap[port] = 2226 sal_alloc(alloc_size, "LLS_L2_BMAP"); 2227 } 2228 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 2229 } 2230 2231 sal_memset(bmap, 0, alloc_size); 2232 2233 if ((clrmap & (1 << (pipe * SOC_TD2_NODE_LVL_MAX + lvl))) == 0) { 2234 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 2235 soc_mem_field32_set(unit, mem, entry, C_PARENTf, INVALID_PARENT(unit, lvl)); 2236 2237 for (i = 0; i <= soc_mem_index_max(unit, mem); i++) { 2238 SOC_IF_ERROR_RETURN 2239 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, &entry)); 2240 } 2241 clrmap |= (1 << (pipe * SOC_TD2_NODE_LVL_MAX + lvl)); 2242 } 2243 } 2244 2245 if (SOC_PBMP_MEMBER(si->eq_pbm, port)) { /* VBS (HSP) port */ 2246 phy_port = si->port_l2p_mapping[port]; 2247 mmu_port = si->port_p2m_mapping[phy_port]; 2248 for (index = 0; index < 5; index++) { 2249 SHR_BITSET(SOC_CONTROL(unit)->port_lls_l0_bmap[port], 2250 (mmu_port & 0x3f) * 5 + index); 2251 } 2252 for (index = 0; index < 10; index++) { 2253 SHR_BITSET(SOC_CONTROL(unit)->port_lls_l1_bmap[port], 2254 (mmu_port & 0x3f) * 10 + index); 2255 } 2256 for (index = 0; index < 10; index++) { 2257 SHR_BITSET(SOC_CONTROL(unit)->port_lls_l2_bmap[port], 2258 (mmu_port & 0x3f) * 10 + index); 2259 } 2260 } 2261 } 2262 2263 return 0; 2264 } 2265 2266 int soc_td2_lls_reset_port(int unit, int port) 2267 { 2268 int lvl; 2269 soc_mem_t mem; 2270 uint32 *bmap = NULL; 2271 int alloc_size; 2272 2273 for (lvl = SOC_TD2_NODE_LVL_L0; lvl <= SOC_TD2_NODE_LVL_L2; lvl++) { 2274 mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, lvl); 2275 alloc_size = SHR_BITALLOCSIZE(soc_mem_index_count(unit, mem)); 2276 if (lvl == SOC_TD2_NODE_LVL_L0) { 2277 if (SOC_CONTROL(unit)->port_lls_l0_bmap[port] == NULL) { 2278 SOC_CONTROL(unit)->port_lls_l0_bmap[port] = 2279 sal_alloc(alloc_size, "LLS_L0_BMAP"); 2280 } 2281 bmap = SOC_CONTROL(unit)->port_lls_l0_bmap[port]; 2282 } else if (lvl == SOC_TD2_NODE_LVL_L1) { 2283 if (SOC_CONTROL(unit)->port_lls_l1_bmap[port] == NULL) { 2284 SOC_CONTROL(unit)->port_lls_l1_bmap[port] = 2285 sal_alloc(alloc_size, "LLS_L1_BMAP"); 2286 } 2287 bmap = SOC_CONTROL(unit)->port_lls_l1_bmap[port]; 2288 } else if (lvl == SOC_TD2_NODE_LVL_L2) { 2289 if (SOC_CONTROL(unit)->port_lls_l2_bmap[port] == NULL) { 2290 SOC_CONTROL(unit)->port_lls_l2_bmap[port] = 2291 sal_alloc(alloc_size, "LLS_L2_BMAP"); 2292 } 2293 bmap = SOC_CONTROL(unit)->port_lls_l2_bmap[port]; 2294 } 2295 2296 sal_memset(bmap, 0, alloc_size); 2297 } 2298 2299 return 0; 2300 } 2301 2302 /* 2303 * Function: 2304 * _soc_td2plus_lls_init 2305 * Purpose: 2306 * This function initialises the structure _td2p_dyn_sched_unit_data, which is 2307 * used later to allocate the register available from the set of 2308 * SP_WERR_DYN_CHANGEnA/nB/nC (n=0,1,2,3) to the port and to keep track 2309 * of the used registers from the set for the port 2310 * Parameters: 2311 * unit - (IN) unit number 2312 * Returns: 2313 * SOC_E_XXX 2314 */ 2315 STATIC int _soc_td2plus_lls_init(int unit) 2316 { 2317 _soc_td2p_port_dyn_sched_t *pcb = NULL; 2318 int i; 2319 2320 if (soc_feature(unit, soc_feature_vector_based_spri)) { 2321 pcb = &_td2p_dyn_sched_unit_data[unit]; 2322 2323 if (pcb->_soc_td2plus_init_done[unit] == 1) { 2324 return SOC_E_NONE; 2325 } 2326 2327 pcb->lock = sal_mutex_create("td2plus_dyn_lock"); 2328 for (i = 0; i < _SOC_TD2PLUS_DYN_REGISTER_SET; i++) { 2329 pcb->port[i] = -1; 2330 } 2331 pcb->_soc_td2plus_init_done[unit] = 1; 2332 } 2333 2334 return SOC_E_NONE; 2335 } 2336 2337 int soc_td2_lls_init(int unit) 2338 { 2339 int port, rv = SOC_E_NONE, reserve_queues, pipe; 2340 soc_trident2_sched_type_t sched_type; 2341 uint32 entry[SOC_MAX_MEM_WORDS]; 2342 uint32 rval; 2343 soc_reg_t reg; 2344 _soc_td2p_lls_op_mode_t op_mode; 2345 2346 static const soc_reg_t llfc_cfgr[] = { 2347 ES_PIPE0_LLS_FC_CONFIGr, ES_PIPE1_LLS_FC_CONFIGr }; 2348 2349 reserve_queues = soc_feature(unit, soc_feature_cmic_reserved_queues); 2350 2351 SOC_IF_ERROR_RETURN(_soc_td2plus_lls_init(unit)); 2352 2353 /* do dummy read from L0 parent mem per TD2-3313. */ 2354 SOC_IF_ERROR_RETURN(soc_mem_read(unit, ES_PIPE0_LLS_L0_PARENTm, MEM_BLOCK_ALL, 0, &entry)); 2355 SOC_IF_ERROR_RETURN(soc_mem_read(unit, ES_PIPE1_LLS_L0_PARENTm, MEM_BLOCK_ALL, 0, &entry)); 2356 2357 SOC_IF_ERROR_RETURN(soc_td2_init_invalid_pointers(unit)); 2358 2359 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, 0)); 2360 2361 SOC_IF_ERROR_RETURN(soc_td2_lls_reset(unit)); 2362 2363 PBMP_ALL_ITER(unit, port) { 2364 sched_type = _soc_trident2_port_sched_type_get(unit, port); 2365 2366 if (sched_type == SOC_TD2_SCHED_HSP) { 2367 rv = soc_td2_setup_hsp_port(unit, port); 2368 if (soc_td2_is_skip_default_lls_creation(unit)) { 2369 SOC_IF_ERROR_RETURN( 2370 soc_td2_port_mmu_tx_enable_set(unit, port, 1)); 2371 } 2372 } else if (IS_CPU_PORT(unit, port)) { 2373 op_mode = _SOC_TD2_LLS_OP_SETUP; 2374 rv = soc_td2_cpu_port_lls_init(unit, port, op_mode, reserve_queues, NULL, NULL); 2375 } else if (IS_LB_PORT(unit, port)) { 2376 if (!soc_td2_is_skip_default_lls_creation(unit)) { 2377 op_mode = _SOC_TD2_LLS_OP_SETUP; 2378 rv = soc_td2_port_lls_init(unit, port, _td2_lb_port_lls_config, op_mode, NULL, NULL); 2379 } 2380 } else { 2381 if (!soc_td2_is_skip_default_lls_creation(unit)) { 2382 op_mode = _SOC_TD2_LLS_OP_SETUP; 2383 rv = soc_td2_port_lls_init(unit, port, _td2_port_lls_config, op_mode, NULL, NULL); 2384 } else { 2385 SOC_IF_ERROR_RETURN( 2386 soc_td2_port_mmu_tx_enable_set(unit, port, 0)); 2387 SOC_IF_ERROR_RETURN( 2388 soc_td2_mmu_rx_enable_set(unit, port, 0)); 2389 } 2390 } 2391 if (rv) { 2392 return SOC_E_INTERNAL; 2393 } 2394 } 2395 2396 for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) { 2397 reg = llfc_cfgr[pipe]; 2398 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2399 soc_reg_field_set(unit, reg, &rval, FC_CFG_DISABLE_XOFFf, 0); 2400 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 2401 } 2402 2403 return SOC_E_NONE; 2404 } 2405 2406 int soc_td2_lls_port_uninit(int unit, soc_port_t port) 2407 { 2408 soc_trident2_sched_type_t sched_type; 2409 int rv = SOC_E_NONE; 2410 _soc_td2p_lls_op_mode_t op_mode; 2411 2412 sched_type = _soc_trident2_port_sched_type_get(unit, port); 2413 2414 if (sched_type == SOC_TD2_SCHED_LLS) { 2415 if (IS_CPU_PORT(unit, port)) { 2416 op_mode = _SOC_TD2_LLS_OP_TEAR; 2417 rv = soc_td2_cpu_port_lls_init(unit, port, op_mode, 0, NULL, NULL); 2418 } else if (IS_LB_PORT(unit, port)) { 2419 if (!soc_td2_is_skip_default_lls_creation(unit)) { 2420 op_mode = _SOC_TD2_LLS_OP_TEAR; 2421 rv = soc_td2_port_lls_init(unit, port, _td2_lb_port_lls_config, op_mode, NULL, NULL); 2422 } 2423 } else { 2424 if (!soc_td2_is_skip_default_lls_creation(unit)) { 2425 op_mode = _SOC_TD2_LLS_OP_TEAR; 2426 rv = soc_td2_port_lls_init(unit, port, _td2_port_lls_config, op_mode, NULL, NULL); 2427 } 2428 } 2429 } else { 2430 rv = soc_td2_reset_hsp_port(unit, port); 2431 } 2432 return rv; 2433 } 2434 2435 /* 2436 * Function: 2437 * soc_td2_port_lls_traverse 2438 * Purpose: 2439 * This function initialises the structure _td2p_dyn_sched_unit_data, which is 2440 * used later to allocate the register available from the set of 2441 * SP_WERR_DYN_CHANGEnA/nB/nC (n=0,1,2,3) to the port and to keep track 2442 * of the used registers from the set for the port 2443 * Parameters: 2444 * unit - (IN) unit number 2445 * port - (IN) local port number 2446 * cb - (IN) callback function / function pointer 2447 * cookie - (OUT) previous state of LLS 2448 * Returns: 2449 * SOC_E_XXX 2450 */ 2451 int soc_td2_port_lls_traverse(int unit, soc_port_t port, 2452 _soc_td2_lls_traverse_cb cb, void *cookie) 2453 { 2454 int rv = SOC_E_INTERNAL; 2455 _soc_td2p_lls_op_mode_t op_mode; 2456 2457 if (_SOC_TD2_IS_HSP_PORT(unit, port)) { 2458 rv = SOC_E_UNAVAIL; 2459 } else if (IS_CPU_PORT(unit, port)) { 2460 if (soc_feature(unit, soc_feature_cmic_reserved_queues)) { 2461 op_mode = _SOC_TD2_LLS_OP_TRAVERSE; 2462 rv = soc_td2_cpu_port_lls_init(unit, port, op_mode, 2463 1, cb, cookie); 2464 } else { 2465 op_mode = _SOC_TD2_LLS_OP_TRAVERSE; 2466 rv = soc_td2_cpu_port_lls_init(unit, port, op_mode, 2467 0, cb, cookie); 2468 } 2469 } else { 2470 op_mode = _SOC_TD2_LLS_OP_TRAVERSE; 2471 rv = soc_td2_port_lls_init(unit, port, _td2_port_lls_config, 2472 op_mode, cb, cookie); 2473 } 2474 return rv; 2475 } 2476 2477 int 2478 soc_td2_sched_hw_index_get(int unit, int port, int lvl, int offset, 2479 int *hw_index) 2480 { 2481 int rv; 2482 2483 rv = _soc_td2_alloc_sched(unit, port, lvl, offset, hw_index); 2484 2485 LOG_INFO(BSL_LS_SOC_COSQ, 2486 (BSL_META_U(unit, 2487 "Alloced : port=%d lvl=%d ofst=%d Index=%d\n"), 2488 port, lvl, offset, *hw_index)); 2489 return rv; 2490 } 2491 2492 int 2493 soc_td2_qcn_counter_hw_index_get(int unit, soc_port_t port, 2494 int index, int *qindex) 2495 { 2496 soc_mem_t mem; 2497 mmu_qcn_enable_entry_t entry; 2498 int resolved_index = -1; 2499 2500 if (qindex == NULL) { 2501 return SOC_E_PARAM; 2502 } 2503 2504 mem = SOC_TD2_PMEM(unit, port, MMU_QCN_ENABLE_0m, MMU_QCN_ENABLE_1m); 2505 2506 resolved_index = soc_td2_l2_hw_index(unit, index, 1); 2507 SOC_IF_ERROR_RETURN 2508 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, resolved_index, &entry)); 2509 if (soc_mem_field32_get(unit, mem, &entry, CPQ_ENf)) { 2510 *qindex = soc_mem_field32_get(unit, mem, &entry, CPQ_IDf); 2511 } else { 2512 *qindex = -1; 2513 } 2514 2515 return SOC_E_NONE; 2516 } 2517 2518 #define MMU_LB_PORT 116 2519 #define MMU_CMIC_PORT 52 2520 2521 int 2522 soc_td2_get_def_qbase(int unit, soc_port_t inport, int qtype, 2523 int *pbase, int *pnumq) 2524 { 2525 soc_info_t *si; 2526 int base, numq; 2527 2528 si = &SOC_INFO(unit); 2529 2530 if (qtype == _SOC_TD2_INDEX_STYLE_UCAST_QUEUE) { 2531 base = si->port_uc_cosq_base[inport]; 2532 numq = si->port_num_uc_cosq[inport]; 2533 } else if (qtype == _SOC_TD2_INDEX_STYLE_MCAST_QUEUE) { 2534 base = si->port_cosq_base[inport]; 2535 numq = si->port_num_cosq[inport]; 2536 } else { 2537 return SOC_E_INTERNAL; 2538 } 2539 2540 if (pbase) { 2541 *pbase = base; 2542 } 2543 if (pnumq) { 2544 *pnumq = numq; 2545 } 2546 return SOC_E_NONE; 2547 } 2548 2549 STATIC int 2550 _soc_td2_dump_hsp_sched_at(int unit, int port, int level, int offset, int index) 2551 { 2552 uint32 rval = 0; 2553 uint32 conn_map; 2554 uint32 l0_index, l1_index; 2555 uint32 mc_group_mode = 0; 2556 char *lvl_name[] = { "Root", "L0", "L1", "UC", "MC" }; 2557 char *sched_modes[] = {"X", "SP", "WRR", "WDRR"}; 2558 uint32 num_spri =0; 2559 uint32 first_child =0; 2560 uint32 first_mc_child =0; 2561 uint32 ucmap =0; 2562 uint32 sched_mode =0; 2563 soc_info_t *si; 2564 int uc_cosq, mc_cosq; 2565 int uc_cosq_base, mc_cosq_base; 2566 int uc_hw_index, mc_hw_index; 2567 int hw_index; 2568 int wt =0; 2569 2570 si = &SOC_INFO(unit); 2571 2572 uc_cosq_base = si->port_uc_cosq_base[port]; 2573 mc_cosq_base = si->port_cosq_base[port]; 2574 uc_cosq = soc_td2_logical_qnum_hw_qnum(unit, port, uc_cosq_base, 1); 2575 mc_cosq = soc_td2_logical_qnum_hw_qnum(unit, port, mc_cosq_base, 0); 2576 2577 if (level != SOC_TD2_NODE_LVL_ROOT) { 2578 return SOC_E_PARAM; 2579 } 2580 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_PORT_CONFIGr(unit, port, &rval)); 2581 mc_group_mode = soc_reg_field_get(unit, HSP_SCHED_PORT_CONFIGr, 2582 rval, MC_GROUP_MODEf); 2583 /* Root Node */ 2584 LOG_CLI((BSL_META_U(unit, 2585 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 2586 lvl_name[level], offset, index, num_spri, first_child, 2587 sched_modes[sched_mode], wt)); 2588 2589 /* L0 Node */ 2590 for (l0_index = 0; l0_index < 5; l0_index++) { 2591 /* print the L0 Nodes*/ 2592 level = SOC_TD2_NODE_LVL_L0; 2593 SOC_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, 2594 port, level, l0_index, &hw_index)); 2595 soc_td2_cosq_get_sched_mode(unit, port, SOC_TD2_NODE_LVL_L0, 2596 hw_index, &sched_mode, &wt); 2597 LOG_CLI((BSL_META_U(unit, 2598 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 2599 lvl_name[level], l0_index, hw_index, num_spri, first_child, 2600 sched_modes[sched_mode], wt)); 2601 2602 /* read Connection map for the L0.1, L0.2, L0.3, L0.4 2603 * by default connection map should be set to all zeros for L0.0 2604 */ 2605 2606 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_L0_NODE_CONNECTION_CONFIGr( 2607 unit, port, l0_index, &rval)); 2608 conn_map = soc_reg_field_get(unit, 2609 HSP_SCHED_L0_NODE_CONNECTION_CONFIGr, 2610 rval, CHILDREN_CONNECTION_MAPf); 2611 if ((l0_index >= 1) && (l0_index <= 4)) { 2612 for (l1_index = 0; l1_index < 8; l1_index++) { 2613 if (conn_map & (1U<<l1_index)) { 2614 if (l0_index == 4) { 2615 offset = l1_index + 2; 2616 } else { 2617 offset = l1_index; 2618 } 2619 /* print L1 node */ 2620 level = SOC_TD2_NODE_LVL_L1; 2621 SOC_IF_ERROR_RETURN(soc_td2_sched_hw_index_get(unit, 2622 port, level, offset, &hw_index)); 2623 soc_td2_cosq_get_sched_mode(unit, port, SOC_TD2_NODE_LVL_L1, 2624 hw_index, &sched_mode, &wt); 2625 LOG_CLI((BSL_META_U(unit, 2626 " %s.%d : INDEX=%d NUM_SP=%d FC=%d " 2627 "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"), 2628 lvl_name[level], offset, hw_index, num_spri, 2629 first_child, first_mc_child, ucmap, 2630 sched_modes[sched_mode], wt)); 2631 2632 /* print L2 UC node attached to L1 */ 2633 uc_hw_index = soc_td2_l2_hw_index( 2634 unit, uc_cosq_base + offset, 1); 2635 soc_td2_cosq_get_sched_mode(unit, port, 2636 SOC_TD2_NODE_LVL_L2, 2637 uc_hw_index, &sched_mode, &wt); 2638 LOG_CLI((BSL_META_U(unit, 2639 " L2.uc : INDEX=%d Mode=%s WEIGHT=%d\n"), 2640 uc_cosq + offset, sched_modes[sched_mode], wt)); 2641 2642 if (((mc_group_mode == 1) && (l0_index == 4)) || 2643 (mc_group_mode == 0)) { 2644 /* print L2 MC node attached to L1 */ 2645 /* MC_GROUP_MODE = 1 then 8 MC Cos queues are 2646 * grouped together and shared the parent (L0.0) bandwidth. 2647 * MC_QM and MC_SC queues are still paired with 2648 * UC_QM and UC_SC respectivly 2649 */ 2650 mc_hw_index = soc_td2_l2_hw_index( 2651 unit, mc_cosq_base + offset, 0); 2652 soc_td2_cosq_get_sched_mode(unit, port, 2653 SOC_TD2_NODE_LVL_L2, 2654 mc_hw_index, &sched_mode, &wt); 2655 LOG_CLI((BSL_META_U(unit, 2656 " L2.mc : INDEX=%d Mode=%s WEIGHT=%d\n"), 2657 mc_cosq + offset, sched_modes[sched_mode], wt)); 2658 } 2659 } 2660 } 2661 } else if (l0_index == 0) { 2662 if (mc_group_mode) { 2663 offset = 0; 2664 for (l1_index = 0; l1_index < 8; l1_index++) { 2665 /* 8 MC Cos queues are grouped together and shared 2666 * the parent (L0.0) bandwidth. 2667 */ 2668 mc_hw_index = soc_td2_l2_hw_index(unit, 2669 mc_cosq_base + offset, 0); 2670 soc_td2_cosq_get_sched_mode(unit, port, 2671 SOC_TD2_NODE_LVL_L2, 2672 mc_hw_index, &sched_mode, &wt); 2673 LOG_CLI((BSL_META_U(unit, 2674 " L2.mc : INDEX=%d Mode=%s WEIGHT=%d\n"), 2675 mc_cosq + offset, sched_modes[sched_mode], wt)); 2676 offset++; 2677 } 2678 2679 } 2680 } 2681 } 2682 2683 return SOC_E_NONE; 2684 } 2685 2686 STATIC int 2687 _soc_td2_child_num_get(int unit, int port, int level, int hw_index, int *count) 2688 { 2689 soc_mem_t mem; 2690 int cindex, index_max, ii, child_level, num_child = 0; 2691 uint32 entry[SOC_MAX_MEM_WORDS]; 2692 2693 soc_td2_get_child_type(unit, port, level, &child_level); 2694 mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, child_level); 2695 2696 if (mem == INVALIDm) { 2697 return SOC_E_INTERNAL; 2698 } 2699 index_max = soc_mem_index_max(unit, mem); 2700 2701 for (ii = 0; ii <= index_max; ii++) { 2702 SOC_IF_ERROR_RETURN( 2703 soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &entry)); 2704 2705 cindex = soc_mem_field32_get(unit, mem, entry, C_PARENTf); 2706 2707 if (cindex == hw_index) { 2708 num_child += 1; 2709 } 2710 } 2711 2712 if (count != NULL) { 2713 *count = num_child; 2714 } 2715 2716 return SOC_E_NONE; 2717 } 2718 2719 STATIC int 2720 _soc_td2_dump_sched_at(int unit, int port, int level, int offset, int hw_index) 2721 { 2722 int num_spri, first_child, first_mc_child, rv, cindex; 2723 uint32 ucmap, spmap; 2724 soc_td2_sched_mode_e sched_mode; 2725 soc_mem_t mem; 2726 int index_max, ii, ci, child_level, wt = 0, num_child, num_l1_children = 0; 2727 uint32 entry[SOC_MAX_MEM_WORDS]; 2728 char *lvl_name[] = { "Root", "L0", "L1", "L2" }; 2729 char *sched_modes[] = {"X", "SP", "WRR", "WDRR"}; 2730 2731 if (level < SOC_TD2_NODE_LVL_L2) { 2732 soc_td2_get_child_type(unit, port, level, &child_level); 2733 if (hw_index == INVALID_PARENT(unit, child_level)) { 2734 if (soc_feature(unit, soc_feature_lls_port_mema_config_match)) { 2735 return SOC_E_NONE; 2736 } 2737 2738 /* 2739 * INVALID_PARENT(L0) may be zero. 2740 * When this condition occurs, 2741 * we need to do further check instead of returning. 2742 */ 2743 if (!((child_level == SOC_TD2_NODE_LVL_L0) && 2744 (hw_index == 0))) { 2745 return SOC_E_NONE; 2746 } 2747 } 2748 } 2749 2750 /* get sched config */ 2751 SOC_IF_ERROR_RETURN( 2752 soc_td2_cosq_get_sched_child_config(unit, port, level, hw_index, 2753 &num_spri, &first_child, &first_mc_child, &ucmap, 2754 &spmap)); 2755 sched_mode = 0; 2756 if (level != SOC_TD2_NODE_LVL_ROOT) { 2757 SOC_IF_ERROR_RETURN( 2758 soc_td2_cosq_get_sched_mode(unit, port, level, hw_index, &sched_mode, &wt)); 2759 } 2760 2761 if (level == SOC_TD2_NODE_LVL_L1) { 2762 LOG_CLI((BSL_META_U(unit, 2763 " %s.%d : INDEX=%d NUM_SP=%d FC=%d " 2764 "FMC=%d UCMAP=0x%08x MODE=%s WT=%d\n"), 2765 lvl_name[level], offset, hw_index, num_spri, 2766 first_child, first_mc_child, ucmap, 2767 sched_modes[sched_mode], wt)); 2768 } else { 2769 LOG_CLI((BSL_META_U(unit, 2770 " %s.%d : INDEX=%d NUM_SPRI=%d FC=%d MODE=%s Wt=%d\n"), 2771 lvl_name[level], offset, hw_index, num_spri, first_child, 2772 sched_modes[sched_mode], wt)); 2773 } 2774 2775 soc_td2_get_child_type(unit, port, level, &child_level); 2776 mem = _SOC_TD2_NODE_PARENT_MEM(unit, port, child_level); 2777 2778 if(mem == INVALIDm) { 2779 return SOC_E_INTERNAL; 2780 } 2781 index_max = soc_mem_index_max(unit, mem); 2782 2783 num_child = 0; 2784 for (ii = 0, ci = 0; ii <= index_max; ii++) { 2785 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, ii, &entry); 2786 if (rv) { 2787 LOG_CLI((BSL_META_U(unit, 2788 "Failed to read memory at index: %d\n"), ii)); 2789 break; 2790 } 2791 2792 cindex = soc_mem_field32_get(unit, mem, entry, C_PARENTf); 2793 if (cindex == hw_index) { 2794 if (!soc_feature(unit, soc_feature_lls_port_mema_config_match)) { 2795 /* 2796 * INVALID_PARENT(L0) may be zero. 2797 * When this condition occurs, 2798 * we should get the node`s child count to decide 2799 * if it is a valid node or not. 2800 */ 2801 if ((cindex == 0) && (child_level == SOC_TD2_NODE_LVL_L0)) { 2802 _soc_td2_child_num_get(unit, port, child_level, 2803 ii, &num_l1_children); 2804 if (num_l1_children == 0) { 2805 continue; 2806 } 2807 } 2808 } 2809 if (child_level == SOC_TD2_NODE_LVL_L2) { 2810 SOC_IF_ERROR_RETURN(soc_td2_cosq_get_sched_mode(unit, port, 2811 SOC_TD2_NODE_LVL_L2, ii, &sched_mode, &wt)); 2812 LOG_CLI((BSL_META_U(unit, 2813 " L2.%s INDEX=%d Mode=%s WEIGHT=%d\n"), 2814 ((ii < 1480) ? "uc" : "mc"), 2815 ii, sched_modes[sched_mode], wt)); 2816 } else { 2817 _soc_td2_dump_sched_at(unit, port, child_level, ci, ii); 2818 ci += 1; 2819 } 2820 num_child += 1; 2821 } 2822 } 2823 if (num_child == 0) { 2824 LOG_CLI((BSL_META_U(unit, 2825 "*** No children \n"))); 2826 } 2827 return SOC_E_NONE; 2828 } 2829 2830 int soc_td2_dump_port_lls(int unit, int port) 2831 { 2832 int mmu_port, index; 2833 2834 if (_soc_trident2_port_sched_type_get(unit, port) == SOC_TD2_SCHED_HSP) { 2835 return SOC_E_NONE; 2836 } 2837 2838 2839 soc_td2_port_common_attributes_get(unit, port, NULL, &mmu_port, NULL); 2840 2841 LOG_CLI((BSL_META_U(unit, 2842 "-------%s (LLS)------\n"), SOC_PORT_NAME(unit, (port)))); 2843 index = _soc_trident2_root_scheduler_index(unit, port); 2844 LOG_INFO(BSL_LS_SOC_COSQ, 2845 (BSL_META_U(unit, "Port:%d mmu_port %d index %d\n"), port, mmu_port, index)); 2846 _soc_td2_dump_sched_at(unit, port, SOC_TD2_NODE_LVL_ROOT, 0, index); 2847 return SOC_E_NONE; 2848 } 2849 int soc_td2_dump_port_hsp(int unit, int port) 2850 { 2851 int mmu_port, index; 2852 2853 if (_soc_trident2_port_sched_type_get(unit, port) == SOC_TD2_SCHED_LLS) { 2854 return SOC_E_NONE; 2855 } 2856 2857 soc_td2_port_common_attributes_get(unit, port, NULL, &mmu_port, NULL); 2858 2859 LOG_CLI((BSL_META_U(unit, 2860 "-------%s (HSP)------\n"), SOC_PORT_NAME(unit, (port)))); 2861 index = _soc_trident2_root_scheduler_index(unit, port); 2862 _soc_td2_dump_hsp_sched_at(unit, port, SOC_TD2_NODE_LVL_ROOT, 0, index); 2863 return SOC_E_NONE; 2864 } 2865 int soc_td2_logical_qnum_hw_qnum(int unit, int port, int lqnum, int uc) 2866 { 2867 if (uc) { 2868 if (lqnum >= 1480) { 2869 return (lqnum - 1480) + 2048; 2870 } else { 2871 return lqnum; 2872 } 2873 } else { 2874 if (lqnum >= 568) { 2875 return (lqnum - 568) + 3528; 2876 } else { 2877 return lqnum + 1480; 2878 } 2879 } 2880 return -1; 2881 } 2882 2883 int soc_td2_mmu_get_shared_size(int unit, int *shared_size) 2884 { 2885 uint32 entry0[SOC_MAX_MEM_WORDS]; 2886 2887 sal_memset(entry0, 0, sizeof(mmu_thdu_xpipe_config_queue_entry_t)); 2888 SOC_IF_ERROR_RETURN 2889 (soc_mem_read(unit, MMU_THDU_XPIPE_CONFIG_QUEUEm, MEM_BLOCK_ALL, 0, entry0)); 2890 *shared_size = soc_mem_field32_get(unit, MMU_THDU_XPIPE_CONFIG_QUEUEm, entry0, Q_SHARED_LIMIT_CELLf); 2891 return 1; 2892 } 2893 2894 int 2895 soc_td2_mmu_config_res_limits_update(int unit,uint32 spid, 2896 uint32 shared_size, int flags) 2897 { 2898 return soc_td2_mmu_config_shared_buf_recalc(unit, spid, shared_size, flags); 2899 } 2900 2901 void 2902 soc_trident2_fc_map_shadow_free(int unit) 2903 { 2904 int mem_idx; 2905 soc_td2_fc_map_shadow_memory_t * shadow_info; 2906 soc_td2_fc_map_shadow_t* shadow_ctrl = &soc_td2_fc_map_shadow[unit]; 2907 2908 if (shadow_ctrl->shadow_array != NULL) { 2909 for (mem_idx = 0; mem_idx < shadow_ctrl->mem_count; mem_idx++){ 2910 shadow_info = &(shadow_ctrl->shadow_array[mem_idx]); 2911 if (shadow_info->mem_shadow != NULL){ 2912 sal_free(shadow_info->mem_shadow); 2913 } 2914 } 2915 sal_free(shadow_ctrl->shadow_array); 2916 shadow_ctrl->shadow_array = NULL; 2917 shadow_ctrl->mem_count = 0; 2918 } 2919 } 2920 2921 int 2922 soc_trident2_fc_map_shadow_create(int unit) 2923 { 2924 int mem_idx, alloc_size, num_entries, entry_size; 2925 soc_td2_fc_map_shadow_memory_t* shadow_info = NULL; 2926 uint32* shadow = NULL; 2927 2928 if (soc_td2_fc_map_shadow[unit].shadow_array == NULL) { 2929 alloc_size = sizeof(soc_td2_fc_map_shadow_memory_t) * 2930 COUNTOF(fc_map_mems); 2931 shadow_info = sal_alloc(alloc_size, "fc map shadow control"); 2932 if (shadow_info == NULL) { 2933 return SOC_E_MEMORY; 2934 } 2935 2936 sal_memset(shadow_info, 0, alloc_size); 2937 soc_td2_fc_map_shadow[unit].shadow_array = shadow_info; 2938 2939 for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) { 2940 num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]); 2941 entry_size = soc_mem_entry_words(unit, fc_map_mems[mem_idx]); 2942 alloc_size = entry_size * num_entries * sizeof(uint32); 2943 shadow = sal_alloc(alloc_size, "fc map shadow tbl"); 2944 if (shadow == NULL) { 2945 soc_trident2_fc_map_shadow_free(unit); 2946 return SOC_E_MEMORY; 2947 } 2948 sal_memset(shadow, 0, alloc_size); 2949 soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow = shadow; 2950 soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem = fc_map_mems[mem_idx]; 2951 soc_td2_fc_map_shadow[unit].mem_count++; 2952 } 2953 } 2954 return SOC_E_NONE; 2955 } 2956 2957 int 2958 soc_trident2_fc_map_shadow_entry_get (int unit, soc_mem_t mem, int index, 2959 void* entry_data) 2960 { 2961 int mem_idx, entry_words; 2962 uint32 * shadow = NULL; 2963 2964 switch(mem){ 2965 case MMU_INTFI_XPIPE_FC_MAP_TBL0m: 2966 mem_idx = 0; 2967 break; 2968 case MMU_INTFI_XPIPE_FC_MAP_TBL1m: 2969 mem_idx = 1; 2970 break; 2971 case MMU_INTFI_YPIPE_FC_MAP_TBL0m: 2972 mem_idx = 2; 2973 break; 2974 case MMU_INTFI_YPIPE_FC_MAP_TBL1m: 2975 mem_idx = 3; 2976 break; 2977 default: 2978 return SOC_E_NOT_FOUND; 2979 2980 } 2981 2982 shadow = soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow; 2983 entry_words = soc_mem_entry_words(unit, mem); 2984 sal_memcpy(entry_data, shadow + index * entry_words, 2985 entry_words * sizeof(uint32)); 2986 return SOC_E_NONE; 2987 } 2988 2989 int 2990 soc_trident2_fc_map_shadow_entry_set (int unit, soc_mem_t mem, int index, 2991 void* entry_data) 2992 { 2993 int mem_idx, entry_words; 2994 uint32 * shadow = NULL; 2995 2996 switch(mem){ 2997 case MMU_INTFI_XPIPE_FC_MAP_TBL0m: 2998 mem_idx = 0; 2999 break; 3000 case MMU_INTFI_XPIPE_FC_MAP_TBL1m: 3001 mem_idx = 1; 3002 break; 3003 case MMU_INTFI_YPIPE_FC_MAP_TBL0m: 3004 mem_idx = 2; 3005 break; 3006 case MMU_INTFI_YPIPE_FC_MAP_TBL1m: 3007 mem_idx = 3; 3008 break; 3009 default: 3010 return SOC_E_NOT_FOUND; 3011 3012 } 3013 shadow = soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow; 3014 entry_words = soc_mem_entry_words(unit, mem); 3015 sal_memcpy(shadow + index * entry_words, entry_data, 3016 entry_words * sizeof(uint32)); 3017 return SOC_E_NONE; 3018 } 3019 3020 int 3021 soc_trident2_fc_map_shadow_clear (int unit, soc_mem_t mem) 3022 { 3023 uint32 * shadow = NULL; 3024 int entry_words, tbl_size, mem_idx, num_entries; 3025 switch(mem){ 3026 case MMU_INTFI_XPIPE_FC_MAP_TBL0m: 3027 mem_idx = 0; 3028 break; 3029 case MMU_INTFI_XPIPE_FC_MAP_TBL1m: 3030 mem_idx = 1; 3031 break; 3032 case MMU_INTFI_YPIPE_FC_MAP_TBL0m: 3033 mem_idx = 2; 3034 break; 3035 case MMU_INTFI_YPIPE_FC_MAP_TBL1m: 3036 mem_idx = 3; 3037 break; 3038 default: 3039 return SOC_E_NOT_FOUND; 3040 } 3041 entry_words = soc_mem_entry_words(unit, mem); 3042 shadow = soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow; 3043 num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]); 3044 tbl_size = entry_words * num_entries; 3045 if (shadow != NULL) { 3046 sal_memset(shadow, 0, tbl_size * sizeof(uint32)); 3047 } 3048 return SOC_E_NONE; 3049 } 3050 #ifdef BCM_WARM_BOOT_SUPPORT 3051 int 3052 soc_trident2_fc_map_shadow_size_get (int unit, uint32 * size) 3053 { 3054 int alloc_size = 0, mem_idx, num_entries, entry_size; 3055 for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) { 3056 num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]); 3057 entry_size = soc_mem_entry_words(unit, fc_map_mems[mem_idx]); 3058 alloc_size += entry_size * num_entries * sizeof(uint32); 3059 } 3060 *size = alloc_size; 3061 return SOC_E_NONE; 3062 } 3063 3064 int 3065 soc_trident2_fc_map_shadow_sync (int unit, uint32 **sync_addr) 3066 { 3067 int mem_idx, num_entries, tbl_size, entry_size; 3068 3069 for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) { 3070 num_entries = soc_mem_index_count(unit, fc_map_mems[mem_idx]); 3071 entry_size = soc_mem_entry_words(unit, fc_map_mems[mem_idx]); 3072 tbl_size = entry_size * num_entries; 3073 sal_memcpy(*sync_addr, soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow, 3074 tbl_size * sizeof(uint32)); 3075 *sync_addr += tbl_size; 3076 } 3077 return SOC_E_NONE; 3078 } 3079 3080 int 3081 soc_trident2_fc_map_shadow_load (int unit, uint32 **load_addr) 3082 { 3083 int blk, mem_idx, num_entries; 3084 int tbl_size, entry_size, vmap_size; 3085 uint32 *cache; 3086 uint32 *shadow; 3087 uint8 *vmap; 3088 int index_min; 3089 soc_mem_t mem; 3090 3091 for (mem_idx = 0; mem_idx < COUNTOF(fc_map_mems); mem_idx++) { 3092 mem = fc_map_mems[mem_idx]; 3093 num_entries = soc_mem_index_count(unit, mem); 3094 entry_size = soc_mem_entry_words(unit, mem); 3095 index_min = soc_mem_index_min(unit, mem); 3096 tbl_size = entry_size * num_entries; 3097 sal_memcpy(soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow, *load_addr, 3098 tbl_size * sizeof(uint32)); 3099 *load_addr += tbl_size; 3100 /* restore memory cache */ 3101 vmap_size = (num_entries + 7) / 8; 3102 SOC_MEM_BLOCK_ITER(unit, mem, blk) { 3103 if (SOC_MEM_STATE(unit, mem).cache[blk] == NULL) { 3104 continue; 3105 } 3106 cache = SOC_MEM_STATE(unit, mem).cache[blk]; 3107 vmap = SOC_MEM_STATE(unit, mem).vmap[blk]; 3108 shadow = soc_td2_fc_map_shadow[unit].shadow_array[mem_idx].mem_shadow; 3109 sal_memcpy(cache, shadow, tbl_size * sizeof(uint32)); 3110 3111 sal_memset(&vmap[index_min / 8], 0xff, 3112 (num_entries + 7 - index_min) / 8); 3113 3114 /* Clear invalid bits at the left and right ends */ 3115 vmap[index_min / 8] &= 0xff00 >> (8 - index_min % 8); 3116 vmap[vmap_size - 1] &= 0x00ff >> ((8 - num_entries % 8) % 8); 3117 } 3118 } 3119 return SOC_E_NONE; 3120 } 3121 #endif 3122 3123 /* 3124 * Function: 3125 * soc_trident2_port_sched_set 3126 * Purpose: 3127 * Update/Set Scheduling on the port 3128 * Parameters: 3129 * unit - (IN) Unit number. 3130 * port - (IN) Logical SOC port number. 3131 * Returns: 3132 * SOC_E_XXX 3133 */ 3134 int 3135 soc_trident2_port_sched_set(int unit, soc_port_t port) 3136 { 3137 int rv = SOC_E_NONE; 3138 soc_trident2_sched_type_t sched_type; 3139 _soc_td2p_lls_op_mode_t op_mode; 3140 3141 if (IS_CPU_PORT(unit, port) || (IS_LB_PORT(unit, port))) { 3142 return rv; 3143 } 3144 3145 sched_type = _soc_trident2_port_sched_type_get(unit, port); 3146 3147 if (sched_type == SOC_TD2_SCHED_HSP) { 3148 rv = soc_td2_setup_hsp_port(unit, port); 3149 } else { 3150 if (!soc_td2_is_skip_default_lls_creation(unit)) { 3151 op_mode = _SOC_TD2_LLS_OP_SETUP; 3152 rv = soc_td2_port_lls_init(unit, port, 3153 _td2_port_lls_config, op_mode, NULL, NULL); 3154 } 3155 } 3156 if (rv) { 3157 return SOC_E_INTERNAL; 3158 } 3159 return SOC_E_NONE; 3160 } 3161 3162 3163 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 3164 /* 3165 * Function: 3166 * soc_td2p_lls_reinit_invalid_pointers 3167 * Purpose: 3168 * Makes a copy of _td2_invalid_ptr. 3169 * Reinitialize _td2_invalid_ptr 3170 * Parameters: 3171 * unit - (IN) unit number 3172 * Returns: 3173 * SOC_E_XXX 3174 */ 3175 3176 int soc_td2p_lls_reinit_invalid_pointers(int unit) 3177 { 3178 int lvl; 3179 3180 for (lvl = SOC_TD2_NODE_LVL_ROOT; lvl < SOC_TD2_NODE_LVL_MAX; lvl++) { 3181 _td2p_prev_invalid_ptr[unit][lvl] = _td2_invalid_ptr[unit][lvl]; 3182 } 3183 3184 SOC_IF_ERROR_RETURN(soc_td2_init_invalid_pointers(unit)); 3185 3186 return SOC_E_NONE; 3187 } 3188 3189 /* 3190 * Function: 3191 * soc_td2p_lls_reset_flex 3192 * Purpose: 3193 * updates LLS memories (_SOC_TD2_NODE_PARENT_MEM) 3194 * with INVALID PARENT 3195 * Parameters: 3196 * unit - (IN) unit number 3197 * Returns: 3198 * SOC_E_XXX 3199 */ 3200 int soc_td2p_lls_reset_flex(int unit) 3201 { 3202 int lvl, i; 3203 uint32 clrmap = 0, pipe; 3204 soc_mem_t mem; 3205 uint32 entry[SOC_MAX_MEM_WORDS]; 3206 int rv, cindex; 3207 3208 3209 for (pipe = _TD2_XPIPE; pipe <= _TD2_YPIPE; pipe++) { 3210 for (lvl = SOC_TD2_NODE_LVL_L0; lvl <= SOC_TD2_NODE_LVL_L2; lvl++) { 3211 mem = _SOC_TD2_PIPED_NODE_PARENT_MEM(unit, pipe, lvl); 3212 3213 if ((clrmap & (1 << (pipe * SOC_TD2_NODE_LVL_MAX + lvl))) == 0) { 3214 /* coverity[negative_returns : FALSE] */ 3215 for (i = 0; i <= soc_mem_index_max(unit, mem); i++) { 3216 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, i, &entry); 3217 if (rv) { 3218 LOG_ERROR(BSL_LS_SOC_COSQ, 3219 (BSL_META_U(unit, 3220 "Failed to read memory at index: %d\n"), i)); 3221 break; 3222 } 3223 cindex = soc_mem_field32_get(unit, mem, entry, C_PARENTf); 3224 if ((cindex == _td2p_prev_invalid_ptr[unit][lvl]) && 3225 (cindex != INVALID_PARENT(unit, lvl))) { 3226 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 3227 soc_mem_field32_set(unit, mem, entry, C_PARENTf, INVALID_PARENT(unit, lvl)); 3228 SOC_IF_ERROR_RETURN 3229 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, i, &entry)); 3230 } 3231 } 3232 clrmap |= (1 << (pipe * SOC_TD2_NODE_LVL_MAX + lvl)); 3233 } 3234 } 3235 } 3236 3237 return SOC_E_NONE; 3238 } 3239 #endif 3240 3241 #endif /* BCM_TRIDENT2_SUPPORT */ 3242