traffic_manager.c (197060B)
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 * File: traffic_manager.c 8 * Purpose: Tomahawk3 IDB, EDB and MMU routines 9 * Requires: 10 */ 11 12 #include <shared/bsl.h> 13 14 #include <soc/drv.h> 15 #include <soc/mem.h> 16 #include <soc/debug.h> 17 #include <soc/hash.h> 18 19 #if defined(BCM_TOMAHAWK3_SUPPORT) 20 21 #include <soc/tomahawk3.h> 22 #include <soc/init/tomahawk3_idb_init.h> 23 #include <soc/init/tomahawk3_port_init.h> 24 #include <soc/tomahawk2_tdm.h> 25 #include <soc/init/tomahawk3_tdm.h> 26 #include <soc/init/tomahawk3_ep_init.h> 27 #include <bcm_int/common/tx.h> 28 #include <soc/flexport/tomahawk3_flexport.h> 29 30 soc_th3_mmu_info_t *th3_cosq_mmu_info[SOC_MAX_NUM_DEVICES]; 31 soc_th3_sched_profile_info_t th3_sched_profile_info[SOC_MAX_NUM_DEVICES][SOC_TH3_MAX_NUM_SCHED_PROFILE][SOC_TH3_NUM_GP_QUEUES]; 32 int L1_TO_L0_MAPPING[SOC_MAX_NUM_DEVICES][SOC_TH3_MAX_NUM_SCHED_PROFILE] 33 [SOC_TH3_NUM_GP_QUEUES]; 34 int L0_TO_L1_MAPPING_NUM[SOC_MAX_NUM_DEVICES][SOC_TH3_MAX_NUM_SCHED_PROFILE] 35 [SOC_TH3_NUM_GP_QUEUES]; 36 int L0_TO_COSQ_MAPPING[SOC_MAX_NUM_DEVICES][SOC_TH3_MAX_NUM_SCHED_PROFILE] 37 [SOC_TH3_NUM_GP_QUEUES]; 38 39 int soc_th3_chip_queue_num_get(int unit, soc_port_t port, int qid, int type, 40 int *hw_index) { 41 /* type 0 UC queue, type 1 MC queue */ 42 int mmu_local_port, mmuq, pipe, num_ucq; 43 uint32 pipe_map; 44 soc_info_t *si = &SOC_INFO(unit); 45 int q_base_list[] = {0, 276, 516, 744, 972, 1200, 1440, 1680}; 46 if (!SOC_PORT_VALID(unit, port)) { 47 return SOC_E_PORT; 48 } 49 pipe = si->port_pipe[port]; 50 mmu_local_port = si->port_l2i_mapping[port]; 51 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 52 if (!(pipe_map & (1U << pipe))) { 53 return SOC_E_PORT; 54 } 55 num_ucq = _soc_th3_get_num_ucq(unit); 56 if (type == 0) { 57 if (qid == -1) { 58 /* return the starting q_num */ 59 *hw_index = q_base_list[pipe] + mmu_local_port * SOC_TH3_NUM_GP_QUEUES; 60 } else { 61 if (qid >= num_ucq) { 62 return SOC_E_PARAM; 63 } 64 mmuq = qid; 65 *hw_index = q_base_list[pipe] + 66 mmu_local_port * SOC_TH3_NUM_GP_QUEUES + mmuq; 67 } 68 } else if (type == 1) { 69 if (qid == -1) { 70 *hw_index = q_base_list[pipe] + 71 mmu_local_port * SOC_TH3_NUM_GP_QUEUES + num_ucq; 72 73 } else { 74 if (qid >= SOC_TH3_NUM_GP_QUEUES - num_ucq) { 75 return SOC_E_PARAM; 76 } 77 mmuq = num_ucq + qid; 78 *hw_index = q_base_list[pipe] + 79 mmu_local_port * SOC_TH3_NUM_GP_QUEUES + mmuq; 80 } 81 } 82 return SOC_E_NONE; 83 } 84 85 uint32 86 soc_th3_mmu_chip_port_num (int unit, int port) 87 { 88 soc_info_t *si = &SOC_INFO(unit); 89 int global_mmu_port, phy_port, mmu_chip_port, pipe; 90 pipe = si->port_pipe[port]; 91 phy_port = si->port_l2p_mapping[port]; 92 global_mmu_port = si->port_p2m_mapping[phy_port]; 93 mmu_chip_port = (global_mmu_port % SOC_TH3_MMU_PORT_STRIDE) + 94 (pipe * SOC_TH3_MAX_DEV_PORTS_PER_PIPE); 95 return mmu_chip_port; 96 } 97 98 uint32 99 soc_th3_mmu_local_port_num (int unit, int port) 100 { 101 soc_info_t *si = &SOC_INFO(unit); 102 return si->port_l2i_mapping[port]; 103 } 104 105 106 /* 107 *Function: soc_tomahawk3_mem_is_itm 108 *Purpose: check if memory is in ITM block 109 *Params: 110 * unit: Device unit number 111 * mem: base memory 112 */ 113 int soc_tomahawk3_mem_is_itm(int unit, soc_mem_t mem) 114 { 115 int block_info_index; 116 117 if (mem != INVALIDm) { 118 if (SOC_MEM_IS_VALID(unit, mem)) { 119 block_info_index = SOC_MEM_BLOCK_ANY(unit, mem); 120 if (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_ITM) { 121 return 1; 122 } 123 } 124 } 125 return 0; 126 } 127 128 /* 129 *Function: soc_tomahawk3_reg_is_itm 130 *Purpose: check if register is in ITM block 131 *Params: 132 * unit: Device unit number 133 * mem: base register 134 */ 135 int soc_tomahawk3_reg_is_itm(int unit, soc_reg_t reg) 136 { 137 if (reg != INVALIDr) { 138 if (SOC_REG_IS_VALID(unit, reg)) { 139 return (SOC_REG_BLOCK_IS(unit, reg, SOC_BLK_MMU_ITM)); 140 } 141 } 142 143 return 0; 144 } 145 146 147 /*Function to check if the itm, base_index combination is valid 148 *Base Type: IPORT/IPIPE: Pipes 0,1,6,7 ITM0, Pipes 2,3,4,5 ITM1 149 *Base Type: EPORT/EPIPE: Can be in both ITMs; 150 *ITM should be valied for device config (esp. for half setups) 151 *Base Type: ITM: Passed ITM is valid 152 */ 153 int 154 soc_tomahawk3_itm_base_index_check(int unit, int base_type, int itm, 155 int base_index, char *msg) 156 { 157 soc_info_t *si; 158 int pipe; 159 uint32 map; 160 char *base_name; 161 162 si = &SOC_INFO(unit); 163 164 if (itm == -1 || base_index == -1) { 165 return SOC_E_NONE; 166 } 167 168 if (itm < NUM_ITM(unit) && si->itm_ipipe_map[itm] == 0) { 169 if (msg) { 170 LOG_CLI((BSL_META_U(unit, 171 "%s: ITM%d is not in config\n"), 172 msg, itm)); 173 } 174 return SOC_E_PARAM; 175 } 176 177 switch (base_type) { 178 case 0: /* IPORT */ 179 case 1: /* EPORT */ 180 base_name = base_type == 0 ? "IPORT" : "EPORT"; 181 pipe = si->port_pipe[base_index]; 182 if (pipe == -1) { 183 if (msg) { 184 LOG_CLI((BSL_META_U(unit, 185 "%s: %s%d is not in config\n"), 186 msg, base_name, base_index)); 187 } 188 } else if (itm < NUM_ITM(unit)) { /* Unique access type */ 189 map = base_type == 0 ? 190 si->ipipe_itm_map[pipe] : si->itm_map; 191 if (map & (1 << itm)) { 192 break; 193 } 194 if (msg != NULL) { 195 LOG_CLI((BSL_META_U(unit, 196 "%s: %s%d is not in ITM%d\n"), 197 msg, base_name, base_index, itm)); 198 } 199 } else { 200 break; 201 } 202 return SOC_E_PARAM; 203 case 2: /* IPIPE */ 204 case 3: /* EPIPE */ 205 if (base_type == 2) { 206 base_name = "IPIPE"; 207 map = si->ipipe_itm_map[base_index]; 208 } else { 209 base_name = "EPIPE"; 210 map = si->itm_map; 211 } 212 if (map == 0) { 213 if (msg) { 214 LOG_CLI((BSL_META_U(unit, 215 "%s: %s%d is not in config\n"), 216 msg, base_name, base_index)); 217 } 218 } else if (itm < NUM_ITM(unit)) { /* Unique access type */ 219 if (map & (1 << itm)) { 220 break; 221 } 222 if (msg != NULL) { 223 LOG_CLI((BSL_META_U(unit, 224 "%s: %s%d is not in ITM%d\n"), 225 msg, base_name, base_index, itm)); 226 } 227 } else { 228 break; 229 } 230 return SOC_E_PARAM; 231 case 4: /* CHIP */ 232 break; 233 case 5: /* ITM*/ 234 if (si->itm_ipipe_map[base_index] != 0) { 235 break; 236 } 237 if (msg != NULL) { 238 LOG_CLI((BSL_META_U(unit, 239 "%s: ITM%d is not in config\n"), 240 msg, base_index)); 241 } 242 return SOC_E_PARAM; 243 } 244 245 return SOC_E_NONE; 246 } 247 248 /* 249 *Function: _soc_tomahawk3_itm_reg_check 250 *Purpose: Check if resigter is in ITM block and passed ITM value is in range 251 * Override itm with access_type for unique memories 252 * Call check to verify itm/base_index combination 253 *Params: 254 * unit: Device unit number 255 * reg: Register name 256 * itm: ITM# 257 * base_index: base index to be accessed 258 */ 259 STATIC int 260 _soc_tomahawk3_itm_reg_check(int unit, soc_reg_t reg, int itm, int base_index) 261 { 262 int acc_type, base_type; 263 264 if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_ITM)) { 265 LOG_CLI((BSL_META_U(unit, 266 "%s is not ITM register\n"), SOC_REG_NAME(unit, reg))); 267 return SOC_E_PARAM; 268 } 269 270 if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */ 271 if (itm == -1 || itm >= NUM_ITM(unit)) { 272 LOG_CLI((BSL_META_U(unit, 273 "%s bad ITM value %d\n"), 274 SOC_REG_NAME(unit, reg), itm)); 275 return SOC_E_PARAM; 276 } 277 } else { 278 acc_type = SOC_REG_ACC_TYPE(unit, reg); 279 if (acc_type < NUM_ITM(unit)) { /* UNIQUE per ITM register */ 280 if (itm != acc_type) { 281 LOG_CLI((BSL_META_U(unit, 282 "Ovveride ITM value %d with ACC_TYPE of %s\n"), 283 itm, SOC_REG_NAME(unit, reg))); 284 } 285 itm = acc_type; 286 } else { /* non-UNIQUE register */ 287 return SOC_E_NONE; 288 } 289 } 290 /*retrieve bits [25:23] of memory address for base_type*/ 291 base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7; 292 293 return soc_tomahawk3_itm_base_index_check(unit, base_type, itm, base_index, 294 SOC_REG_NAME(unit, reg)); 295 } 296 297 /* 298 * Parameters for soc_tomahawk3_itm_reg_access: 299 * 300 * base unique reg/ itm write action read action 301 * index type mem 302 * ==== ====== ===== === ================ ================= 303 * #1 -1 no - - all ITMs first pipe in the first ITM 304 * #2 -1 yes base -1 (same as #1) 305 * #3 -1 yes base 0-3 all pipes in the ITM first pipe in the ITM 306 * #4 -1 yes itm0-3 - (same as #3) 307 * #5 0-1 no - - applicable ITMs first ITM has the pipe 308 * 309 * - S/W will loop through base types (i.e. pipes) if base_index==-1 310 * - S/W will loop through applicable ITMs if itm==-1 on unique access type 311 * base view (H/W will do the loop for other access types) 312 */ 313 STATIC int 314 _soc_tomahawk3_itm_reg_access(int unit, soc_reg_t reg, int itm, int base_index, 315 int index, uint64 *data, int write) 316 { 317 soc_info_t *si; 318 soc_reg_t orig_reg; 319 int port, pipe; 320 int base_type, break_after_first; 321 int loop_index; 322 uint32 base_index_map, itm_map=0; 323 soc_pbmp_t base_index_pbmp; 324 uint32 inst; 325 326 si = &SOC_INFO(unit); 327 orig_reg = reg; 328 /*retrieve bits [25:23] of memory address for base_type*/ 329 base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7; 330 break_after_first = TRUE; 331 332 if (itm >= 0 && base_index >= 0) { 333 SOC_IF_ERROR_RETURN 334 (_soc_tomahawk3_itm_reg_check(unit, reg, itm, base_index)); 335 } 336 337 if (base_index < -1) { 338 return SOC_E_PARAM; 339 } 340 switch (base_type) { 341 case 0: /* IPORT */ 342 case 1: /* EPORT */ 343 if (itm >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { 344 reg = SOC_REG_UNIQUE_ACC(unit, reg)[itm]; 345 } 346 if (base_index == -1) { 347 SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit)); 348 } else { 349 /* This argument is logical port, same as soc_reg_get/set */ 350 SOC_PBMP_PORT_SET(base_index_pbmp, base_index); 351 } 352 SOC_PBMP_ITER(base_index_pbmp, port) { 353 pipe = si->port_pipe[port]; 354 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 355 itm_map = base_type == 0 ? 356 si->ipipe_itm_map[pipe]: 357 si->itm_map; 358 359 if (write) { 360 break_after_first = FALSE; 361 } 362 } 363 for (itm = 0; itm < NUM_ITM(unit); itm++) { 364 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 365 if (!(itm_map & (1 << itm))) { 366 continue; 367 } 368 reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[itm]; 369 } 370 if (write) { 371 SOC_IF_ERROR_RETURN 372 (soc_reg_set(unit, reg, port, index, *data)); 373 } else { 374 SOC_IF_ERROR_RETURN 375 (soc_reg_get(unit, reg, port, index, data)); 376 } 377 if (break_after_first) { 378 break; 379 } 380 } 381 } 382 break; 383 case 2: /* IPIPE */ 384 case 3: /* EPIPE */ 385 if (itm >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { 386 reg = SOC_REG_UNIQUE_ACC(unit, reg)[itm]; 387 } 388 soc_tomahawk3_pipe_map_get(unit, &base_index_map); 389 if (base_index != -1) { 390 base_index_map &= 1 << base_index; 391 if (base_index_map == 0) { 392 return SOC_E_PARAM; 393 } 394 } 395 396 for (base_index = 0; base_index < _TH3_PIPES_PER_DEV; base_index++) { 397 if (!(base_index_map & (1 << base_index))) { 398 continue; 399 } 400 /* Select the right ITM for IPIPE and both ITMs for EPIPE*/ 401 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 402 itm_map = base_type == 2 ? 403 si->ipipe_itm_map[base_index]: 404 si->itm_map; 405 if (write) { 406 break_after_first = FALSE; 407 } 408 } 409 /*Check the ITM value passed through params*/ 410 if (itm >=0) { 411 itm_map &= (1 << itm); 412 } 413 for (itm = 0; itm < NUM_ITM(unit); itm++) { 414 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 415 if (!(itm_map & (1 << itm))) { 416 continue; 417 } 418 reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[itm]; 419 } 420 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK; 421 if (write) { 422 SOC_IF_ERROR_RETURN 423 (soc_reg_set(unit, reg, inst, index, *data)); 424 } else { 425 SOC_IF_ERROR_RETURN 426 (soc_reg_get(unit, reg, inst, index, data)); 427 } 428 if (break_after_first) { 429 break; 430 } 431 } 432 } 433 break; 434 case 4: /* CHIP */ 435 if (write) { 436 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data)); 437 } else { 438 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data)); 439 } 440 break; 441 case 5: /* ITM */ 442 if (itm >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { 443 reg = SOC_REG_UNIQUE_ACC(unit, reg)[itm]; 444 } 445 446 if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL || 447 SOC_REG_ACC_TYPE(unit, reg) < NUM_ITM(unit)) { 448 base_index_map = 1; 449 } else if (base_index == -1) { 450 base_index_map = 0x3; /*Use both ITMs*/ 451 } else { 452 base_index_map = 1 << base_index; 453 } 454 455 /* Loop through ITM(s) only on UNIQUE type base register */ 456 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 457 itm_map=si->itm_map; 458 break_after_first = FALSE; 459 } 460 461 for (loop_index = 0; loop_index < NUM_ITM(unit); loop_index++) { 462 if (!(base_index_map & (1 << loop_index))) { 463 continue; 464 } 465 for (itm = 0; itm < NUM_ITM(unit); itm++) { 466 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 467 if (!(itm_map & (1 << itm))) { 468 continue; 469 } 470 reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[itm]; 471 } 472 inst = loop_index | SOC_REG_ADDR_INSTANCE_MASK; 473 if (write) { 474 SOC_IF_ERROR_RETURN 475 (soc_reg_set(unit, reg, inst, index, *data)); 476 } else { 477 SOC_IF_ERROR_RETURN 478 (soc_reg_get(unit, reg, inst, index, data)); 479 } 480 if (break_after_first) { 481 break; 482 } 483 } 484 } 485 break; 486 /* No default case as base_type can have value only between 0-5 */ 487 } 488 489 return SOC_E_NONE; 490 } 491 492 /* 493 *Function: soc_tomahawk3_itm_reg32_set 494 *Purpose: Set ITM register 495 */ 496 int 497 soc_tomahawk3_itm_reg32_set(int unit, soc_reg_t reg, int itm, int base_index, 498 int index, uint32 data) 499 { 500 uint64 data64; 501 502 COMPILER_64_SET(data64, 0, data); 503 SOC_IF_ERROR_RETURN(_soc_tomahawk3_itm_reg_access(unit, reg, itm, base_index, 504 index, &data64, TRUE)); 505 506 return SOC_E_NONE; 507 } 508 509 /* 510 *Function: soc_tomahawk3_itm_reg32_get 511 *Purpose: Get ITM register 512 */ 513 int 514 soc_tomahawk3_itm_reg32_get(int unit, soc_reg_t reg, int itm, int base_index, 515 int index, uint32 *data) 516 { 517 uint64 data64; 518 519 COMPILER_64_SET(data64, 0, *data); 520 SOC_IF_ERROR_RETURN(_soc_tomahawk3_itm_reg_access(unit, reg, itm, base_index, 521 index, &data64, FALSE)); 522 *data = COMPILER_64_LO(data64); 523 524 return SOC_E_NONE; 525 } 526 527 /* 528 *Function: soc_tomahawk3_itm_reg_set 529 *Purpose: Set ITM register 530 */ 531 int 532 soc_tomahawk3_itm_reg_set(int unit, soc_reg_t reg, int itm, int base_index, 533 int index, uint64 data) 534 { 535 return _soc_tomahawk3_itm_reg_access(unit, reg, itm, base_index, 536 index, &data, TRUE); 537 } 538 539 /* 540 *Function: soc_tomahawk3_itm_reg_get 541 *Purpose: Get ITM register 542 */ 543 int 544 soc_tomahawk3_itm_reg_get(int unit, soc_reg_t reg, int itm, int base_index, 545 int index, uint64 *data) 546 { 547 return _soc_tomahawk3_itm_reg_access(unit, reg, itm, base_index, 548 index, data, FALSE); 549 } 550 551 /* 552 *Function to check if the EB, base_index combination is valid 553 *Base Type: IPORT/IPIPE: Can be in any of the 8 EBs 554 *Base Type: EPORT/EPIPE: Can only be in one EB corresponding to the port/pipe. 555 *Base Type: ITM: Can be in any EB 556 *EB should be valied for device config (esp. for half setups) 557 */ 558 int 559 soc_tomahawk3_eb_base_index_check(int unit, int base_type, int eb, 560 int base_index, char *msg) 561 { 562 soc_info_t *si; 563 int pipe; 564 uint32 map, pipe_map =0; 565 char *base_name; 566 567 568 si = &SOC_INFO(unit); 569 570 if (eb == -1 || base_index == -1) { 571 return SOC_E_NONE; 572 } 573 574 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 575 576 if ((eb < _TH3_PIPES_PER_DEV) && ((pipe_map & (1 << eb)) == 0)) { 577 if (msg) { 578 LOG_CLI((BSL_META_U(unit, 579 "%s: EB%d is not in config\n"), 580 msg, eb)); 581 } 582 return SOC_E_PARAM; 583 } 584 585 switch (base_type) { 586 case 0: /* IPORT */ 587 case 1: /* EPORT */ 588 base_name = base_type == 0 ? "IPORT" : "EPORT"; 589 pipe = si->port_pipe[base_index]; 590 if (pipe == -1) { 591 if (msg) { 592 LOG_CLI((BSL_META_U(unit, 593 "%s: %s%d is not in config\n"), 594 msg, base_name, base_index)); 595 } 596 } else if (eb < _TH3_PIPES_PER_DEV) { /* Unique access type */ 597 map = base_type == 0 ? 598 pipe_map : (1 << eb); 599 if (msg != NULL) { 600 LOG_CLI((BSL_META_U(unit, 601 "%s: %s%d is not in EB%d\n"), 602 msg, base_name, base_index, eb)); 603 } 604 } else { 605 break; 606 } 607 return SOC_E_PARAM; 608 case 2: /* IPIPE */ 609 case 3: /* EPIPE */ 610 if (base_type == 2) { 611 base_name = "IPIPE"; 612 map = pipe_map; 613 } else { 614 base_name = "EPIPE"; 615 map = (1 << eb); 616 } 617 if (map == 0) { 618 if (msg) { 619 LOG_CLI((BSL_META_U(unit, 620 "%s: %s%d is not in config\n"), 621 msg, base_name, base_index)); 622 } 623 } else if (eb < _TH3_PIPES_PER_DEV) { /* Unique access type */ 624 if (map & (1 << eb)) { 625 break; 626 } 627 if (msg != NULL) { 628 LOG_CLI((BSL_META_U(unit, 629 "%s: %s%d is not in EB%d\n"), 630 msg, base_name, base_index, eb)); 631 } 632 } else { 633 break; 634 } 635 return SOC_E_PARAM; 636 case 4: /* CHIP */ 637 break; 638 case 5: /* ITM */ 639 if ((si->itm_map & (1 << base_index)) == 0) { 640 if (msg != NULL) { 641 LOG_CLI((BSL_META_U(unit, 642 "%s: ITM%d is not in config\n"), 643 msg, base_index)); 644 } 645 } else { 646 break; 647 } 648 return SOC_E_PARAM; 649 } 650 651 return SOC_E_NONE; 652 } 653 654 /* 655 *Function: _soc_tomahawk3_eb_reg_check 656 *Purpose: Check if resigter is in EB block and passed EB value is in range 657 * Override itm with access_type for unique memories 658 * Call check to verify EB/base_index combination 659 */ 660 STATIC int 661 _soc_tomahawk3_eb_reg_check(int unit, soc_reg_t reg, int eb, int base_index) 662 { 663 int acc_type, base_type; 664 665 if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_EB)) { 666 LOG_CLI((BSL_META_U(unit, 667 "%s is not EB register\n"), SOC_REG_NAME(unit, reg))); 668 return SOC_E_PARAM; 669 } 670 671 if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */ 672 if (eb == -1 || eb >= _TH3_PIPES_PER_DEV) { 673 LOG_CLI((BSL_META_U(unit, 674 "%s bad EB value %d\n"), 675 SOC_REG_NAME(unit, reg), eb)); 676 return SOC_E_PARAM; 677 } 678 } else { 679 acc_type = SOC_REG_ACC_TYPE(unit, reg); 680 if (acc_type < _TH3_PIPES_PER_DEV) { /* UNIQUE per EB register */ 681 if (eb != acc_type) { 682 LOG_CLI((BSL_META_U(unit, 683 "Ovveride EB value %d with ACC_TYPE of %s\n"), 684 eb, SOC_REG_NAME(unit, reg))); 685 } 686 eb = acc_type; 687 } else { /* non-UNIQUE register */ 688 return SOC_E_NONE; 689 } 690 } 691 /*retrieve bits [25:23] of memory address for base_type*/ 692 base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7; 693 694 return soc_tomahawk3_eb_base_index_check(unit, base_type, eb, base_index, 695 SOC_REG_NAME(unit, reg)); 696 } 697 698 /* 699 *Function: _soc_tomahawk3_eb_reg_access 700 *Purpose: Set/get resgisters in EB block 701 */ 702 STATIC int 703 _soc_tomahawk3_eb_reg_access(int unit, soc_reg_t reg, int eb, int base_index, 704 int index, uint64 *data, int write) 705 { 706 soc_info_t *si; 707 int port; 708 int base_type, loop_index; 709 uint32 base_index_map; 710 soc_pbmp_t base_index_pbmp; 711 uint32 inst; 712 713 si = &SOC_INFO(unit); 714 /*retrieve bits [25:23] of memory address for base_type*/ 715 base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7; 716 717 if (eb >= 0 && base_index >= 0) { 718 SOC_IF_ERROR_RETURN 719 (_soc_tomahawk3_eb_reg_check(unit, reg, eb, base_index)); 720 } 721 722 switch (base_type) { 723 case 0: /* IPORT */ 724 case 1: /* EPORT */ 725 /* No unique access type for such base_type */ 726 if (base_index == -1) { 727 SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit)); 728 } else { 729 /* This argument is logical port, same as soc_reg_get/set */ 730 SOC_PBMP_PORT_SET(base_index_pbmp, base_index); 731 } 732 733 SOC_PBMP_ITER(base_index_pbmp, port) { 734 if (write) { 735 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, index, *data)); 736 } else { 737 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, index, data)); 738 } 739 } 740 break; 741 case 2: /* IPIPE */ 742 case 3: /* EPIPE */ 743 /* No unique access type for such base_type */ 744 soc_tomahawk3_pipe_map_get(unit, &base_index_map); 745 if (base_index != -1) { 746 base_index_map &= 1 << base_index; 747 if (base_index_map == 0) { 748 return SOC_E_PARAM; 749 } 750 } 751 752 for (loop_index = 0; loop_index < _TH3_PIPES_PER_DEV; loop_index++) { 753 if (!(base_index_map & (1 << loop_index))) { 754 continue; 755 } 756 inst = loop_index | SOC_REG_ADDR_INSTANCE_MASK; 757 if (write) { 758 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data)); 759 } else { 760 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data)); 761 } 762 } 763 break; 764 case 4: /* CHIP */ 765 if (write) { 766 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data)); 767 } else { 768 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data)); 769 } 770 break; 771 case 5: /* ITM */ 772 /* No unique access type for such base_type */ 773 if (base_index == -1) { 774 base_index_map = si->itm_map; 775 } else { 776 base_index_map = 1 << base_index; 777 } 778 779 for (loop_index = 0; loop_index < NUM_ITM(unit); loop_index++) { 780 if (!(base_index_map & (1 << loop_index))) { 781 continue; 782 } 783 inst = loop_index | SOC_REG_ADDR_INSTANCE_MASK; 784 if (write) { 785 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data)); 786 } else { 787 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data)); 788 } 789 } 790 break; 791 default: 792 return SOC_E_INTERNAL; 793 } 794 795 return SOC_E_NONE; 796 } 797 798 /* 799 *Function: _soc_tomahawk3_eb_reg32_set 800 *Purpose: Set resgisters in EB block 801 */ 802 int 803 soc_tomahawk3_eb_reg32_set(int unit, soc_reg_t reg, int eb, int base_index, 804 int index, uint32 data) 805 { 806 uint64 data64; 807 808 COMPILER_64_SET(data64, 0, data); 809 SOC_IF_ERROR_RETURN(_soc_tomahawk3_eb_reg_access(unit, reg, eb, base_index, 810 index, &data64, TRUE)); 811 812 return SOC_E_NONE; 813 } 814 815 /* 816 *Function: _soc_tomahawk3_eb_reg32_get 817 *Purpose: Get resgisters in EB block 818 */ 819 int 820 soc_tomahawk3_eb_reg32_get(int unit, soc_reg_t reg, int eb, int base_index, 821 int index, uint32 *data) 822 { 823 uint64 data64; 824 825 COMPILER_64_SET(data64, 0, *data); 826 SOC_IF_ERROR_RETURN(_soc_tomahawk3_eb_reg_access(unit, reg, eb, base_index, 827 index, &data64, FALSE)); 828 *data = COMPILER_64_LO(data64); 829 830 return SOC_E_NONE; 831 } 832 833 /* 834 *Function: _soc_tomahawk3_eb_reg_set 835 *Purpose: Set resgisters in EB block 836 */ 837 int 838 soc_tomahawk3_eb_reg_set(int unit, soc_reg_t reg, int eb, int base_index, 839 int index, uint64 data) 840 { 841 return _soc_tomahawk3_eb_reg_access(unit, reg, eb, base_index, 842 index, &data, TRUE); 843 } 844 845 /* 846 *Function: _soc_tomahawk3_eb_reg_get 847 *Purpose: Get resgisters in EB block 848 */ 849 int 850 soc_tomahawk3_eb_reg_get(int unit, soc_reg_t reg, int eb, int base_index, 851 int index, uint64 *data) 852 { 853 return _soc_tomahawk3_eb_reg_access(unit, reg, eb, base_index, 854 index, data, FALSE); 855 } 856 857 /* 858 *Function: _soc_tomahawk3_itm_mem_check 859 *Purpose: Check 1. If memory is in ITM block 860 * 2. If the passed ITM value is in range 861 * Override ITM value with access type of the ITM memory 862 */ 863 STATIC int 864 _soc_tomahawk3_itm_mem_check(int unit, soc_mem_t mem, int itm, int base_index) 865 { 866 int block_info_index, acc_type, base_type; 867 868 block_info_index = SOC_MEM_BLOCK_ANY(unit, mem); 869 if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_ITM) { 870 LOG_CLI((BSL_META_U(unit, 871 "%s is not ITM memory\n"), SOC_MEM_NAME(unit, mem))); 872 return SOC_E_PARAM; 873 } 874 875 if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { /* UNIQUE base memory */ 876 if (itm == -1 || itm >= NUM_ITM(unit)) { 877 LOG_CLI((BSL_META_U(unit, 878 "%s bad ITM value %d\n"), 879 SOC_MEM_NAME(unit, mem), itm)); 880 return SOC_E_PARAM; 881 } 882 } else { 883 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 884 if (acc_type < NUM_ITM(unit)) { /* UNIQUE per ITM memory */ 885 if (itm != acc_type) { 886 LOG_CLI((BSL_META_U(unit, 887 "Ovveride ITM value %d with ACC_TYPE of %s\n"), 888 itm, SOC_MEM_NAME(unit, mem))); 889 itm = acc_type; 890 } 891 } else { /* non-UNIQUE memory */ 892 return SOC_E_NONE; 893 } 894 } 895 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 896 897 return soc_tomahawk3_itm_base_index_check(unit, base_type, itm, base_index, 898 SOC_MEM_NAME(unit, mem)); 899 } 900 901 /*Function to retrieve the ITM memory list corresponding to specific ITM or base_type 902 * 903 * Base Type:0/1: IPORT/EPORT: No MMU memories available with this base type 904 * Base Type:2: IPIPE: returns _PIPEx memory list 905 * Base Type:3: EPIPE: returns _ITMx_PIPEy if acc_type is UNIQUE 906 * returns _PIPEx memories for non-unique memories 907 * Base Type:4: CHIP: returns _ITMx mem list if acc_type = UNIQUE 908 * Base Type:5: ITM: returns _ITMx mem list if acc_type = UNIQUE 909 */ 910 STATIC int 911 _soc_tomahawk3_retrieve_itm_mem_list(int unit, soc_mem_t mem, int itm, 912 int base_index, soc_mem_t *mem_list, int max_mem_cnt, int *number_of_mems) 913 { 914 #define _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 31 915 soc_info_t *si; 916 int base_type, acc_type; 917 uint32 base_index_map, itm_map=0; 918 int mem_index = 0; 919 int loop_index; 920 921 si = &SOC_INFO(unit); 922 /*retrieve bits [25:23] of memory address for base_type*/ 923 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 924 925 switch (base_type) { 926 case 2: /* IPIPE */ 927 case 3: /* EPIPE */ 928 if (max_mem_cnt < (NUM_ITM(unit) * _TH3_PIPES_PER_DEV)) { 929 /*Max combinations is 2 ITMs * 8 PIPEs */ 930 return SOC_E_INTERNAL; 931 } 932 /* Memory doesnt have enumeration */ 933 if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) { 934 mem_list[mem_index++] = mem; 935 break; 936 } 937 soc_tomahawk3_pipe_map_get(unit, &base_index_map); 938 if (base_index != -1) { 939 base_index_map &= (1 << base_index); 940 if (base_index_map == 0) { 941 return SOC_E_PARAM; 942 } 943 } 944 for (loop_index = 0; loop_index < _TH3_PIPES_PER_DEV; loop_index++) { 945 if (!(base_index_map & (1 << loop_index))) { 946 continue; 947 } 948 acc_type = SOC_MEM_ACC_TYPE 949 (unit, SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, 0)); 950 if ((acc_type != _TH3_MMU_SBUS_ACC_TYPE_UNIQUE)|| base_type ==2) { 951 /* Single/Duplicate acc_type memories only have _PIPEx*/ 952 mem_list[mem_index++] = 953 SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, loop_index); 954 } else { 955 /*Unique acc_type memories with _ITMx_PIPEy*/ 956 itm_map = si->itm_map; 957 if (itm != -1) { 958 itm_map &= (1 << itm); 959 if (itm_map == 0) { 960 return SOC_E_PARAM; 961 } 962 } 963 for (itm = 0; itm < NUM_ITM(unit); itm++) { 964 if (!(itm_map & (1 << itm))) { 965 continue; 966 } 967 mem_list[mem_index++] = 968 SOC_MEM_UNIQUE_ACC_ITM_PIPE 969 (unit, mem, itm, loop_index); 970 LOG_ERROR(BSL_LS_SOC_COMMON, 971 (BSL_META_U(unit, 972 "mmu_mem %d added to list \n"), 973 SOC_MEM_UNIQUE_ACC_ITM_PIPE 974 (unit, mem, itm, loop_index))); 975 } 976 } 977 } 978 break; 979 case 4: /* CHIP */ 980 case 5: /* ITM */ 981 if (max_mem_cnt < NUM_ITM(unit)) { 982 /*Max combinations is 2 ITMs */ 983 return SOC_E_INTERNAL; 984 } 985 986 /* No memory enumeration available. Non-unique memories */ 987 if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) { 988 mem_list[mem_index++] = mem; 989 break; 990 } 991 itm_map = si->itm_map; 992 if (itm != -1) { 993 itm_map &= (1 << itm); 994 if (itm_map == 0) { 995 return SOC_E_PARAM; 996 } 997 } 998 if (base_index != -1) { 999 itm_map &= (1 << base_index); 1000 if (itm_map == 0) { 1001 return SOC_E_PARAM; 1002 } 1003 } 1004 1005 /* Unique memories with _ITMx */ 1006 for (loop_index = 0; loop_index < NUM_ITM(unit); loop_index++) { 1007 if (!(itm_map & (1 << loop_index))) { 1008 continue; 1009 } 1010 mem_list[mem_index++] = 1011 SOC_MEM_UNIQUE_ACC_ITM(unit, mem, loop_index); 1012 } 1013 break; 1014 case 0: /* IPORT */ 1015 case 1: /* EPORT */ 1016 default: 1017 return SOC_E_INTERNAL; 1018 } 1019 *number_of_mems = mem_index; 1020 1021 #undef _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 1022 return SOC_E_NONE; 1023 } 1024 1025 /*Function to read/write all ITM memories based on memory list retrieval*/ 1026 STATIC int 1027 _soc_tomahawk3_itm_mem_access(int unit, soc_mem_t mem, int itm, int base_index, 1028 int copyno, int offset_in_section, 1029 void *entry_data, int write) 1030 { 1031 #define _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 31 1032 int mem_index, mem_cnt; 1033 int index; 1034 soc_mem_t mem_list[64] = {INVALIDm}; 1035 1036 if (itm >= 0 && base_index >= 0) { 1037 SOC_IF_ERROR_RETURN 1038 (_soc_tomahawk3_itm_mem_check(unit, mem, itm, base_index)); 1039 } 1040 SOC_IF_ERROR_RETURN 1041 (_soc_tomahawk3_retrieve_itm_mem_list (unit, mem, itm, base_index, 1042 mem_list, 64, &mem_cnt)); 1043 index = offset_in_section; 1044 if(write) { 1045 /*Write to all memories in list*/ 1046 for (mem_index = 0; mem_index < mem_cnt; mem_index ++) { 1047 SOC_IF_ERROR_RETURN(soc_mem_write 1048 (unit, mem_list[mem_index], copyno, index, entry_data)); 1049 } 1050 } else { 1051 /*Read only from the 1st memory in list*/ 1052 SOC_IF_ERROR_RETURN(soc_mem_read 1053 (unit, mem_list[0], copyno, index, entry_data)); 1054 } 1055 #undef _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 1056 return SOC_E_NONE; 1057 } 1058 1059 /*Function to read/write all ITM memories based on memory list retrieval*/ 1060 STATIC int 1061 _soc_tomahawk3_itm_mem_access_range(int unit, soc_mem_t mem, int itm, int base_index, 1062 int copyno, int idx_min, int idx_max, 1063 void *entry_data, int write) 1064 { 1065 #define _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 31 1066 int mem_cnt; 1067 soc_mem_t mem_list[64] = {INVALIDm}; 1068 1069 if (itm >= 0 && base_index >= 0) { 1070 SOC_IF_ERROR_RETURN 1071 (_soc_tomahawk3_itm_mem_check(unit, mem, itm, base_index)); 1072 } 1073 SOC_IF_ERROR_RETURN 1074 (_soc_tomahawk3_retrieve_itm_mem_list (unit, mem, itm, base_index, 1075 mem_list, 64, &mem_cnt)); 1076 if(write) { 1077 /* Write goes here, but since this was made for WB, not supported */ 1078 } else { 1079 /*Read only from the 1st memory in list, but read it all*/ 1080 SOC_IF_ERROR_RETURN(soc_mem_read_range 1081 (unit, mem_list[0], MEM_BLOCK_ANY, 1082 idx_min, idx_max, entry_data)); 1083 } 1084 #undef _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 1085 return SOC_E_NONE; 1086 } 1087 /* 1088 * Function: soc_tomahawk3_itm_mem_write 1089 * Purpose: Write to memories of different acc_type/base_type in the ITM block 1090 */ 1091 int 1092 soc_tomahawk3_itm_mem_write(int unit, soc_mem_t mem, int itm, int base_index, 1093 int copyno, int offset_in_section, void *entry_data) 1094 { 1095 return _soc_tomahawk3_itm_mem_access(unit, mem, itm, base_index, copyno, 1096 offset_in_section, entry_data, TRUE); 1097 } 1098 1099 /* 1100 * Function: soc_tomahawk3_itm_mem_read 1101 * Purpose: Read memories of different acc_type/base_type in the ITM block 1102 */ 1103 int 1104 soc_tomahawk3_itm_mem_read(int unit, soc_mem_t mem, int itm, int base_index, 1105 int copyno, int offset_in_section, void *entry_data) 1106 { 1107 return _soc_tomahawk3_itm_mem_access(unit, mem, itm, base_index, copyno, 1108 offset_in_section, entry_data, FALSE); 1109 } 1110 1111 int 1112 soc_tomahawk3_itm_mem_read_range(int unit, soc_mem_t mem, int itm, int base_index, 1113 int copyno, int idx_min, int idx_max, void *entry_data) 1114 { 1115 return _soc_tomahawk3_itm_mem_access_range(unit, mem, itm, base_index, copyno, 1116 idx_min, idx_max, entry_data, FALSE); 1117 } 1118 STATIC int 1119 _soc_tomahawk3_eb_mem_check(int unit, soc_mem_t mem, int eb, int base_index) 1120 { 1121 int block_info_index, acc_type, base_type; 1122 1123 block_info_index = SOC_MEM_BLOCK_ANY(unit, mem); 1124 if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_EB) { 1125 LOG_CLI((BSL_META_U(unit, 1126 "%s is not EB memory\n"), SOC_MEM_NAME(unit, mem))); 1127 return SOC_E_PARAM; 1128 } 1129 1130 if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { /* UNIQUE base memory */ 1131 if (eb == -1 || eb >= _TH3_PIPES_PER_DEV) { 1132 LOG_CLI((BSL_META_U(unit, 1133 "%s bad PIPE value %d\n"), 1134 SOC_MEM_NAME(unit, mem), eb)); 1135 return SOC_E_PARAM; 1136 } 1137 } else { 1138 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 1139 if (acc_type < _TH3_PIPES_PER_DEV) { /* UNIQUE per EB memory */ 1140 if (eb != acc_type) { 1141 LOG_CLI((BSL_META_U(unit, 1142 "Ovveride EB value %d with ACC_TYPE of %s\n"), 1143 eb, SOC_MEM_NAME(unit, mem))); 1144 eb = acc_type; 1145 } 1146 } else { /* non-UNIQUE memory */ 1147 return SOC_E_NONE; 1148 } 1149 } 1150 /*retrieve bits [25:23] of memory address for base_type*/ 1151 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 1152 1153 return soc_tomahawk3_eb_base_index_check(unit, base_type, eb, base_index, 1154 SOC_MEM_NAME(unit, mem)); 1155 } 1156 1157 /*Function to retrieve the EB memory list corresponding to specific EB or base_type 1158 * 1159 * Base Type:0/1: IPORT/EPORT: No MMU memories available with this base type 1160 * Base Type:3: EPIPE: returns _PIPEx memory list 1161 * Base Type:2: IPIPE: returns _EBx_PIPEy if acc_type is UNIQUE 1162 * returns _PIPEx memories for non-unique memories 1163 * Base Type:4: CHIP: returns _PIPEx mem list if acc_type = UNIQUE 1164 * Base Type:5: ITM: returns _EBx_ITMy mem list if acc_type = UNIQUE 1165 * returns _ITMx mem list for non-unique memories 1166 */ 1167 STATIC int 1168 _soc_tomahawk3_retrieve_eb_mem_list (int unit, soc_mem_t mem, int eb, 1169 int base_index, soc_mem_t *mem_list, int max_mem_cnt, 1170 int *mem_cnt) 1171 { 1172 #define _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 31 1173 soc_info_t *si; 1174 int mem_index; 1175 int base_type, acc_type; 1176 uint32 base_index_map, eb_map=0; 1177 int loop_index; 1178 1179 si = &SOC_INFO(unit); 1180 /*retrieve bits [25:23] of memory address for base_type*/ 1181 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 1182 mem_index = 0; 1183 1184 if (eb >= 0 && base_index >= 0) { 1185 SOC_IF_ERROR_RETURN 1186 (_soc_tomahawk3_eb_mem_check(unit, mem, eb, base_index)); 1187 } 1188 switch (base_type) { 1189 case 2: /* IPIPE */ 1190 case 3: /* EPIPE */ 1191 if (max_mem_cnt < (_TH3_PIPES_PER_DEV * _TH3_PIPES_PER_DEV)) { 1192 /*Max combinations is 8 EBs * 8 PIPEs*/ 1193 return SOC_E_INTERNAL; 1194 } 1195 /* no _PIPEx, no _ITMx */ 1196 if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) { 1197 mem_list[mem_index++] = mem; 1198 break; 1199 } 1200 soc_tomahawk3_pipe_map_get(unit, &base_index_map); 1201 eb_map = base_index_map; 1202 if (base_index != -1) { 1203 base_index_map &= (1 << base_index); 1204 if (base_index_map == 0) { 1205 return SOC_E_PARAM; 1206 } 1207 } 1208 for (loop_index = 0; loop_index < _TH3_PIPES_PER_DEV; loop_index++) { 1209 if (!(base_index_map & (1 << loop_index))) { 1210 continue; 1211 } 1212 acc_type = SOC_MEM_ACC_TYPE 1213 (unit, SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, 0)); 1214 if ((acc_type != _TH3_MMU_SBUS_ACC_TYPE_UNIQUE)|| (base_type ==3)) { 1215 /* Single/Duplicate acc_type memories only have _PIPEx*/ 1216 /*Base_type EPIPE memories in block EB have same behavior as Single*/ 1217 mem_list[mem_index++] = 1218 SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, loop_index); 1219 } else { 1220 /*Unique acc_type memories with _EBx_PIPEy*/ 1221 for (eb = 0; eb < _TH3_PIPES_PER_DEV; eb++) { 1222 if (!(eb_map & (1 << eb))) { 1223 continue; 1224 } 1225 mem_list[mem_index++] = 1226 SOC_MEM_UNIQUE_ACC_EB_PIPE 1227 (unit, mem, eb, loop_index); 1228 } 1229 } 1230 } 1231 break; 1232 case 4: /* CHIP */ 1233 if (max_mem_cnt < _TH3_PIPES_PER_DEV * _TH3_PIPES_PER_DEV) { 1234 /*Max combinations is 8 EBs*/ 1235 return SOC_E_INTERNAL; 1236 } 1237 if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) { 1238 mem_list[mem_index++] = mem; 1239 break; 1240 } 1241 soc_tomahawk3_pipe_map_get(unit, &eb_map); 1242 if (eb != -1) { 1243 eb_map &= (1 << eb); 1244 if (eb_map == 0) { 1245 return SOC_E_PARAM; 1246 } 1247 } 1248 /*Unique memories across different EBs are enumerated with _PIPEx */ 1249 for (eb = 0; eb < _TH3_PIPES_PER_DEV; eb++) { 1250 if (!(eb_map & (1 << eb))) { 1251 continue; 1252 } 1253 mem_list[mem_index++] = 1254 SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, eb); 1255 } 1256 break; 1257 case 5: /* ITM */ 1258 if (max_mem_cnt < NUM_ITM(unit) * _TH3_PIPES_PER_DEV) { 1259 /*Max combinations is 8 EBs * 2 ITMs */ 1260 return SOC_E_INTERNAL; 1261 } 1262 /* no _ITMx, _PIPEx */ 1263 if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) { 1264 mem_list[mem_index++] = mem; 1265 break; 1266 } 1267 soc_tomahawk3_pipe_map_get(unit, &eb_map); 1268 if (eb != -1) { 1269 eb_map &= (1 << eb); 1270 if (eb_map == 0) { 1271 return SOC_E_PARAM; 1272 } 1273 } 1274 base_index_map = si->itm_map; 1275 if (base_index != -1) { 1276 base_index_map &= (1 << base_index); 1277 if (base_index_map== 0) { 1278 return SOC_E_PARAM; 1279 } 1280 } 1281 for (loop_index = 0; loop_index < NUM_ITM(unit); loop_index++) { 1282 if (!(base_index_map & (1 << loop_index))) { 1283 continue; 1284 } 1285 acc_type = SOC_MEM_ACC_TYPE 1286 (unit, SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, 0)); 1287 if ((acc_type != _TH3_MMU_SBUS_ACC_TYPE_UNIQUE)) { 1288 /* Single/Duplicate acc_type memories only have _ITMx*/ 1289 mem_list[mem_index++] = 1290 SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, loop_index); 1291 } else { 1292 /*Unique acc_type memories with _EBx_ITMy*/ 1293 for (eb = 0; eb < _TH3_PIPES_PER_DEV; eb++) { 1294 if (!(eb_map & (1 << eb))) { 1295 continue; 1296 } 1297 mem_list[mem_index++] = 1298 SOC_MEM_UNIQUE_ACC_EB_ITM 1299 (unit, mem,eb, loop_index); 1300 } 1301 } 1302 } 1303 break; 1304 case 0: /* IPORT */ 1305 case 1: /* EPORT */ 1306 default: 1307 /*No MMU memories supported with base_tyep IPORT/EPORT*/ 1308 return SOC_E_INTERNAL; 1309 } 1310 *mem_cnt = mem_index; 1311 1312 #undef _TH3_MMU_SBUS_ACC_TYPE_UNIQUE 1313 return SOC_E_NONE; 1314 } 1315 1316 /*Function : _soc_tomahawk3_eb_mem_access 1317 *Purpose: read/write memories in EB 1318 */ 1319 STATIC int 1320 _soc_tomahawk3_eb_mem_access(int unit, soc_mem_t mem, int eb, int base_index, 1321 int copyno, int offset_in_section, 1322 void *entry_data, int write) 1323 { 1324 int mem_index, mem_cnt; 1325 int index; 1326 soc_mem_t mem_list[64] = {INVALIDm}; 1327 1328 if (eb >= 0 && base_index >= 0) { 1329 SOC_IF_ERROR_RETURN 1330 (_soc_tomahawk3_eb_mem_check(unit, mem, eb, base_index)); 1331 } 1332 _soc_tomahawk3_retrieve_eb_mem_list (unit, mem, eb, base_index, 1333 mem_list, 64, &mem_cnt); 1334 index = offset_in_section; 1335 if(write) { 1336 /*Write to all memories in list*/ 1337 for (mem_index = 0; mem_index < mem_cnt; mem_index ++) { 1338 SOC_IF_ERROR_RETURN(soc_mem_write 1339 (unit, mem_list[mem_index], copyno, index, entry_data)); 1340 } 1341 } else { 1342 /*Read only from the 1st memory in list*/ 1343 SOC_IF_ERROR_RETURN(soc_mem_read 1344 (unit, mem_list[0], copyno, index, entry_data)); 1345 } 1346 return SOC_E_NONE; 1347 } 1348 1349 /*Function : _soc_tomahawk3_eb_mem_write 1350 *Purpose: write memories in EB 1351 */ 1352 int 1353 soc_tomahawk3_eb_mem_write(int unit, soc_mem_t mem, int eb, int base_index, 1354 int copyno, int offset_in_section, void *entry_data) 1355 { 1356 return _soc_tomahawk3_eb_mem_access(unit, mem, eb, base_index, copyno, 1357 offset_in_section, entry_data, TRUE); 1358 } 1359 1360 /*Function : _soc_tomahawk3_eb_mem_read 1361 *Purpose: read memories in EB 1362 */ 1363 int 1364 soc_tomahawk3_eb_mem_read(int unit, soc_mem_t mem, int eb, int base_index, 1365 int copyno, int offset_in_section, void *entry_data) 1366 { 1367 return _soc_tomahawk3_eb_mem_access(unit, mem, eb, base_index, copyno, 1368 offset_in_section, entry_data, FALSE); 1369 } 1370 1371 /* 1372 *Function: soc_retrieve_mem_list_for_port 1373 *Purpose: Function to retrieve the memory expansion base on logical port # and 1374 *base memory name 1375 * Users of this function do not need the knowledge of memory's 1376 * base_type, access_type or block 1377 * Fnction only returns the memory list and the address need to be calculated by 1378 * the user 1379 */ 1380 int 1381 soc_th3_retrieve_mmu_mem_list_for_port(int unit, int port, soc_mem_t mem, int blk_num, 1382 soc_mem_t *mem_list, int max_mem_cnt, int *mem_cnt) 1383 { 1384 int block_info_index, base_type; 1385 int pipe, base_index; 1386 soc_info_t *si = &SOC_INFO(unit); 1387 1388 pipe = si->port_pipe[port]; 1389 /*retrieve bits [25:23] of memory address for base_type*/ 1390 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 1391 1392 switch(base_type) { 1393 case 2: /*IPIPE*/ 1394 case 3: /*EPIPE*/ 1395 base_index = pipe; 1396 break; 1397 case 4: /*CHIP*/ 1398 base_index = 0; 1399 break; 1400 case 5: /*ITM*/ 1401 /*ITM 0 if port is in pipes 0,1,6,7 else ITM1*/ 1402 base_index = blk_num; 1403 break; 1404 default: 1405 base_index = -1; 1406 break; 1407 } 1408 1409 block_info_index = SOC_MEM_BLOCK_ANY(unit, mem); 1410 1411 if (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_ITM) { 1412 _soc_tomahawk3_retrieve_itm_mem_list (unit, mem, blk_num, base_index, 1413 mem_list, max_mem_cnt, mem_cnt); 1414 } else if (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_EB) { 1415 _soc_tomahawk3_retrieve_eb_mem_list (unit, mem, blk_num, base_index, 1416 mem_list, max_mem_cnt, mem_cnt); 1417 } else { 1418 LOG_CLI((BSL_META_U(unit, 1419 "%s is not ITM or EB memory\n"), SOC_MEM_NAME(unit, mem))); 1420 return SOC_E_PARAM; 1421 } 1422 return SOC_E_NONE; 1423 } 1424 1425 /* 1426 * CPU port (mmu port 32): 48 MC queues 1427 * Loopback port (mmu port 33,97,161,225): 10 MC queues 1428 * Mgmt port (mmu port 96,160): 10 UC, 10 MC queues 1429 */ 1430 int 1431 soc_tomahawk3_num_cosq_init(int unit, int port) 1432 { 1433 soc_info_t *si; 1434 int local_mmu_port, num_uc_q, pipe, pipe_index; 1435 int pipe_queue_base[_TH3_PIPES_PER_DEV]; 1436 int mc_q_mode = 2; /* mc_q_mode defines the number of UC/MC queues 1437 * for all ports except CPU 1438 */ 1439 /*Number of queues per pipe is 1440 *pipe 0: 18 FP, 1 LB, 1 CPU: 18*12 + 12 + 48 = 296 1441 *pipe 1,5: 18FP, 1 LB, 1 MGMT: 18*12 + 12 + 12 = 240 1442 *pipe 2,3,4: 18 FP, 1 LB: 18*12 + 12 = 228 1443 *pipe 6,7: 18 FP, 1 LB, 1 Extra port: 18*12 + 12 + 12 = 240 1444 */ 1445 int num_queues_pipe[] = {276, 240, 228, 228, 228, 240, 240, 240}; 1446 si = &SOC_INFO(unit); 1447 1448 mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, _TH3_MC_Q_MODE_DEFAULT); 1449 1450 if (mc_q_mode == 1) { 1451 num_uc_q = 10; 1452 } else if (mc_q_mode == 2) { 1453 num_uc_q = 8; 1454 } else if (mc_q_mode == 3) { 1455 num_uc_q = 6; 1456 } else { 1457 num_uc_q = 12; 1458 } 1459 pipe_queue_base[0] = 0; 1460 for (pipe_index = 1; pipe_index < _TH3_PIPES_PER_DEV; pipe_index++) { 1461 pipe_queue_base[pipe_index] = num_queues_pipe[pipe_index - 1] + 1462 pipe_queue_base[pipe_index - 1]; 1463 } 1464 local_mmu_port = SOC_TH3_MMU_LOCAL_PORT(unit, port); 1465 pipe = si->port_pipe[port]; 1466 if (IS_CPU_PORT(unit, port)) { 1467 si->port_num_cosq[port] = SOC_TH3_NUM_CPU_QUEUES; 1468 si->port_cosq_base[port] = 1469 (local_mmu_port * SOC_TH3_NUM_GP_QUEUES) + pipe_queue_base[pipe]; 1470 LOG_INFO(BSL_LS_SOC_COMMON, 1471 (BSL_META_U(unit, 1472 "CPU info mmu_port:%d, port_cosq_base:%d\n"), 1473 local_mmu_port, si->port_cosq_base[port])); 1474 } else { 1475 si->port_num_cosq[port] = SOC_TH3_NUM_GP_QUEUES - num_uc_q; 1476 si->port_cosq_base[port] = 1477 (local_mmu_port * SOC_TH3_NUM_GP_QUEUES) + num_uc_q 1478 + pipe_queue_base[pipe]; 1479 si->port_num_uc_cosq[port] = num_uc_q; 1480 si->port_uc_cosq_base[port] = 1481 (local_mmu_port * SOC_TH3_NUM_GP_QUEUES) + 1482 pipe_queue_base[pipe]; 1483 si->port_num_ext_cosq[port] = 0; 1484 } 1485 return SOC_E_NONE; 1486 } 1487 1488 static int 1489 soc_th3_check_mmu_mem_init_done(int unit) { 1490 struct { 1491 soc_reg_t ref_reg; 1492 soc_field_t done_field; 1493 } itm_rf_list[] = { 1494 {MMU_TOQ_STATUSr, INIT_DONEf}, 1495 {MMU_WRED_MEM_INIT_STATUSr, DONEf}, 1496 {INVALIDr, INVALIDf} 1497 }; 1498 struct { 1499 soc_reg_t ref_reg; 1500 soc_field_t done_field; 1501 } pipe_rf_list[] = { 1502 {MMU_EBCFP_INIT_DONEr, DONEf}, 1503 {EBTOQ_STATUSr, INIT_DONEf}, 1504 {INVALIDr, INVALIDf} 1505 }; 1506 uint32 rval; 1507 int idx, done, itm, pipe; 1508 soc_reg_t reg; 1509 soc_field_t field; 1510 soc_info_t *si = &SOC_INFO(unit); 1511 uint32 itm_map = si->itm_map; 1512 uint32 pipe_map; 1513 1514 for (idx = 0; itm_rf_list[idx].ref_reg != INVALIDr; idx++) { 1515 reg = itm_rf_list[idx].ref_reg; 1516 field = itm_rf_list[idx].done_field; 1517 for (itm = 0; itm < NUM_ITM(unit); itm++) { 1518 if (itm_map & (1 << itm)) { 1519 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, 0, itm, &rval)); 1520 done = soc_reg_field_get(unit, reg, rval, field); 1521 if (!done) { 1522 LOG_INFO(BSL_LS_SOC_COSQ, 1523 (BSL_META_U(unit, 1524 " MMU Memory Init done not set after toggling" 1525 "INIT_MEM \n"))); 1526 return SOC_E_INTERNAL; 1527 } 1528 } 1529 } 1530 } 1531 1532 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 1533 for (idx = 0; pipe_rf_list[idx].ref_reg != INVALIDr; idx++) { 1534 reg = pipe_rf_list[idx].ref_reg; 1535 field = pipe_rf_list[idx].done_field; 1536 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) { 1537 if (pipe_map & (1 << pipe)) { 1538 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, 0, pipe, &rval)); 1539 done = soc_reg_field_get(unit, reg, rval, field); 1540 if (!done) { 1541 LOG_ERROR(BSL_LS_SOC_COSQ, 1542 (BSL_META_U(unit, 1543 " MMU Memory Init done not set after toggling" 1544 "INIT_MEM \n"))); 1545 return SOC_E_INTERNAL; 1546 } 1547 } 1548 } 1549 } 1550 return SOC_E_NONE; 1551 } 1552 /*Function to initialize IDB and MMU memories*/ 1553 int 1554 soc_tomahawk3_init_tm_memory(int unit) 1555 { 1556 uint32 rval; 1557 soc_reg_t reg; 1558 int parity_en; 1559 uint32 pipe_map; 1560 int in_progress =1, init_usec, pipe; 1561 soc_timeout_t to; 1562 soc_info_t *si = &SOC_INFO(unit); 1563 uint32 entry[SOC_MAX_MEM_WORDS]; 1564 soc_mem_t mem; 1565 1566 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 1567 1568 /* Initialize IDB memory */ 1569 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV && in_progress; pipe++) { 1570 /* skip pipes that don't exist */ 1571 if (!(pipe_map & (1 << pipe))) { 1572 continue; 1573 } 1574 rval = 0; 1575 reg = SOC_REG_UNIQUE_ACC(unit, IDB_HW_RESET_CONTROLr)[pipe]; 1576 soc_reg_field_set(unit, reg, &rval, RESET_ALLf, 1); 1577 soc_reg_field_set(unit, reg, &rval, VALIDf, 1); 1578 soc_reg_field_set(unit, reg, &rval, COUNTf, 0x80); 1579 SOC_IF_ERROR_RETURN 1580 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1581 } 1582 1583 /* For simulation, set timeout to 10 sec. Otherwise, timeout = 50 ms */ 1584 if (SAL_BOOT_SIMULATION) { 1585 init_usec = 10000000; 1586 } else { 1587 init_usec = 50000; 1588 } 1589 if (!SAL_BOOT_SIMULATION) { 1590 soc_timeout_init(&to, init_usec, 0); 1591 1592 /* Wait for IPIPE memory initialization done */ 1593 in_progress = pipe_map; 1594 do { 1595 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV && in_progress; pipe++) { 1596 rval = 0; 1597 1598 /* skip pipes that don't exist */ 1599 if (!(pipe_map & (1 << pipe))) { 1600 continue; 1601 } 1602 1603 reg = SOC_REG_UNIQUE_ACC(unit, IDB_HW_RESET_CONTROLr)[pipe]; 1604 if (in_progress & (1 << pipe)) { /* not done yet */ 1605 SOC_IF_ERROR_RETURN 1606 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1607 if (soc_reg_field_get(unit, reg, rval, DONEf)) { 1608 in_progress ^= 1 << pipe; 1609 } 1610 } 1611 } 1612 if (soc_timeout_check(&to)) { 1613 LOG_WARN(BSL_LS_SOC_COMMON, 1614 (BSL_META_U(unit, 1615 "unit %d : IDB_HW_RESET timeout\n"), unit)); 1616 break; 1617 } 1618 } while (in_progress != 0); 1619 } 1620 parity_en = soc_property_get(unit, spn_PARITY_ENABLE, TRUE); 1621 /*Initialize MMU memory*/ 1622 rval = 0; 1623 reg = MMU_GLBCFG_MISCCONFIGr; 1624 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1625 soc_reg_field_set(unit, reg, &rval, ECCP_ENf, 1); 1626 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1627 sal_usleep(20); 1628 soc_reg_field_set(unit, reg, &rval, INIT_MEMf, 1); 1629 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1630 soc_reg_field_set(unit, reg, &rval, INIT_MEMf, 0); 1631 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1632 sal_usleep(30); 1633 1634 if (!SAL_BOOT_SIMULATION) { 1635 SOC_IF_ERROR_RETURN(soc_th3_check_mmu_mem_init_done(unit)); 1636 } 1637 soc_reg_field_set(unit, reg, &rval, ECCP_ENf, parity_en); 1638 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1639 1640 1641 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV ; pipe++) { 1642 if (!SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 1643 mem = SOC_MEM_UNIQUE_ACC(unit, MMU_EBCFP_MXM_TAG_MEMm)[pipe]; 1644 soc_mem_field32_set(unit, mem, &entry, DATAf, 0x1); 1645 SOC_IF_ERROR_RETURN 1646 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, &entry)); 1647 } 1648 } 1649 1650 return SOC_E_NONE; 1651 } 1652 1653 /*Start: Port mapping functions*/ 1654 STATIC int 1655 _soc_th3_mmu_port_to_phy_port_map (int unit, int dev_port, int phy_port, 1656 int mmu_port) 1657 { 1658 /* 1659 *MMU_INTFI_MMU_PORT_TO_PHY_PORT_MAPPING 1660 *MMU_INTFO_MMU_PORT_TO_PHY_PORT_MAPPING 1661 *MMU_EBPTS_MMU_PORT_TO_PHY_PORT_MAPPING- 1662 */ 1663 soc_reg_t reg_list[] = {MMU_INTFI_MMU_PORT_TO_PHY_PORT_MAPPINGr, 1664 MMU_INTFO_MMU_PORT_TO_PHY_PORT_MAPPINGr, 1665 MMU_EBPTS_MMU_PORT_TO_PHY_PORT_MAPPINGr, 1666 }; 1667 soc_reg_t reg; 1668 uint32 rval; 1669 int reg_index, field_val, num_regs; 1670 int pipe; 1671 soc_info_t *si = &SOC_INFO(unit); 1672 num_regs = sizeof(reg_list) / sizeof(soc_reg_t); 1673 1674 pipe = si->port_pipe[dev_port]; 1675 for (reg_index = 0; reg_index < num_regs; reg_index ++) { 1676 rval = 0; 1677 reg = reg_list[reg_index]; 1678 if (SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, 1679 SOC_BLK_MMU_EB)) { 1680 /* Pipe 0 is special because of CPU port being port 0. Range is 0 - 32 */ 1681 if (pipe == 0) { 1682 field_val = phy_port % (SOC_TH3_MAX_PHY_PORTS_PER_PIPE + 1); 1683 } else { 1684 field_val = (phy_port - 1) % SOC_TH3_MAX_PHY_PORTS_PER_PIPE; 1685 } 1686 if (IS_LB_PORT(unit, dev_port)) { 1687 /*Local phy port 33 to be used for all LB ports*/ 1688 field_val = SOC_TH3_LB_PORT_LOCAL_PHY_NUM; 1689 } 1690 if(IS_MANAGEMENT_PORT(unit, dev_port)) { 1691 /*Local phy port 32 to be used for all LB ports*/ 1692 field_val = SOC_TH3_MGMT_PORT_LOCAL_PHY_NUM; 1693 } 1694 } else { 1695 field_val = phy_port; 1696 } 1697 soc_reg_field_set(unit, reg, &rval, PHY_PORT_NUMf, 1698 field_val); 1699 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, dev_port, 0, rval)); 1700 } 1701 return SOC_E_NONE; 1702 } 1703 1704 STATIC int 1705 _soc_th3_mmu_port_to_dev_port_map (int unit, int dev_port, int mmu_port) 1706 { 1707 /* 1708 *MMU_CRB_DEVICE_PORT_TO_MMU_PORT_MAPPING - Global dev to Global mmu 1709 *MMU_EBCFP_MMU_PORT_TO_DEVICE_PORT_MAPPING - Global MMU to global dev 1710 *MMU_RQE_PORT_TO_DEVICE_PORT_MAPPING-memory, global dev to global mmu 1711 *MMU_THDO_DEVICE_PORT_MAP -memory, chip port num to dev port 1712 */ 1713 soc_reg_t reg_list[] = {MMU_CRB_DEVICE_PORT_TO_MMU_PORT_MAPPINGr, 1714 MMU_EBCFP_MMU_PORT_TO_DEVICE_PORT_MAPPINGr}; 1715 soc_mem_t mem_list[] = {MMU_RQE_DEVICE_TO_MMU_PORT_MAPPINGm, 1716 MMU_THDO_DEVICE_PORT_MAPm}; 1717 soc_field_t reg_field = INVALIDf, mem_field = INVALIDf; 1718 soc_reg_t reg; 1719 soc_mem_t mem; 1720 uint32 entry[SOC_MAX_MEM_WORDS]; 1721 uint32 rval; 1722 int reg_index, field_val = -1, index = -1, mem_index, num_regs, num_mems; 1723 num_regs = sizeof(reg_list) / sizeof(soc_reg_t); 1724 num_mems = sizeof(mem_list) / sizeof(soc_mem_t); 1725 1726 sal_memset(entry, 0, sizeof(entry)); 1727 for (reg_index = 0; reg_index < num_regs; reg_index++) { 1728 rval = 0; 1729 reg = reg_list[reg_index]; 1730 switch(reg) { 1731 case MMU_CRB_DEVICE_PORT_TO_MMU_PORT_MAPPINGr: 1732 reg_field = MMU_PORTf; 1733 field_val = mmu_port; /*Global mmu port*/ 1734 index = dev_port; 1735 break; 1736 case MMU_EBCFP_MMU_PORT_TO_DEVICE_PORT_MAPPINGr: 1737 reg_field = DEVICE_PORTf; 1738 field_val = dev_port; 1739 /*dev port to mmu port conversion done in soc_reg_write*/ 1740 index = dev_port; 1741 break; 1742 default: 1743 break; 1744 } 1745 soc_reg_field_set(unit, reg, &rval, reg_field, 1746 field_val); 1747 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, index, 0, rval)); 1748 } 1749 for (mem_index = 0; mem_index < num_mems; mem_index++) { 1750 mem = mem_list[mem_index]; 1751 switch(mem) { 1752 case MMU_RQE_DEVICE_TO_MMU_PORT_MAPPINGm: 1753 mem_field = MMU_PORTf; 1754 field_val = mmu_port; /*Global mmu port*/ 1755 index = dev_port; 1756 break; 1757 case MMU_THDO_DEVICE_PORT_MAPm: 1758 mem_field = DEVICE_PORTf; 1759 field_val = dev_port; 1760 index = SOC_TH3_MMU_CHIP_PORT(unit, dev_port); 1761 break; 1762 default: 1763 break; 1764 } 1765 soc_mem_field32_set(unit, mem, &entry, mem_field , field_val); 1766 SOC_IF_ERROR_RETURN 1767 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry)); 1768 } 1769 return SOC_E_NONE; 1770 } 1771 1772 int 1773 soc_tomahawk3_mmu_port_mapping_init (int unit) 1774 { 1775 soc_info_t *si; 1776 int port, phy_port, mmu_port; 1777 si = &SOC_INFO(unit); 1778 1779 1780 PBMP_ALL_ITER(unit, port) { 1781 phy_port = si->port_l2p_mapping[port]; 1782 mmu_port = si->port_p2m_mapping[phy_port]; 1783 LOG_INFO(BSL_LS_SOC_COSQ, 1784 (BSL_META_U(unit, 1785 " Dev Port:%d MMU_port:%d Phy Port:%d\n"), 1786 port, mmu_port, phy_port)); 1787 _soc_th3_mmu_port_to_phy_port_map(unit, port, phy_port, mmu_port); 1788 _soc_th3_mmu_port_to_dev_port_map(unit, port, mmu_port); 1789 } 1790 return SOC_E_NONE; 1791 } 1792 /*End: Port mapping init functions*/ 1793 1794 int 1795 soc_tomahawk3_en_mmu_refresh (int unit) 1796 { 1797 int reg_index; 1798 soc_field_t refresh_field = REFRESH_DISABLEf; 1799 soc_reg_t reg_list[] = {MMU_MTRO_CONFIGr, MMU_WRED_REFRESH_CONTROLr}; 1800 uint32 rval; 1801 int num_regs = sizeof(reg_list) / sizeof(soc_reg_t); 1802 1803 for (reg_index = 0; reg_index < num_regs; reg_index++) { 1804 rval = 0; 1805 soc_reg_field_set(unit, reg_list[reg_index], &rval, refresh_field, 0); 1806 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg_list[reg_index], 1807 REG_PORT_ANY, 0, rval)); 1808 } 1809 return SOC_E_NONE; 1810 } 1811 1812 STATIC int 1813 soc_tomahawk3_ifp_cos_map_init_rqe_flush_war (int unit) 1814 { 1815 1816 int mem_index; 1817 int pri; 1818 soc_mem_t mem = IFP_COS_MAPm; 1819 soc_field_t rqe_cos = IFP_RQE_Q_NUMf; 1820 uint32 entry[SOC_MAX_MEM_WORDS]; 1821 1822 for (pri = 0; pri < _TH3_MMU_NUM_RQE_QUEUES; pri++) { 1823 mem_index = (_TH3_IFP_COS_MAP_RSVD_PROF * _TH3_MMU_NUM_INT_PRI) + pri; 1824 SOC_IF_ERROR_RETURN 1825 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, mem_index, &entry)); 1826 soc_mem_field32_set(unit, mem, &entry, rqe_cos, pri); 1827 SOC_IF_ERROR_RETURN 1828 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_index, &entry)); 1829 } 1830 return SOC_E_NONE; 1831 } 1832 1833 /* 1834 * Function: soc_th3_mmu_rqe_queue_number_init 1835 * Purpose: Initialize to use separate RQE queue numbers for mirror and CPU 1836 * packets 1837 * Param: unit: device number 1838 */ 1839 int 1840 soc_th3_mmu_rqe_queue_number_init(int unit) 1841 { 1842 uint32 rval = 0; 1843 soc_reg_t reg; 1844 uint16 dev_id; 1845 uint8 rev_id; 1846 1847 soc_cm_get_id(unit, &dev_id, &rev_id); 1848 1849 /*RQE queue number for CPU hi packets*/ 1850 reg = CPU_HI_RQE_Q_NUMr; 1851 SOC_IF_ERROR_RETURN 1852 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1853 if (rev_id == BCM56980_A0_REV_ID) { 1854 soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_A0_CPU_HI_RQE_Q_NUM); 1855 } else { 1856 soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_CPU_HI_RQE_Q_NUM); 1857 } 1858 SOC_IF_ERROR_RETURN 1859 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1860 1861 /*RQE queue number for CPU lo packets*/ 1862 reg = CPU_LO_RQE_Q_NUMr; 1863 rval = 0; 1864 SOC_IF_ERROR_RETURN 1865 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1866 if (rev_id == BCM56980_A0_REV_ID) { 1867 soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_A0_CPU_LO_RQE_Q_NUM); 1868 } else { 1869 soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_CPU_LO_RQE_Q_NUM); 1870 } 1871 SOC_IF_ERROR_RETURN 1872 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1873 1874 /*RQE queue number for Mirror packets*/ 1875 reg = MIRROR_RQE_Q_NUMr; 1876 rval = 0; 1877 SOC_IF_ERROR_RETURN 1878 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1879 if (rev_id == BCM56980_A0_REV_ID) { 1880 soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_A0_MIRR_RQE_Q_NUM); 1881 } else { 1882 soc_reg_field_set(unit, reg, &rval, RQE_Q_NUMf, _TH3_MIRR_RQE_Q_NUM); 1883 } 1884 SOC_IF_ERROR_RETURN 1885 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1886 1887 reg = MMU_CRB_RQE_QUEUE_CONFIGr; 1888 rval = 0; 1889 SOC_IF_ERROR_RETURN 1890 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1891 if (rev_id == BCM56980_A0_REV_ID) { 1892 soc_reg_field_set(unit, reg, &rval, CPUHI_RQE_QUEUE_NUMf, _TH3_A0_CPU_HI_RQE_Q_NUM); 1893 soc_reg_field_set(unit, reg, &rval, CPULO_RQE_QUEUE_NUMf, _TH3_A0_CPU_LO_RQE_Q_NUM); 1894 soc_reg_field_set(unit, reg, &rval, MIRROR_RQE_QUEUE_NUMf, _TH3_A0_MIRR_RQE_Q_NUM); 1895 } else { 1896 soc_reg_field_set(unit, reg, &rval, CPUHI_RQE_QUEUE_NUMf, _TH3_CPU_HI_RQE_Q_NUM); 1897 soc_reg_field_set(unit, reg, &rval, CPULO_RQE_QUEUE_NUMf, _TH3_CPU_LO_RQE_Q_NUM); 1898 soc_reg_field_set(unit, reg, &rval, MIRROR_RQE_QUEUE_NUMf, _TH3_MIRR_RQE_Q_NUM); 1899 } 1900 SOC_IF_ERROR_RETURN 1901 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1902 1903 /* Initialize IFP_COS_MAP reserved profile fro RQE flush WAR (SDK-142748)*/ 1904 SOC_IF_ERROR_RETURN( 1905 soc_tomahawk3_ifp_cos_map_init_rqe_flush_war(unit)); 1906 1907 return SOC_E_NONE; 1908 } 1909 1910 /* 1911 * Function: soc_tomahawk3_mmu_port_rx_enables 1912 * Purpose: Enable MMU to receive traffic on different ports as part of init 1913 * Param: unit: device number 1914 */ 1915 int 1916 soc_tomahawk3_mmu_port_rx_enables(int unit) { 1917 int pipe, dev_port, itm; 1918 uint32 rval; 1919 soc_info_t *si = &SOC_INFO(unit); 1920 uint32 itm_map = si->itm_map; 1921 1922 PBMP_ALL_ITER(unit, dev_port) { 1923 SOC_IF_ERROR_RETURN 1924 (soc_reg32_get(unit, MMU_CRB_SRC_PORT_CFGr, dev_port, 0, 1925 &rval)); 1926 soc_reg_field_set(unit, MMU_CRB_SRC_PORT_CFGr, &rval, 1927 RX_PORT_ENf, 1); 1928 SOC_IF_ERROR_RETURN 1929 (soc_reg32_set(unit, MMU_CRB_SRC_PORT_CFGr, dev_port, 0, 1930 rval)); 1931 } 1932 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) { 1933 if (!SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 1934 LOG_INFO(BSL_LS_SOC_COSQ, 1935 (BSL_META_U(unit, "Programming for Pipe:%d\n"), pipe)); 1936 rval = 0; 1937 SOC_IF_ERROR_RETURN 1938 (soc_reg32_get(unit, MMU_THDO_CONFIG_PORTr, REG_PORT_ANY, pipe, 1939 &rval)); 1940 /*Enable for all MMU ports in a pipe*/ 1941 soc_reg_field_set(unit, MMU_THDO_CONFIG_PORTr, &rval, 1942 OUTPUT_PORT_RX_ENABLEf, 0xfffff); 1943 SOC_IF_ERROR_RETURN 1944 (soc_reg32_set(unit, MMU_THDO_CONFIG_PORTr, REG_PORT_ANY, pipe, 1945 rval)); 1946 } 1947 } 1948 for(itm = 0; itm < NUM_ITM(unit); itm++) { 1949 if (itm_map & (1 << itm)) { 1950 rval = 0; 1951 SOC_IF_ERROR_RETURN 1952 (soc_reg32_get(unit, MMU_THDO_ENGINE_ENABLES_CFGr, itm, 1953 REG_PORT_ANY, &rval)); 1954 /*Enable for all MMU ports in a pipe*/ 1955 soc_reg_field_set(unit, MMU_THDO_ENGINE_ENABLES_CFGr, &rval, 1956 SRC_PORT_DROP_COUNT_ENABLEf, 1); 1957 SOC_IF_ERROR_RETURN 1958 (soc_reg32_set(unit, MMU_THDO_ENGINE_ENABLES_CFGr, itm, 1959 REG_PORT_ANY, rval)); 1960 1961 } 1962 } 1963 /*Disable THDO counter overflow interrupt (SDK-133360)*/ 1964 rval = 0; 1965 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, MMU_THDO_CPU_INT_SETr, 1966 REG_PORT_ANY, 0, &rval)); 1967 soc_reg_field_set(unit, MMU_THDO_CPU_INT_SETr, &rval, COUNTER_OVERFLOWf, 0); 1968 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_THDO_CPU_INT_SETr, 1969 REG_PORT_ANY, 0, rval)); 1970 return SOC_E_NONE; 1971 } 1972 1973 /* 1974 * Function: soc_tomahawk3_cell_pointer_init 1975 * Purpose: Initialize cell pointer memory in MMU during init 1976 * Param: unit: device number 1977 */ 1978 int 1979 soc_tomahawk3_cell_pointer_init(int unit) 1980 { 1981 uint64 rval, cfap_bank; 1982 uint32 rval32; 1983 int itm; 1984 soc_info_t *si = &SOC_INFO(unit); 1985 uint32 itm_map = si->itm_map; 1986 COMPILER_64_ZERO(rval); 1987 /*Enable all 34 CFAP banks in each ITM*/ 1988 COMPILER_64_SET(cfap_bank, 0x3, 0xffffffff); 1989 for (itm = 0; itm < NUM_ITM(unit); itm++) { 1990 if (itm_map & (1 << itm)) { 1991 LOG_INFO(BSL_LS_SOC_COSQ, 1992 (BSL_META_U(unit, "Programming for ITM:%d\n"), itm)); 1993 SOC_IF_ERROR_RETURN 1994 (soc_tomahawk3_itm_reg_get(unit, MMU_CFAP_INIT_64r, 1995 itm, itm, 0, &rval)); 1996 COMPILER_64_OR(rval, cfap_bank); 1997 SOC_IF_ERROR_RETURN 1998 (soc_tomahawk3_itm_reg_set(unit, MMU_CFAP_INIT_64r, 1999 itm, itm, 0, rval)); 2000 } 2001 } 2002 2003 /* SDK-142571 MMU_CFAP_ARBITER_MASK should be 2 */ 2004 rval32 = 0; 2005 SOC_IF_ERROR_RETURN 2006 (soc_tomahawk3_itm_reg32_get(unit, MMU_CFAP_ARBITER_MASKr, 2007 -1, -1, 0, &rval32)); 2008 soc_reg_field_set(unit, MMU_CFAP_ARBITER_MASKr, &rval32, 2009 MASKf, 2); 2010 SOC_IF_ERROR_RETURN 2011 (soc_tomahawk3_itm_reg32_set(unit, MMU_CFAP_ARBITER_MASKr, 2012 -1, -1, 0, rval32)); 2013 2014 return SOC_E_NONE; 2015 } 2016 2017 /* 2018 *Function: soc_tomahawk3_cosq_profile_info_init 2019 *Purpose: init data struct for scheduler hierachy for a particular profile 2020 */ 2021 int 2022 soc_tomahawk3_cosq_profile_info_init(int unit, int profile_idx) 2023 { 2024 int queue_num; 2025 2026 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2027 th3_sched_profile_info[unit][profile_idx][queue_num].cos = -1; 2028 th3_sched_profile_info[unit][profile_idx][queue_num].mmuq[0] = -1; 2029 th3_sched_profile_info[unit][profile_idx][queue_num].mmuq[1] = -1; 2030 th3_sched_profile_info[unit][profile_idx][queue_num].strict_priority = 0; 2031 th3_sched_profile_info[unit][profile_idx][queue_num].fc_is_uc_only = 0; 2032 } 2033 return SOC_E_NONE; 2034 2035 } 2036 2037 /* 2038 *Function: soc_cosq_profile_struct_init 2039 *Purpose: init data struct for scheduler hierachy 2040 */ 2041 int 2042 soc_cosq_profile_struct_init(int unit, int profile) 2043 { 2044 int queue_num; 2045 2046 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2047 L1_TO_L0_MAPPING[unit][profile][queue_num] = -1; 2048 L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] = 0; 2049 L0_TO_COSQ_MAPPING[unit][profile][queue_num] = -1; 2050 } 2051 return SOC_E_NONE; 2052 } 2053 2054 /* 2055 *Function: soc_tomahawk3_cosq_port_info_init 2056 *Purpose: init data struct for scheduler hierachy for a particular port 2057 */ 2058 int 2059 soc_tomahawk3_cosq_port_info_init(int unit, int port_num) 2060 { 2061 int queue_num; 2062 2063 if (th3_cosq_mmu_info[unit] == NULL) { 2064 return SOC_E_MEMORY; 2065 } 2066 2067 /*general port initialization*/ 2068 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2069 /*level 0*/ 2070 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2071 L0[queue_num].level = 0; 2072 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2073 L0[queue_num].in_use = 0; 2074 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2075 L0[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR; 2076 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2077 L0[queue_num].weight = 0; 2078 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2079 L0[queue_num].fc_is_uc_only = 0; 2080 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2081 L0[queue_num].hw_index = queue_num; 2082 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2083 L0[queue_num].cos = -1; 2084 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2085 L0[queue_num].parent = NULL; 2086 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2087 L0[queue_num].children[0] = NULL; 2088 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2089 L0[queue_num].children[1] = NULL; 2090 } 2091 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2092 /*level 1*/ 2093 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2094 L1[queue_num].level = 1; 2095 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2096 L1[queue_num].in_use = 0; 2097 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2098 L1[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR; 2099 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2100 L1[queue_num].weight = 0; 2101 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2102 L1[queue_num].fc_is_uc_only = 0; 2103 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2104 L1[queue_num].hw_index = queue_num; 2105 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2106 L1[queue_num].cos = -1; 2107 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2108 L1[queue_num].parent = NULL; 2109 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2110 L1[queue_num].children[0] = NULL; 2111 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2112 L1[queue_num].children[1] = NULL; 2113 } 2114 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2115 /*level 2*/ 2116 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2117 mmuq[queue_num].level = 2; 2118 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2119 mmuq[queue_num].in_use = 1; 2120 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2121 mmuq[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR; 2122 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2123 mmuq[queue_num].weight = 0; 2124 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2125 mmuq[queue_num].fc_is_uc_only = 0; 2126 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2127 mmuq[queue_num].hw_index = queue_num; 2128 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2129 mmuq[queue_num].cos = -1; 2130 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2131 mmuq[queue_num].parent = NULL; 2132 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2133 mmuq[queue_num].children[0] = NULL; 2134 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2135 mmuq[queue_num].children[1] = NULL; 2136 } 2137 return SOC_E_NONE; 2138 } 2139 2140 void soc_gport_tree_print(int unit, int port) 2141 { 2142 int cosq_idx; 2143 2144 /* Print */ 2145 for (cosq_idx = 0; cosq_idx < SOC_TH3_COS_MAX; cosq_idx++) { 2146 LOG_INFO(BSL_LS_SOC_COSQ, 2147 (BSL_META_U(unit, "\n L0 [%0d, %0d] in_use=%0d, level=%0d, hw_index=%0d, cos=%0d "), 2148 port, cosq_idx, th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].in_use, 2149 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].level, 2150 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].hw_index, 2151 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].cos)); 2152 if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].parent != NULL) { 2153 LOG_INFO(BSL_LS_SOC_COSQ, 2154 (BSL_META_U(unit, "parent.hw_index=%0d "), 2155 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].parent->hw_index)); 2156 } 2157 if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].children[0] != NULL) { 2158 LOG_INFO(BSL_LS_SOC_COSQ, 2159 (BSL_META_U(unit, "children[0].hw_index=%0d "), 2160 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].children[0]->hw_index)); 2161 if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].children[1] != NULL) { 2162 LOG_INFO(BSL_LS_SOC_COSQ, 2163 (BSL_META_U(unit, "children[1].hw_index=%0d "), 2164 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[cosq_idx].children[1]->hw_index)); 2165 } 2166 } 2167 2168 LOG_INFO(BSL_LS_SOC_COSQ, 2169 (BSL_META_U(unit, "\n L1 [%0d, %0d] in_use=%0d, level=%0d, hw_index=%0d, cos=%0d "), 2170 port, cosq_idx, th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].in_use, 2171 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].level, 2172 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].hw_index, 2173 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].cos)); 2174 if (th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].parent != NULL) { 2175 LOG_INFO(BSL_LS_SOC_COSQ, 2176 (BSL_META_U(unit, "parent.hw_index=%0d "), 2177 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].parent->hw_index)); 2178 } 2179 if (th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].children[0] != NULL) { 2180 LOG_INFO(BSL_LS_SOC_COSQ, 2181 (BSL_META_U(unit, "children[0].hw_index=%0d "), 2182 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].children[0]->hw_index)); 2183 if (th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].children[1] != NULL) { 2184 LOG_INFO(BSL_LS_SOC_COSQ, 2185 (BSL_META_U(unit, "children[1].hw_index=%0d "), 2186 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[cosq_idx].children[1]->hw_index)); 2187 } 2188 } 2189 2190 LOG_INFO(BSL_LS_SOC_COSQ, 2191 (BSL_META_U(unit, "\n mmuq [%0d, %0d] in_use=%0d, level=%0d, hw_index=%0d, cos=%0d "), 2192 port, cosq_idx, th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].in_use, 2193 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].level, 2194 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].hw_index, 2195 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].cos)); 2196 if (th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].parent != NULL) { 2197 LOG_INFO(BSL_LS_SOC_COSQ, 2198 (BSL_META_U(unit, "parent.hw_index=%0d "), 2199 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].parent->hw_index)); 2200 } 2201 if (th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].children[0] != NULL) { 2202 LOG_INFO(BSL_LS_SOC_COSQ, 2203 (BSL_META_U(unit, "children[0].hw_index=%0d "), 2204 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].children[0]->hw_index)); 2205 if (th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].children[1] != NULL) { 2206 LOG_INFO(BSL_LS_SOC_COSQ, 2207 (BSL_META_U(unit, "children[1].hw_index=%0d "), 2208 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[cosq_idx].children[1]->hw_index)); 2209 } 2210 } 2211 } 2212 } 2213 2214 /* 2215 *Function: soc_cosq_struct_init 2216 *Purpose: init data struct for scheduler hierachy 2217 */ 2218 int 2219 soc_cosq_struct_init(int unit) 2220 { 2221 int port_num, queue_num, profile, i; 2222 /*L1 to L0 is port based in reg file. Keep the profile based mapping in software*/ 2223 for (profile = 0; profile < SOC_TH3_MAX_NUM_SCHED_PROFILE; profile++) { 2224 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2225 L1_TO_L0_MAPPING[unit][profile][queue_num] = -1; 2226 L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] = 0; 2227 L0_TO_COSQ_MAPPING[unit][profile][queue_num] = -1; 2228 } 2229 } 2230 if (th3_cosq_mmu_info[unit] == NULL) { 2231 /*th3_cosq_mmu_info is not freed */ 2232 th3_cosq_mmu_info[unit] = 2233 sal_alloc(sizeof(soc_th3_mmu_info_t), "soc_th3_mmu_info_t"); 2234 if (th3_cosq_mmu_info[unit] == NULL) { 2235 return SOC_E_MEMORY; 2236 } 2237 } 2238 /*general port initialization*/ 2239 for (port_num = 0; port_num < SOC_TH3_MAX_NUM_PORTS; port_num++) { 2240 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2241 /*level 0*/ 2242 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2243 L0[queue_num].level = 0; 2244 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2245 L0[queue_num].in_use = 0; 2246 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2247 L0[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR; 2248 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2249 L0[queue_num].weight = 0; 2250 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2251 L0[queue_num].fc_is_uc_only = 0; 2252 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2253 L0[queue_num].hw_index = queue_num; 2254 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2255 L0[queue_num].cos = -1; 2256 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2257 L0[queue_num].parent = NULL; 2258 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2259 L0[queue_num].children[0] = NULL; 2260 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2261 L0[queue_num].children[1] = NULL; 2262 } 2263 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2264 /*level 1*/ 2265 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2266 L1[queue_num].level = 1; 2267 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2268 L1[queue_num].in_use = 0; 2269 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2270 L1[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR; 2271 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2272 L1[queue_num].weight = 0; 2273 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2274 L1[queue_num].fc_is_uc_only = 0; 2275 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2276 L1[queue_num].hw_index = queue_num; 2277 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2278 L1[queue_num].cos = -1; 2279 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2280 L1[queue_num].parent = NULL; 2281 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2282 L1[queue_num].children[0] = NULL; 2283 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2284 L1[queue_num].children[1] = NULL; 2285 } 2286 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2287 /*level 2*/ 2288 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2289 mmuq[queue_num].level = 2; 2290 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2291 mmuq[queue_num].in_use = 1; 2292 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2293 mmuq[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR; 2294 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2295 mmuq[queue_num].weight = 0; 2296 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2297 mmuq[queue_num].fc_is_uc_only = 0; 2298 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2299 mmuq[queue_num].hw_index = queue_num; 2300 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2301 mmuq[queue_num].cos = -1; 2302 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2303 mmuq[queue_num].parent = NULL; 2304 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2305 mmuq[queue_num].children[0] = NULL; 2306 th3_cosq_mmu_info[unit]->th3_port_info[port_num]. 2307 mmuq[queue_num].children[1] = NULL; 2308 } 2309 } 2310 /*cpu port initialization*/ 2311 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2312 /*levl 0*/ 2313 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num].level = 0; 2314 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num].in_use = 0; 2315 th3_cosq_mmu_info[unit]->th3_cpu_port_info. 2316 L0[queue_num].sched_policy = SOC_TH3_SCHED_MODE_WRR; 2317 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num].weight = 0; 2318 th3_cosq_mmu_info[unit]->th3_cpu_port_info. 2319 L0[queue_num].hw_index = queue_num; 2320 th3_cosq_mmu_info[unit]->th3_cpu_port_info. 2321 L0[queue_num].cos = queue_num; 2322 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num].parent = NULL; 2323 for (i = 0; i < SOC_TH3_NUM_CPU_QUEUES; i++) { 2324 th3_cosq_mmu_info[unit]->th3_cpu_port_info. 2325 L0[queue_num].children[i] = NULL; 2326 } 2327 } 2328 for (queue_num = 0; queue_num < SOC_TH3_NUM_CPU_QUEUES; queue_num++) { 2329 /*level 1*/ 2330 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].level = 1; 2331 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].in_use = 0; 2332 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num]. 2333 sched_policy = SOC_TH3_SCHED_MODE_WRR; 2334 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].weight = 0; 2335 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num]. 2336 hw_index = queue_num; 2337 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].cos = -1; 2338 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num].parent = NULL; 2339 for (i = 0; i < SOC_TH3_NUM_CPU_QUEUES; i++) { 2340 th3_cosq_mmu_info[unit]->th3_cpu_port_info. 2341 L1[queue_num].children[i] = NULL; 2342 } 2343 } 2344 return SOC_E_NONE; 2345 } 2346 /* 2347 *Function: soc_tomahawk3_mcq_mode_set 2348 *Purpose: Program MC_Q_MODE value to configure number of UC and MC queues per 2349 * port 2350 *Params: 2351 * unit: Device unit number 2352 * mode: mc_q_mode value (rage: 0-3) 2353 */ 2354 2355 int 2356 soc_tomahawk3_mcq_mode_set(int unit, int mode) 2357 { 2358 soc_reg_t reg; 2359 uint32 rval; 2360 int i; 2361 soc_reg_t reg_array[] = {MMU_INTFO_CONFIG0r, 2362 MMU_TOQ_CONFIGr, 2363 MMU_THDO_CONFIGr, 2364 MMU_CRB_CONFIGr, 2365 MMU_WRED_CONFIGr}; 2366 if (mode < 0 || mode > 3) { 2367 return SOC_E_PARAM; 2368 } 2369 for (i = 0; i < sizeof(reg_array) / sizeof(reg); i++) { 2370 reg = reg_array[i]; 2371 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, 0, 0, &rval)); 2372 soc_reg_field_set(unit, reg, &rval, MC_Q_MODEf, mode); 2373 SOC_IF_ERROR_RETURN 2374 (soc_tomahawk3_itm_reg32_set(unit, reg, -1, -1, -1, rval)); 2375 } 2376 return SOC_E_NONE; 2377 } 2378 2379 /* Function: 2380 * soc_tomahawk3_port_schedule_state_basic_setup 2381 * Purpose: 2382 * Setup Global params in port_schedule_state structure 2383 * to DV FlexPort API 2384 * Parameters: 2385 * unit - (IN) Unit number. 2386 * port_schedule_state - (OUT) Port resource state. 2387 * Returns: 2388 * BCM_E_xxx 2389 */ 2390 STATIC int 2391 soc_tomahawk3_port_schedule_state_basic_setup(int unit, 2392 soc_port_schedule_state_t *port_schedule_state) 2393 { 2394 #define _TH3_CPU_LB_PORT_SPEED 10000 2395 #if 0 2396 soc_control_t *soc = SOC_CONTROL(unit); 2397 #endif 2398 soc_info_t *si = &SOC_INFO(unit); 2399 soc_port_map_type_t *in_portmap; 2400 soc_asf_prop_t *cutthru_prop; 2401 int port, latency; 2402 int dpr_freq; 2403 /* Core clock frequency */ 2404 port_schedule_state->frequency = si->frequency; 2405 2406 /*MMU lossless mode. default to 1(lossy)*/ 2407 port_schedule_state->lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 2408 SOC_TH3_MMU_LOSSLESS_DEFAULT_DISABLE); 2409 2410 /* Construct in_port_map */ 2411 in_portmap = &port_schedule_state->in_port_map; 2412 2413 /*DPP clock frequency in MHz needs to be passed*/ 2414 dpr_freq = soc_property_get(unit, spn_DPR_CLOCK_FREQUENCY, -1); 2415 SOC_IF_ERROR_RETURN 2416 (soc_tomahawk3_dpr_frequency_range_check(unit, dpr_freq)); 2417 in_portmap->port_p2PBLK_inst_mapping[0] = dpr_freq; 2418 2419 PBMP_ALL_ITER(unit, port) { 2420 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 2421 continue; 2422 } 2423 in_portmap->log_port_speed[port] = si->port_speed_max[port]; 2424 in_portmap->port_num_lanes[port] = si->port_num_lanes[port]; 2425 /*Override port speed for CPU and LB ports*/ 2426 if (IS_CPU_PORT(unit, port) || (IS_LB_PORT(unit, port))) { 2427 in_portmap->log_port_speed[port] = _TH3_CPU_LB_PORT_SPEED; 2428 } 2429 } 2430 sal_memcpy(in_portmap->port_p2l_mapping, si->port_p2l_mapping, 2431 sizeof(int) * SOC_MAX_NUM_PORTS); 2432 sal_memcpy(in_portmap->port_l2p_mapping, si->port_l2p_mapping, 2433 sizeof(int) * SOC_MAX_NUM_PORTS); 2434 sal_memcpy(in_portmap->port_p2m_mapping, si->port_p2m_mapping, 2435 sizeof(int) * SOC_MAX_NUM_PORTS); 2436 sal_memcpy(in_portmap->port_m2p_mapping, si->port_m2p_mapping, 2437 sizeof(int) * SOC_MAX_NUM_MMU_PORTS); 2438 sal_memcpy(in_portmap->port_l2i_mapping, si->port_l2i_mapping, 2439 sizeof(int) * SOC_MAX_NUM_PORTS); 2440 /*physical pbm is dont care for init 2441 *sal_memcpy(&in_portmap->physical_pbm, &si->physical_pbm, sizeof(pbmp_t)); 2442 */ 2443 sal_memcpy(&in_portmap->management_pbm, &si->management_pbm, 2444 sizeof(pbmp_t)); 2445 /* Construct in_port_map */ 2446 cutthru_prop = &port_schedule_state->cutthru_prop; 2447 SOC_IF_ERROR_RETURN(soc_th_latency_get(unit, &latency)); 2448 cutthru_prop->switch_bypass_mode = latency; 2449 /* Construct tdm_ingress_schedule_pipe and tdm_egress_schedule_pipe */ 2450 port_schedule_state->is_flexport = 0; 2451 /*DV function to setup out_port_map. 2452 *Required before calling any DV function 2453 */ 2454 SOC_IF_ERROR_RETURN(soc_tomahawk3_tdm_set_out_port_map(unit, 2455 port_schedule_state)); 2456 #undef _TH3_CPU_LB_PORT_SPEED 2457 return SOC_E_NONE; 2458 } 2459 2460 2461 2462 /* 2463 * Function: 2464 * soc_tomahawk3_port_schedule_tdm_init 2465 * Purpose: 2466 * Initialize TDM information in port_schedule_state that will be passed 2467 * to DV FlexPort API 2468 * Parameters: 2469 * unit - (IN) Unit number. 2470 * port_schedule_state - (OUT) Port resource state. 2471 * Returns: 2472 * BCM_E_xxx 2473 * Notes: 2474 * If called during Scheduler Initialization, only below values need to be 2475 * properly set: 2476 * soc_tdm_schedule_pipe_t::num_slices 2477 * soc_tdm_schedule_t:: cal_len 2478 */ 2479 STATIC int 2480 soc_tomahawk3_port_schedule_tdm_init(int unit, soc_port_schedule_state_t 2481 *port_schedule_state) 2482 { 2483 #if 0 2484 soc_control_t *soc = SOC_CONTROL(unit); 2485 _soc_tomahawk2_tdm_t *tdm = soc->tdm_info; 2486 soc_tdm_schedule_t *sched; 2487 #endif 2488 soc_tdm_schedule_pipe_t *tdm_ischd, *tdm_eschd; 2489 int pipe; 2490 /*int *port_p2PBLK_inst_mapping;*/ 2491 2492 #if 0 2493 if (tdm == NULL) { 2494 /*XGSSIM will skip tdm configuration on TH2*/ 2495 if (SAL_BOOT_XGSSIM) { 2496 return SOC_E_NONE; 2497 } 2498 return SOC_E_INIT; 2499 } 2500 #endif 2501 /* Construct tdm_ingress_schedule_pipe and tdm_egress_schedule_pipe */ 2502 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) { 2503 tdm_ischd = &port_schedule_state->tdm_ingress_schedule_pipe[pipe]; 2504 tdm_eschd = &port_schedule_state->tdm_egress_schedule_pipe[pipe]; 2505 2506 tdm_ischd->num_slices = _TH3_OVS_HPIPE_COUNT_PER_PIPE; 2507 tdm_eschd->num_slices = _TH3_OVS_HPIPE_COUNT_PER_PIPE; 2508 2509 #if 0 2510 is_flexport = port_schedule_state->is_flexport; 2511 if (is_flexport) { 2512 /* TDM Calendar is always in slice 0 */ 2513 sal_memcpy(tdm_ischd->tdm_schedule_slice[0].linerate_schedule, 2514 tdm->tdm_pipe[pipe].idb_tdm, 2515 sizeof(int)*_TH3_TDM_LENGTH); 2516 sal_memcpy(tdm_eschd->tdm_schedule_slice[0].linerate_schedule, 2517 tdm->tdm_pipe[pipe].mmu_tdm, 2518 sizeof(int)*_TH3_TDM_LENGTH); 2519 } 2520 #endif 2521 #if 0 2522 /* OVS */ 2523 for (hpipe = 0; hpipe < _TH3_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) { 2524 /* IDB OVERSUB*/ 2525 sched = &tdm_ischd->tdm_schedule_slice[hpipe]; 2526 sched->cal_len = _TH3_TDM_LENGTH; 2527 2528 /* MMU OVERSUB */ 2529 sched = &tdm_eschd->tdm_schedule_slice[hpipe]; 2530 sched->cal_len = _TH3_TDM_LENGTH; 2531 2532 } 2533 #endif 2534 } 2535 return SOC_E_NONE; 2536 } 2537 2538 int _soc_th3_get_num_ucq(int unit) 2539 { 2540 int mc_q_mode, num_ucq; 2541 2542 mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, 2); 2543 num_ucq = (mc_q_mode == 0) ? 12 : (mc_q_mode == 1) ? 10 : 2544 (mc_q_mode == 2) ? 8 : (mc_q_mode == 3) ? 6 : 8; 2545 2546 return num_ucq; 2547 } 2548 2549 int _soc_th3_get_num_mcq(int unit) 2550 { 2551 int mc_q_mode, num_mcq; 2552 2553 mc_q_mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, 2); 2554 num_mcq = (mc_q_mode == 0) ? 0 : (mc_q_mode == 1) ? 2 : 2555 (mc_q_mode == 2) ? 4 : (mc_q_mode == 3) ? 6 : 4; 2556 2557 return num_mcq; 2558 } 2559 2560 2561 /* 2562 *Function: soc_tomahawk3_l0_cos_set 2563 *Purpose: Assign Hardware L0 index to a cos 2564 */ 2565 int 2566 soc_tomahawk3_l0_cos_set(int unit, soc_port_t port, int hw_index, soc_cos_t cos) 2567 { 2568 if (cos < 0 || cos >= SOC_TH3_NUM_GP_QUEUES || hw_index < 0 || hw_index >= 2569 SOC_TH3_NUM_GP_QUEUES) { 2570 return SOC_E_PARAM; 2571 } 2572 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[hw_index].cos = cos; 2573 LOG_INFO(BSL_LS_SOC_COSQ, 2574 (BSL_META_U(unit, "Port: %0d L0[%0d].cos: %0d in_use:%0d\n"), 2575 port, hw_index, cos, th3_cosq_mmu_info[unit]->th3_port_info[port].L0[hw_index].in_use)); 2576 return SOC_E_NONE; 2577 } 2578 2579 /* 2580 *Function: soc_tomahawk3_sched_profile_attach 2581 *Purpose: Update port structure for scheduler based on profile information 2582 * Program the MMU to SCHQ mapping fro the profile in HW 2583 */ 2584 int 2585 soc_tomahawk3_sched_profile_attach(int unit, soc_port_t port, int profile) 2586 { 2587 soc_reg_t reg; 2588 uint32 rval; 2589 uint64 rval_64; 2590 int queue_num, i; 2591 int mmuq, schedq; 2592 soc_reg_t reg_array[] = {MMU_EBPCC_MMUQ_SCHQ_CFGr, 2593 MMU_MTRO_MMUQ_SCHQ_CFGr, 2594 MMU_QSCH_MMUQ_TO_SCHQ_MAPr, 2595 MMU_PORT_MMUQ_SCHQ_CFGr}; 2596 2597 soc_field_t schedq_field[] = { 2598 SCH_Q_NUM_0f, SCH_Q_NUM_1f, 2599 SCH_Q_NUM_2f, SCH_Q_NUM_3f, 2600 SCH_Q_NUM_4f, SCH_Q_NUM_5f, 2601 SCH_Q_NUM_6f, SCH_Q_NUM_7f, 2602 SCH_Q_NUM_8f, SCH_Q_NUM_9f, 2603 SCH_Q_NUM_10f, SCH_Q_NUM_11f, 2604 }; 2605 soc_field_t mmuq_field[12] = { 2606 MMU_Q_NUM_0f, MMU_Q_NUM_1f, 2607 MMU_Q_NUM_2f, MMU_Q_NUM_3f, 2608 MMU_Q_NUM_4f, MMU_Q_NUM_5f, 2609 MMU_Q_NUM_6f, MMU_Q_NUM_7f, 2610 MMU_Q_NUM_8f, MMU_Q_NUM_9f, 2611 MMU_Q_NUM_10f, MMU_Q_NUM_11f, 2612 }; 2613 if (IS_CPU_PORT(unit, port)) { 2614 return SOC_E_NONE; 2615 } 2616 for (i = 0; i < sizeof(reg_array) / sizeof(reg); i++) { 2617 reg = reg_array[i]; 2618 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 2619 soc_reg_field_set(unit, reg, &rval, Q_PROFILE_SELf, profile); 2620 SOC_IF_ERROR_RETURN 2621 (soc_reg32_set(unit, reg, port, 0, rval)); 2622 } 2623 2624 /*L1 to L0 mapping construct*/ 2625 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2626 if (L1_TO_L0_MAPPING[unit][profile][queue_num] != -1) { 2627 soc_th3_cosq_node_t *parent; 2628 parent = &th3_cosq_mmu_info[unit]->th3_port_info[port]. 2629 L0[L1_TO_L0_MAPPING[unit][profile][queue_num]]; 2630 th3_cosq_mmu_info[unit]->th3_port_info[port]. 2631 L1[queue_num].parent = parent; 2632 } else { 2633 th3_cosq_mmu_info[unit]->th3_port_info[port]. 2634 L1[queue_num].parent = NULL; 2635 } 2636 } 2637 /*L0 to L1 mapping construct*/ 2638 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2639 if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 0) { 2640 th3_cosq_mmu_info[unit]->th3_port_info[port]. 2641 L0[queue_num].in_use = 0; 2642 continue; 2643 } else { 2644 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].in_use = 1; 2645 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].cos = 2646 L0_TO_COSQ_MAPPING[unit][profile][queue_num]; 2647 2648 if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 1) { 2649 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num]. 2650 children[0] = &th3_cosq_mmu_info[unit]->th3_port_info[port]. 2651 L1[queue_num]; 2652 } else if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 2) { 2653 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num]. 2654 children[0] = &th3_cosq_mmu_info[unit]->th3_port_info[port]. 2655 L1[queue_num]; 2656 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num]. 2657 children[1] = &th3_cosq_mmu_info[unit]->th3_port_info[port]. 2658 L1[queue_num - 1]; 2659 } else { 2660 /* No children */ 2661 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num]. 2662 children[0] = NULL; 2663 } 2664 } 2665 } 2666 /*mmuq to schedq mapping construct*/ 2667 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2668 reg = MMU_EBPCC_MMUQ_SCHQ_PROFILEr; 2669 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, profile, &rval_64)); 2670 schedq = soc_reg64_field32_get(unit, reg, rval_64, schedq_field[queue_num]); 2671 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue_num].parent = 2672 &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq]; 2673 } 2674 /*schedq to mmuq mapping construct*/ 2675 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2676 reg = MMU_PPSCH_SCHQ_MMUQ_PROFILEr; 2677 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, profile, &rval_64)); 2678 mmuq = soc_reg64_field32_get(unit, reg, rval_64, mmuq_field[queue_num]); 2679 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[queue_num].children[0] 2680 = &th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq]; 2681 } 2682 return SOC_E_NONE; 2683 } 2684 2685 /* 2686 *Function: soc_tomahawk3_sched_profile_attach_reinit 2687 *Purpose: Update port structure for scheduler based on profile information 2688 * Program the MMU to SCHQ mapping fro the profile in HW 2689 */ 2690 int 2691 soc_tomahawk3_sched_profile_attach_reinit(int unit, soc_port_t port, int profile) 2692 { 2693 int queue_num; 2694 2695 /*L1 to L0 mapping construct*/ 2696 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2697 if (L1_TO_L0_MAPPING[unit][profile][queue_num] != -1) { 2698 soc_th3_cosq_node_t *parent; 2699 parent = &th3_cosq_mmu_info[unit]->th3_port_info[port]. 2700 L0[L1_TO_L0_MAPPING[unit][profile][queue_num]]; 2701 th3_cosq_mmu_info[unit]->th3_port_info[port]. 2702 L1[queue_num].parent = parent; 2703 } else { 2704 th3_cosq_mmu_info[unit]->th3_port_info[port]. 2705 L1[queue_num].parent = NULL; 2706 } 2707 } 2708 /*L0 to L1 mapping construct*/ 2709 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 2710 if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 0) { 2711 th3_cosq_mmu_info[unit]->th3_port_info[port]. 2712 L0[queue_num].in_use = 0; 2713 continue; 2714 } else { 2715 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].in_use = 1; 2716 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num].cos = 2717 L0_TO_COSQ_MAPPING[unit][profile][queue_num]; 2718 2719 if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 1) { 2720 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num]. 2721 children[0] = &th3_cosq_mmu_info[unit]->th3_port_info[port]. 2722 L1[queue_num]; 2723 } else if (L0_TO_L1_MAPPING_NUM[unit][profile][queue_num] == 2) { 2724 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num]. 2725 children[0] = &th3_cosq_mmu_info[unit]->th3_port_info[port]. 2726 L1[queue_num]; 2727 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num]. 2728 children[1] = &th3_cosq_mmu_info[unit]->th3_port_info[port]. 2729 L1[queue_num - 1]; 2730 } else { 2731 /* No children */ 2732 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num]. 2733 children[0] = NULL; 2734 } 2735 } 2736 } 2737 2738 return SOC_E_NONE; 2739 } 2740 2741 /* 2742 *Function: soc_tomahawk3_sched_profile_get 2743 *Purpose: Get the scheduler rofile for a port 2744 */ 2745 int 2746 soc_tomahawk3_sched_profile_get(int unit, soc_port_t port, int *profile) 2747 { 2748 soc_reg_t reg; 2749 uint32 rval; 2750 2751 if (profile == NULL) { 2752 return SOC_E_PARAM; 2753 } 2754 2755 if (IS_CPU_PORT(unit, port)) { 2756 return SOC_E_NONE; 2757 } 2758 2759 reg = MMU_EBPCC_MMUQ_SCHQ_CFGr; 2760 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 2761 *profile = soc_reg_field_get(unit, reg, rval, Q_PROFILE_SELf); 2762 2763 return SOC_E_NONE; 2764 } 2765 2766 /* 2767 *Function: soc_profile_port_list_get 2768 *Purpose: retrieve information of all ports attached to a profile 2769 */ 2770 int 2771 soc_profile_port_list_get(int unit, int profile, int port_in_profile[]) 2772 { 2773 soc_reg_t reg = MMU_EBPCC_MMUQ_SCHQ_CFGr; 2774 int profile_in_use; 2775 uint32 rval; 2776 soc_port_t port; 2777 2778 SOC_PBMP_ITER(PBMP_ALL(unit), port) { 2779 if (!IS_CPU_PORT(unit, port)) { 2780 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 2781 profile_in_use = soc_reg_field_get(unit, reg, rval, Q_PROFILE_SELf); 2782 if (profile == profile_in_use) { 2783 port_in_profile[port] = 1; 2784 } else { 2785 port_in_profile[port] = 0; 2786 } 2787 } 2788 } 2789 return SOC_E_NONE; 2790 } 2791 2792 /* 2793 *Function: soc_tomahawk3_l1_to_l0_profile_set 2794 *Purpose: Update L1 to L0 mapping information in HW and teh SW structure 2795 */ 2796 int 2797 soc_tomahawk3_l1_to_l0_profile_set(int unit, int profile, int L0, int schedq, 2798 int port_in_profile[]) 2799 { 2800 soc_reg_t reg = INVALIDr; 2801 uint64 rval_64; 2802 uint32 mapping = 0; 2803 int port; 2804 uint32 rval; 2805 2806 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 2807 return SOC_E_PARAM; 2808 } 2809 2810 L1_TO_L0_MAPPING[unit][profile][schedq] = L0; 2811 L0_TO_L1_MAPPING_NUM[unit][profile][L0]++; 2812 LOG_INFO(BSL_LS_SOC_COSQ, 2813 (BSL_META_U(unit, "Profile %d L1_TO_L0_MAPPING[%d]: %d L0_TO_L1_MAPPING_NUM[%d]: %d\n"), 2814 profile, schedq, L1_TO_L0_MAPPING[unit][profile][schedq], L0, L0_TO_L1_MAPPING_NUM[unit][profile][L0])); 2815 2816 for (port = 0; port < SOC_TH3_MAX_NUM_PORTS; port++) { 2817 if (port_in_profile[port] == 1) { 2818 /* Set same value of L1 to L0 map in MTRO*/ 2819 reg = MMU_MTRO_MMUQ_SCHQ_CFGr; 2820 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 2821 mapping = soc_reg_field_get(unit, reg, rval, L1_TO_L0_MAPf); 2822 /*L1_TO_L0_MAP [x] configures L1[x], where x = 0..10. Note L1[11] 2823 *is only connected to L0[11] so is not included in this config. 2824 *bit[x]=0: (default) L1[x] connected to L0[x]; 2825 *bit[x]=1: (default) L1[x] connected to L0[x+1] 2826 */ 2827 if (schedq == L0) 2828 mapping = mapping & ~(1 << schedq); 2829 else 2830 mapping = mapping | (1 << schedq); 2831 2832 soc_reg_field_set(unit, reg, &rval, L1_TO_L0_MAPf, mapping); 2833 SOC_IF_ERROR_RETURN 2834 (soc_reg32_set(unit, reg, port, 0, rval)); 2835 2836 reg = MMU_QSCH_PORT_CONFIGr; 2837 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval_64)); 2838 soc_reg64_field32_set(unit, reg, &rval_64, L1_TO_L0_MAPPINGf, mapping); 2839 SOC_IF_ERROR_RETURN 2840 (soc_reg64_set(unit, reg, port, 0, rval_64)); 2841 2842 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].parent = 2843 &th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0]; 2844 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].in_use = 1; 2845 if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0] 2846 == NULL) { 2847 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0] 2848 = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq]; 2849 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].in_use = 1; 2850 } else { 2851 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[1] 2852 = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq]; 2853 } 2854 } 2855 } 2856 return SOC_E_NONE; 2857 } 2858 2859 /* 2860 *Function: soc_tomahawk3_l1_to_l0_profile_set_reinit 2861 *Purpose: Update L1 to L0 mapping information in HW and teh SW structure 2862 */ 2863 int 2864 soc_tomahawk3_l1_to_l0_profile_set_reinit(int unit, int profile, int L0, int schedq, 2865 int port_in_profile[]) 2866 { 2867 int port; 2868 2869 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 2870 return SOC_E_PARAM; 2871 } 2872 2873 L1_TO_L0_MAPPING[unit][profile][schedq] = L0; 2874 L0_TO_L1_MAPPING_NUM[unit][profile][L0]++; 2875 2876 for (port = 0; port < SOC_TH3_MAX_NUM_PORTS; port++) { 2877 if (port_in_profile[port] == 1) { 2878 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].parent = 2879 &th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0]; 2880 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].in_use = 1; 2881 if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0] 2882 == NULL) { 2883 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0] 2884 = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq]; 2885 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].in_use = 1; 2886 } else { 2887 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[1] 2888 = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq]; 2889 } 2890 } 2891 } 2892 return SOC_E_NONE; 2893 } 2894 2895 2896 /* 2897 *Function: soc_tomahawk3_l1_to_l0_profile_update_per_port 2898 *Purpose: Update L1 to L0 mapping information in HW and teh SW structure 2899 */ 2900 int 2901 soc_tomahawk3_l1_to_l0_profile_update_per_port(int unit, int port, int profile) 2902 { 2903 int L0[SOC_TH3_COS_MAX]; 2904 int schedq[SOC_TH3_COS_MAX]; 2905 int i; 2906 2907 for (i = 0; i < SOC_TH3_COS_MAX; i++) { 2908 L0[i] = L1_TO_L0_MAPPING[unit][profile][i]; 2909 schedq[i] = i; 2910 SOC_IF_ERROR_RETURN 2911 (soc_tomahawk3_l1_to_l0_profile_set_per_port(unit, port, profile, L0[i], schedq[i])); 2912 } 2913 return SOC_E_NONE; 2914 } 2915 2916 /* 2917 *Function: soc_tomahawk3_l1_to_l0_profile_set_per_port 2918 *Purpose: Update L1 to L0 mapping information in HW and teh SW structure 2919 */ 2920 int 2921 soc_tomahawk3_l1_to_l0_profile_set_per_port(int unit, int port, int profile, int L0, int schedq) 2922 { 2923 soc_reg_t reg = INVALIDr; 2924 uint64 rval_64; 2925 uint32 mapping = 0; 2926 uint32 rval; 2927 2928 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 2929 return SOC_E_PARAM; 2930 } 2931 2932 /* Set same value of L1 to L0 map in MTRO*/ 2933 reg = MMU_MTRO_MMUQ_SCHQ_CFGr; 2934 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 2935 mapping = soc_reg_field_get(unit, reg, rval, L1_TO_L0_MAPf); 2936 /*L1_TO_L0_MAP [x] configures L1[x], where x = 0..10. Note L1[11] 2937 *is only connected to L0[11] so is not included in this config. 2938 *bit[x]=0: (default) L1[x] connected to L0[x]; 2939 *bit[x]=1: (default) L1[x] connected to L0[x+1] 2940 */ 2941 if (schedq == L0) { 2942 mapping = mapping & ~(1 << schedq); 2943 } 2944 else { 2945 mapping = mapping | (1 << schedq); 2946 } 2947 2948 soc_reg_field_set(unit, reg, &rval, L1_TO_L0_MAPf, mapping); 2949 SOC_IF_ERROR_RETURN 2950 (soc_reg32_set(unit, reg, port, 0, rval)); 2951 2952 reg = MMU_QSCH_PORT_CONFIGr; 2953 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval_64)); 2954 soc_reg64_field32_set(unit, reg, &rval_64, L1_TO_L0_MAPPINGf, mapping); 2955 SOC_IF_ERROR_RETURN 2956 (soc_reg64_set(unit, reg, port, 0, rval_64)); 2957 2958 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].parent = 2959 &th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0]; 2960 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].in_use = 1; 2961 if (th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0] 2962 == NULL) { 2963 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[0] 2964 = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq]; 2965 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].in_use = 1; 2966 } else { 2967 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[L0].children[1] 2968 = &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq]; 2969 } 2970 2971 soc_gport_tree_print(unit, port); 2972 2973 return SOC_E_NONE; 2974 } 2975 2976 2977 /*! @fn void soc_print_port_schedule_state(int unit, 2978 * soc_port_schedule_state_t *port_schedule_state) 2979 * @param unit Chip unit number. 2980 * @param port_schedule_state Pointer to a soc_port_schedule_state_t struct 2981 * variable. 2982 * @brief Debug API to print port_schedule_state 2983 */ 2984 void 2985 soc_th3_print_port_schedule_state(int unit, 2986 soc_port_schedule_state_t *port_schedule_state) 2987 { 2988 2989 LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit, 2990 "\n\nPRINTING soc_port_schedule_state_t \n"))); 2991 2992 LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit, 2993 "frequency= %4dMHz\n"), port_schedule_state->frequency)); 2994 LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit, 2995 "DPP frequency= %4dMHz\n"), 2996 port_schedule_state->in_port_map.port_p2PBLK_inst_mapping[0])); 2997 LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit, 2998 "lossless= %1d\n"), port_schedule_state->lossless)); 2999 LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit, 3000 "is_flexport= %1d\n"), port_schedule_state->is_flexport)); 3001 3002 LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit, 3003 "\nPRINTING soc_port_schedule_state_t::in_port_map\n"))); 3004 soc_print_port_map(unit, &port_schedule_state->in_port_map); 3005 3006 if (port_schedule_state->is_flexport == 1) { 3007 LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit, 3008 "\nPRINTING soc_port_schedule_state_t::out_port_map\n"))); 3009 soc_print_port_map(unit, &port_schedule_state->out_port_map); 3010 } 3011 3012 #if 0 3013 if ((port_schedule_state->is_flexport == 1) && 3014 (port_schedule_state->nport > 0)) { 3015 LOG_DEBUG(BSL_LS_SOC_PORT, (BSL_META_U(unit, 3016 "\n====== FLEXPORT RESOURCES ===== num entries= %d = \n"), 3017 port_schedule_state->nport)); 3018 for (i = 0; i < port_schedule_state->nport; i++) { 3019 soc_print_port_resource(unit, &port_schedule_state->resource[i], i); 3020 } 3021 } 3022 #endif 3023 } 3024 3025 /*Function: 3026 * soc_tomahawk3_tdm_update 3027 *Purpose: 3028 * Setup port_schedule_state structure and call TDM init 3029 *Params: 3030 * unit: Chip unit number 3031 */ 3032 int 3033 soc_tomahawk3_tdm_update (int unit) 3034 { 3035 soc_port_schedule_state_t *port_schedule_state; 3036 int rv; 3037 3038 port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t), 3039 "Tomahawk3 soc_port_schedule_state_t"); 3040 if (port_schedule_state == NULL) { 3041 return SOC_E_MEMORY; 3042 } 3043 sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t)); 3044 rv = soc_tomahawk3_port_schedule_state_basic_setup(unit, 3045 port_schedule_state); 3046 rv = soc_tomahawk3_port_schedule_tdm_init(unit, port_schedule_state); 3047 3048 soc_th3_print_port_schedule_state(unit, port_schedule_state); 3049 3050 rv = soc_tomahawk3_tdm_init(unit, port_schedule_state); 3051 3052 if (rv != SOC_E_NONE) { 3053 LOG_CLI((BSL_META_U(unit, 3054 "Unable to configure TDM, please contact your " 3055 "Field Applications Engineer or Sales Manager for " 3056 "additional assistance.\n"))); 3057 sal_free(port_schedule_state); 3058 return rv; 3059 } 3060 3061 /* Update SOC TDM info */ 3062 /*The TDM infor needs to be captured in SOC_CONTROL->tdm_info before 3063 *port_schedule_state is freed. This function needs to be defined for TH3*/ 3064 /*rv = soc_th2_soc_tdm_update(unit, port_schedule_state);*/ 3065 3066 sal_free(port_schedule_state); 3067 return rv; 3068 } 3069 3070 /* 3071 *Function: soc_tomahawk3_cpu_l1_to_l0_profile_set 3072 *Purpose: Update L1 to L0 mapping information for CPU port 3073 */ 3074 int 3075 soc_tomahawk3_cpu_l1_to_l0_profile_set(int unit, int L0, int schedq) 3076 { 3077 soc_reg_t reg = INVALIDr; 3078 uint32 rval; 3079 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[L0].in_use = 1; 3080 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[L0].children[schedq] = 3081 &th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[schedq]; 3082 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[schedq].in_use = 1; 3083 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[schedq].parent = 3084 &th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[L0]; 3085 3086 reg = MMU_MTRO_CPU_L1_TO_L0_MAPPINGr; 3087 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, schedq, &rval)); 3088 soc_reg_field_set(unit, reg, &rval, SELECTf, L0); 3089 SOC_IF_ERROR_RETURN 3090 (soc_reg32_set(unit, reg, REG_PORT_ANY, schedq, rval)); 3091 3092 reg = MMU_QSCH_CPU_L1_TO_L0_MAPPINGr; 3093 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, schedq, &rval)); 3094 soc_reg_field_set(unit, reg, &rval, SELECTf, L0); 3095 SOC_IF_ERROR_RETURN 3096 (soc_reg32_set(unit, reg, REG_PORT_ANY, schedq, rval)); 3097 return SOC_E_NONE; 3098 } 3099 3100 /* 3101 *Function: soc_tomahawk3_mmuq_to_schedq_profile_set_per_port 3102 *Purpose: Updated MMUQ to SCHQ mapping profile 3103 */ 3104 int 3105 soc_tomahawk3_mmuq_to_schedq_profile_set_per_port(int unit, int port, int schedq, 3106 int mmuq) 3107 { 3108 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq].parent = 3109 &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq]; 3110 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].children[0] 3111 = &th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq]; 3112 return SOC_E_NONE; 3113 } 3114 /* 3115 *Function: soc_tomahawk3_mmuq_to_schedq_profile_set 3116 *Purpose: Updated MMUQ to SCHQ mapping profile 3117 */ 3118 int 3119 soc_tomahawk3_mmuq_to_schedq_profile_set(int unit, int profile, int schedq, 3120 int mmuq, int port_in_profile[]) 3121 { 3122 soc_reg_t reg = INVALIDr; 3123 uint64 rval_64; 3124 int port; 3125 soc_field_t schedq_field[12] = { 3126 SCH_Q_NUM_0f, SCH_Q_NUM_1f, 3127 SCH_Q_NUM_2f, SCH_Q_NUM_3f, 3128 SCH_Q_NUM_4f, SCH_Q_NUM_5f, 3129 SCH_Q_NUM_6f, SCH_Q_NUM_7f, 3130 SCH_Q_NUM_8f, SCH_Q_NUM_9f, 3131 SCH_Q_NUM_10f, SCH_Q_NUM_11f, 3132 }; 3133 soc_field_t mmuq_field[12] = { 3134 MMU_Q_NUM_0f, MMU_Q_NUM_1f, 3135 MMU_Q_NUM_2f, MMU_Q_NUM_3f, 3136 MMU_Q_NUM_4f, MMU_Q_NUM_5f, 3137 MMU_Q_NUM_6f, MMU_Q_NUM_7f, 3138 MMU_Q_NUM_8f, MMU_Q_NUM_9f, 3139 MMU_Q_NUM_10f, MMU_Q_NUM_11f, 3140 }; 3141 3142 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 3143 return SOC_E_PARAM; 3144 } 3145 reg = MMU_EBPCC_MMUQ_SCHQ_PROFILEr; 3146 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, profile, &rval_64)); 3147 soc_reg64_field32_set(unit, reg, &rval_64, schedq_field[mmuq], schedq); 3148 SOC_IF_ERROR_RETURN 3149 (soc_reg64_set(unit, reg, 0, profile, rval_64)); 3150 3151 reg = MMU_MTRO_MMUQ_SCHQ_PROFILEr; 3152 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, profile, &rval_64)); 3153 soc_reg64_field32_set(unit, reg, &rval_64, schedq_field[mmuq], schedq); 3154 SOC_IF_ERROR_RETURN 3155 (soc_reg64_set(unit, reg, 0, profile, rval_64)); 3156 3157 reg = MMU_PPSCH_SCHQ_MMUQ_PROFILEr; 3158 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, profile, &rval_64)); 3159 soc_reg64_field32_set(unit, reg, &rval_64, mmuq_field[schedq], mmuq); 3160 SOC_IF_ERROR_RETURN 3161 (soc_reg64_set(unit, reg, 0, profile, rval_64)); 3162 3163 for (port = 0; port < SOC_TH3_MAX_NUM_PORTS; port++) { 3164 if (port_in_profile[port] == 1) { 3165 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq].parent = 3166 &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq]; 3167 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].children[0] 3168 = &th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq]; 3169 } 3170 } 3171 return SOC_E_NONE; 3172 } 3173 3174 /* 3175 *Function: soc_tomahawk3_mmuq_to_schedq_profile_set_reinit 3176 *Purpose: Updated MMUQ to SCHQ mapping profile 3177 */ 3178 int 3179 soc_tomahawk3_mmuq_to_schedq_profile_set_reinit(int unit, int profile, int schedq, 3180 int mmuq, int port_in_profile[]) 3181 { 3182 int port; 3183 3184 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 3185 return SOC_E_PARAM; 3186 } 3187 3188 for (port = 0; port < SOC_TH3_MAX_NUM_PORTS; port++) { 3189 if (port_in_profile[port] == 1) { 3190 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq].parent = 3191 &th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq]; 3192 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[schedq].children[0] 3193 = &th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[mmuq]; 3194 } 3195 } 3196 return SOC_E_NONE; 3197 } 3198 3199 /* 3200 *Function: soc_tomahawk3_sched_update_init 3201 *Purpose: Wrapper function to set L0->schedq->MMUQ map for a specific profile 3202 */ 3203 int 3204 soc_tomahawk3_sched_update_init(int unit, int profile, int *L0, int *schedq, 3205 int *mmuq, int *cos, int *strict_priority, int* fc_is_uc_only) 3206 { 3207 int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0}; 3208 int port, queue; 3209 3210 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 3211 return SOC_E_PARAM; 3212 } 3213 /*check which ports is using this profile*/ 3214 soc_profile_port_list_get(unit, profile, port_in_profile); 3215 3216 PBMP_ALL_ITER(unit, port) { 3217 if (port_in_profile[port]) { 3218 LOG_INFO(BSL_LS_SOC_COSQ, 3219 (BSL_META_U(unit, "Port info init for port %0d\n"), 3220 port)); 3221 soc_tomahawk3_cosq_port_info_init(unit, port); 3222 } 3223 } 3224 3225 soc_tomahawk3_cosq_profile_info_init(unit, profile); 3226 3227 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3228 /* initialize per profile structure */ 3229 int cosq_index; 3230 cosq_index = L0[queue]; 3231 if (cos[queue] == -1) { 3232 continue; 3233 } 3234 th3_sched_profile_info[unit][profile][cosq_index].cos = cos[queue]; 3235 th3_sched_profile_info[unit][profile][cosq_index].strict_priority = strict_priority[queue]; 3236 th3_sched_profile_info[unit][profile][cosq_index].fc_is_uc_only = fc_is_uc_only[queue]; 3237 if (th3_sched_profile_info[unit][profile][cosq_index].mmuq[0] == -1) { 3238 th3_sched_profile_info[unit][profile][cosq_index].mmuq[0] = mmuq[queue]; 3239 } 3240 else { 3241 th3_sched_profile_info[unit][profile][cosq_index].mmuq[1] = mmuq[queue]; 3242 } 3243 3244 SOC_IF_ERROR_RETURN 3245 (soc_tomahawk3_l1_to_l0_profile_set(unit, profile, L0[queue], schedq[queue], 3246 port_in_profile)); 3247 SOC_IF_ERROR_RETURN 3248 (soc_tomahawk3_mmuq_to_schedq_profile_set(unit, profile, schedq[queue], 3249 mmuq[queue], port_in_profile)); 3250 L0_TO_COSQ_MAPPING[unit][profile][queue] = cos[queue]; 3251 } 3252 3253 SOC_IF_ERROR_RETURN 3254 (soc_cosq_sched_policy_init(unit, profile)); 3255 3256 PBMP_ALL_ITER(unit, port) { 3257 if (port_in_profile[port]) { 3258 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3259 SOC_IF_ERROR_RETURN 3260 (soc_tomahawk3_l0_cos_set(unit, port, queue, cos[queue])); 3261 } 3262 3263 LOG_INFO(BSL_LS_SOC_COSQ, 3264 (BSL_META_U(unit, "Attach port %d to profile %d\n"), 3265 port, profile)); 3266 SOC_IF_ERROR_RETURN 3267 (soc_tomahawk3_sched_profile_attach(unit, port, profile)); 3268 } 3269 } 3270 return SOC_E_NONE; 3271 } 3272 3273 /* 3274 *Function: soc_tomahawk3_sched_update_reinit 3275 *Purpose: Wrapper function to set L0->schedq->MMUQ map for a specific profile 3276 */ 3277 int 3278 soc_tomahawk3_sched_update_reinit(int unit, int profile, int *L0, int *schedq, 3279 int *mmuq, int *cos, int *strict_priority, int* fc_is_uc_only) 3280 { 3281 int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0}; 3282 int port, queue; 3283 3284 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 3285 return SOC_E_PARAM; 3286 } 3287 /*check which ports is using this profile*/ 3288 soc_profile_port_list_get(unit, profile, port_in_profile); 3289 3290 SOC_IF_ERROR_RETURN(soc_cosq_profile_struct_init(unit, profile)); 3291 3292 PBMP_ALL_ITER(unit, port) { 3293 if (port_in_profile[port]) { 3294 LOG_INFO(BSL_LS_SOC_COSQ, 3295 (BSL_META_U(unit, "Port info init for port %0d\n"), 3296 port)); 3297 soc_tomahawk3_cosq_port_info_init(unit, port); 3298 } 3299 } 3300 3301 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3302 SOC_IF_ERROR_RETURN 3303 (soc_tomahawk3_l1_to_l0_profile_set_reinit(unit, profile, L0[queue], schedq[queue], 3304 port_in_profile)); 3305 SOC_IF_ERROR_RETURN 3306 (soc_tomahawk3_mmuq_to_schedq_profile_set_reinit(unit, profile, schedq[queue], 3307 mmuq[queue], port_in_profile)); 3308 L0_TO_COSQ_MAPPING[unit][profile][queue] = cos[queue]; 3309 } 3310 3311 SOC_IF_ERROR_RETURN 3312 (soc_cosq_sched_policy_reinit(unit, profile)); 3313 3314 PBMP_ALL_ITER(unit, port) { 3315 if (port_in_profile[port]) { 3316 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3317 SOC_IF_ERROR_RETURN 3318 (soc_tomahawk3_l0_cos_set(unit, port, queue, cos[queue])); 3319 } 3320 3321 LOG_INFO(BSL_LS_SOC_COSQ, 3322 (BSL_META_U(unit, "Attach port %d to profile %d\n"), 3323 port, profile)); 3324 SOC_IF_ERROR_RETURN 3325 (soc_tomahawk3_sched_profile_attach_reinit(unit, port, profile)); 3326 } 3327 } 3328 return SOC_E_NONE; 3329 } 3330 3331 3332 /* 3333 *Function: soc_tomahawk3_sched_update_flex_per_port 3334 *Purpose: Wrapper function to set L0->schedq->MMUQ map for a specific profile 3335 */ 3336 int 3337 soc_tomahawk3_sched_update_flex_per_port(int unit, int port, int profile, int *L0, int *schedq, 3338 int *mmuq, int *cos) 3339 { 3340 int queue; 3341 3342 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 3343 return SOC_E_PARAM; 3344 } 3345 3346 soc_tomahawk3_cosq_port_info_init(unit, port); 3347 3348 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3349 SOC_IF_ERROR_RETURN 3350 (soc_tomahawk3_l1_to_l0_profile_set_per_port(unit, port, profile, L0[queue], schedq[queue])); 3351 SOC_IF_ERROR_RETURN 3352 (soc_tomahawk3_mmuq_to_schedq_profile_set_per_port(unit, port, schedq[queue], 3353 mmuq[queue])); 3354 } 3355 3356 /* Not needed for flex . Done in cosq_port_attach 3357 SOC_IF_ERROR_RETURN 3358 (soc_cosq_sched_policy_init(unit, profile, sp_child, sp_parent)); 3359 */ 3360 3361 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3362 SOC_IF_ERROR_RETURN 3363 (soc_tomahawk3_l0_cos_set(unit, port, queue, cos[queue])); 3364 } 3365 3366 LOG_INFO(BSL_LS_SOC_COSQ, 3367 (BSL_META_U(unit, "Attach port %d to profile %d\n"), 3368 port, profile)); 3369 SOC_IF_ERROR_RETURN 3370 (soc_tomahawk3_sched_profile_attach(unit, port, profile)); 3371 3372 return SOC_E_NONE; 3373 } 3374 3375 /* 3376 *Function: soc_tomahawk3_sched_profile_set 3377 *Purpose: Wrapper function to set L0->schedq->MMUQ map for a specific profile 3378 */ 3379 int 3380 soc_tomahawk3_sched_profile_set(int unit, int profile, int L0, int schedq, 3381 int mmuq) 3382 { 3383 int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0}; 3384 3385 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 3386 return SOC_E_PARAM; 3387 } 3388 /*check which ports is using this profile*/ 3389 soc_profile_port_list_get(unit, profile, port_in_profile); 3390 3391 SOC_IF_ERROR_RETURN 3392 (soc_tomahawk3_l1_to_l0_profile_set(unit, profile, L0, schedq, 3393 port_in_profile)); 3394 SOC_IF_ERROR_RETURN 3395 (soc_tomahawk3_mmuq_to_schedq_profile_set(unit, profile, schedq, 3396 mmuq, port_in_profile)); 3397 3398 return SOC_E_NONE; 3399 } 3400 3401 /* 3402 *Function: soc_cosq_hierarchy_init 3403 *Purpose: Wrapper function to setup scheduler hierarchy for the unit 3404 */ 3405 int 3406 soc_cosq_hierarchy_init(int unit) 3407 { 3408 #define _TH3_MMU_NUM_CPU_QUEUES_PER_COS 4 3409 int profile = 0; 3410 int queue, cpu_l1; 3411 soc_port_t port; 3412 int i, rv; 3413 _soc_mmu_cfg_scheduler_profile_t *sched_profile; 3414 int L0[SOC_TH3_NUM_GP_QUEUES]; 3415 int schedq[SOC_TH3_NUM_GP_QUEUES]; 3416 int mmuq[SOC_TH3_NUM_GP_QUEUES]; 3417 int cos_list[SOC_TH3_NUM_GP_QUEUES]; 3418 int strict_priority[SOC_TH3_NUM_GP_QUEUES]; 3419 int fc_is_uc_only[SOC_TH3_NUM_GP_QUEUES]; 3420 int sched_port_profile_map[SOC_TH3_MAX_NUM_PORTS]; 3421 int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0}; 3422 3423 rv = SOC_E_NONE; 3424 3425 /* Override default init from config.bcm */ 3426 sched_profile = soc_mmu_cfg_scheduler_profile_alloc(unit); 3427 if (!sched_profile) { 3428 return SOC_E_MEMORY; 3429 } 3430 3431 /*Map all ports to use profile 0 by default*/ 3432 for (i = 0; i < SOC_TH3_MAX_NUM_PORTS; i++) 3433 sched_port_profile_map[i] = 0; 3434 3435 /* Override via bcm config */ 3436 rv = _soc_mmu_tomahawk3_scheduler_profile_reset(unit, sched_profile); 3437 if (rv != SOC_E_NONE) { 3438 goto exit; 3439 } 3440 _soc_mmu_cfg_scheduler_profile_read(unit, sched_profile, sched_port_profile_map); 3441 rv = _soc_mmu_tomahawk3_scheduler_profile_check(unit, sched_profile); 3442 3443 /* If overriden values break the rules, do back to default */ 3444 if (SOC_FAILURE(rv)) { 3445 LOG_INFO(BSL_LS_SOC_COSQ, 3446 (BSL_META_U(unit, "Override failed Resetting scheduler profile to default init\n"))); 3447 rv = _soc_mmu_tomahawk3_scheduler_profile_reset(unit, sched_profile); 3448 if (rv != SOC_E_NONE) { 3449 goto exit; 3450 } 3451 } 3452 3453 /* Init */ 3454 3455 /*Map ports to profile. Default is profile 0 */ 3456 PBMP_ALL_ITER(unit, port) { 3457 LOG_INFO(BSL_LS_SOC_COSQ, 3458 (BSL_META_U(unit, "Attach port %d to profile %d\n"), 3459 port, sched_port_profile_map[port])); 3460 rv = soc_tomahawk3_sched_profile_attach(unit, port, sched_port_profile_map[port]); 3461 if (rv != SOC_E_NONE) { 3462 goto exit; 3463 } 3464 } 3465 3466 for (profile = 0; profile < SOC_TH3_MAX_NUM_SCHED_PROFILE; profile++) { 3467 soc_tomahawk3_cosq_profile_info_init(unit, profile); 3468 3469 if (sched_profile[profile].valid != 1) { 3470 3471 continue; 3472 } 3473 3474 rv = _soc_scheduler_profile_mapping_setup(unit, sched_profile, profile, 3475 L0, schedq, mmuq, cos_list, strict_priority, fc_is_uc_only); 3476 if (rv != SOC_E_NONE) { 3477 goto exit; 3478 } 3479 3480 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3481 /* initialize per profile structure */ 3482 int cosq_index; 3483 cosq_index = L0[queue]; 3484 if (cos_list[queue] == -1) { 3485 continue; 3486 } 3487 th3_sched_profile_info[unit][profile][cosq_index].cos = cos_list[queue]; 3488 th3_sched_profile_info[unit][profile][cosq_index].strict_priority = strict_priority[queue]; 3489 th3_sched_profile_info[unit][profile][cosq_index].fc_is_uc_only = fc_is_uc_only[queue]; 3490 if (th3_sched_profile_info[unit][profile][cosq_index].mmuq[0] == -1) { 3491 th3_sched_profile_info[unit][profile][cosq_index].mmuq[0] = mmuq[queue]; 3492 } 3493 else { 3494 th3_sched_profile_info[unit][profile][cosq_index].mmuq[1] = mmuq[queue]; 3495 } 3496 3497 /*initilization of L0.i->schedq.i->mmuq.i*/ 3498 rv = soc_tomahawk3_sched_profile_set(unit, profile, L0[queue], schedq[queue], mmuq[queue]); 3499 if (rv != SOC_E_NONE) { 3500 goto exit; 3501 } 3502 L0_TO_COSQ_MAPPING[unit][profile][queue] = cos_list[queue]; 3503 } 3504 rv = soc_cosq_sched_policy_init(unit, profile); 3505 if (rv != SOC_E_NONE) { 3506 goto exit; 3507 } 3508 3509 /*check which ports is using this profile*/ 3510 soc_profile_port_list_get(unit, profile, port_in_profile); 3511 3512 PBMP_ALL_ITER(unit, port) { 3513 if (port_in_profile[port]) { 3514 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3515 /* Max number of device ports in TH3 is 160*/ 3516 if (cos_list[queue] == -1) { 3517 continue; 3518 } 3519 rv = soc_tomahawk3_l0_cos_set(unit, port, queue, cos_list[queue]); 3520 if (rv != SOC_E_NONE) { 3521 goto exit; 3522 } 3523 } 3524 } 3525 } 3526 } 3527 3528 /* CPU Port */ 3529 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3530 for(i = 0; i < _TH3_MMU_NUM_CPU_QUEUES_PER_COS; i++) { 3531 cpu_l1 = queue * _TH3_MMU_NUM_CPU_QUEUES_PER_COS + i; 3532 if (cpu_l1 >= SOC_TH3_NUM_CPU_QUEUES) { 3533 break; 3534 } else { 3535 rv = soc_tomahawk3_cpu_l1_to_l0_profile_set(unit, 0, cpu_l1); 3536 if (rv != SOC_E_NONE) { 3537 goto exit; 3538 } 3539 } 3540 } 3541 } 3542 3543 exit: 3544 soc_mmu_cfg_scheduler_profile_free(unit, sched_profile); 3545 3546 #undef _TH3_MMU_NUM_CPU_QUEUES_PER_COS 3547 3548 return rv; 3549 } 3550 3551 /* 3552 *Function: soc_cosq_sched_policy_init 3553 *Purpose: Initialize scheduling discipline in HW and SW structure based on config bcm 3554 */ 3555 int 3556 soc_cosq_sched_policy_init(int unit, int profile) 3557 { 3558 soc_reg_t reg = INVALIDr; 3559 uint64 rval; 3560 int queue_num; 3561 soc_port_t port; 3562 int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0}; 3563 3564 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 3565 return SOC_E_PARAM; 3566 } 3567 3568 /*check which ports is using this profile*/ 3569 soc_profile_port_list_get(unit, profile, port_in_profile); 3570 3571 PBMP_ALL_ITER(unit, port) { 3572 /* Max number of device ports in TH3 is 160*/ 3573 if (!IS_CPU_PORT(unit, port)) { 3574 if (port_in_profile[port] == 0) 3575 continue; 3576 reg = MMU_QSCH_PORT_CONFIGr; 3577 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval)); 3578 soc_reg64_field32_set(unit, reg, &rval, ENABLE_WRRf, 1); 3579 soc_reg64_field32_set(unit, reg, &rval, SP_L0_CHILDf, 0); 3580 soc_reg64_field32_set(unit, reg, &rval, SP_L0_PARENTf, 0); 3581 SOC_IF_ERROR_RETURN 3582 (soc_reg64_set(unit, reg, port, 0, rval)); 3583 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 3584 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num]. 3585 sched_policy = SOC_TH3_SCHED_MODE_WRR; 3586 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[queue_num]. 3587 sched_policy = SOC_TH3_SCHED_MODE_WRR; 3588 } 3589 } else { 3590 reg = MMU_QSCH_CPU_PORT_CONFIGr; 3591 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 0, 0, &rval)); 3592 soc_reg64_field32_set(unit, reg, &rval, ENABLE_WRRf, 1); 3593 soc_reg64_field32_set(unit, reg, &rval, SP_L0f, 0); 3594 soc_reg64_field32_set(unit, reg, &rval, SP_L1f, 0); 3595 SOC_IF_ERROR_RETURN 3596 (soc_reg64_set(unit, reg, 0, 0, rval)); 3597 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 3598 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num]. 3599 sched_policy = SOC_TH3_SCHED_MODE_WRR; 3600 } 3601 for (queue_num = 0; queue_num < SOC_TH3_NUM_CPU_QUEUES; queue_num++) { 3602 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num]. 3603 sched_policy = SOC_TH3_SCHED_MODE_WRR; 3604 } 3605 } 3606 } 3607 return SOC_E_NONE; 3608 } 3609 3610 /* 3611 *Function: soc_cosq_sched_policy_reinit 3612 *Purpose: Initialize scheduling discipline in HW and SW structure based on config bcm 3613 */ 3614 int 3615 soc_cosq_sched_policy_reinit(int unit, int profile) 3616 { 3617 int queue_num; 3618 soc_port_t port; 3619 int port_in_profile[SOC_TH3_MAX_NUM_PORTS] = {0}; 3620 3621 if (profile < 0 || profile >= SOC_TH3_MAX_NUM_SCHED_PROFILE) { 3622 return SOC_E_PARAM; 3623 } 3624 3625 /*check which ports is using this profile*/ 3626 soc_profile_port_list_get(unit, profile, port_in_profile); 3627 3628 PBMP_ALL_ITER(unit, port) { 3629 /* Max number of device ports in TH3 is 160*/ 3630 if (!IS_CPU_PORT(unit, port)) { 3631 if (port_in_profile[port] == 0) 3632 continue; 3633 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 3634 th3_cosq_mmu_info[unit]->th3_port_info[port].L0[queue_num]. 3635 sched_policy = SOC_TH3_SCHED_MODE_WRR; 3636 th3_cosq_mmu_info[unit]->th3_port_info[port].L1[queue_num]. 3637 sched_policy = SOC_TH3_SCHED_MODE_WRR; 3638 } 3639 } else { 3640 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 3641 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue_num]. 3642 sched_policy = SOC_TH3_SCHED_MODE_WRR; 3643 } 3644 for (queue_num = 0; queue_num < SOC_TH3_NUM_CPU_QUEUES; queue_num++) { 3645 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L1[queue_num]. 3646 sched_policy = SOC_TH3_SCHED_MODE_WRR; 3647 } 3648 } 3649 } 3650 return SOC_E_NONE; 3651 } 3652 3653 3654 3655 /* 3656 *Function: soc_tomahawk3_schduler_hier_show 3657 *Purpose: FUnction to display configured hierarchy 3658 */ 3659 int 3660 soc_tomahawk3_schduler_hier_show(int unit,int port) 3661 { 3662 int queue, queue_num; 3663 3664 if (SOC_PORT_VALID(unit, port)) { 3665 LOG_CLI(("PORT L0 COS SCHEDQ MMUQ\n")); 3666 if (IS_CPU_PORT(unit, port)) { 3667 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3668 for (queue_num = 0; queue_num < SOC_TH3_NUM_CPU_QUEUES; 3669 queue_num++) { 3670 if (th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue]. 3671 children[queue_num] != NULL) { 3672 LOG_CLI((BSL_META_U(unit, 3673 "%-8d "), port)); 3674 LOG_CLI((BSL_META_U(unit, 3675 "%-8d "), 3676 th3_cosq_mmu_info[unit]->th3_cpu_port_info.L0[queue]. 3677 hw_index)); 3678 LOG_CLI((BSL_META_U(unit, 3679 "%-8d "), 3680 th3_cosq_mmu_info[unit]->th3_cpu_port_info. 3681 L0[queue].cos)); 3682 LOG_CLI((BSL_META_U(unit, 3683 "%-8d \n"), 3684 queue_num)); 3685 } 3686 } 3687 } 3688 } else { 3689 for (queue = 0; queue < SOC_TH3_NUM_GP_QUEUES; queue++) { 3690 /* Max number of device ports in TH3 is 160*/ 3691 /* coverity[overrun-local] */ 3692 if (th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue]. 3693 parent == NULL || 3694 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue]. 3695 parent->parent == NULL) { 3696 LOG_CLI((BSL_META_U(unit, 3697 "%-8d unknown unknown unknown %d\n"), 3698 port, queue)); 3699 } else { 3700 LOG_CLI((BSL_META_U(unit, 3701 "%-8d "), port)); 3702 LOG_CLI((BSL_META_U(unit, 3703 "%-8d "), 3704 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue]. 3705 parent->parent->hw_index)); 3706 LOG_CLI((BSL_META_U(unit, 3707 "%-8d "), 3708 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue]. 3709 parent->parent->cos)); 3710 LOG_CLI((BSL_META_U(unit, 3711 "%-8d "), 3712 th3_cosq_mmu_info[unit]->th3_port_info[port].mmuq[queue]. 3713 parent->hw_index)); 3714 LOG_CLI((BSL_META_U(unit, 3715 "%-8d \n"), queue)); 3716 } 3717 } 3718 } 3719 } else { 3720 LOG_CLI(("Invalid port: %d \n", port)); 3721 return SOC_E_PORT; 3722 } 3723 return SOC_E_NONE; 3724 } 3725 3726 3727 /* 3728 *Function: soc_tomahawk3_scheduler_init 3729 *Purpose: Wrapper for init code 3730 */ 3731 int 3732 soc_tomahawk3_scheduler_init(int unit) 3733 { 3734 int mode = 2; 3735 uint32 rval; 3736 int pipe, voq_fairness_en = 1; 3737 uint32 pipe_map, itm_map; 3738 soc_info_t *si = &SOC_INFO(unit); 3739 int itm, num_valid_itms = 0; 3740 /* int port, cosq_idx; */ 3741 3742 mode = soc_property_get(unit, spn_MMU_PORT_NUM_MC_QUEUE, _TH3_MC_Q_MODE_DEFAULT); 3743 SOC_IF_ERROR_RETURN 3744 (soc_tomahawk3_mcq_mode_set(unit, mode)); 3745 SOC_IF_ERROR_RETURN 3746 (soc_cosq_struct_init(unit)); 3747 SOC_IF_ERROR_RETURN 3748 (soc_cosq_hierarchy_init(unit)); 3749 3750 itm_map = si->itm_map; 3751 for (itm = 0; itm < NUM_ITM(unit); itm++) { 3752 if (itm_map & (1 << itm)) { 3753 num_valid_itms++; 3754 } 3755 } 3756 if (num_valid_itms < NUM_ITM(unit)) { 3757 voq_fairness_en = 0; 3758 } 3759 3760 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 3761 3762 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) { 3763 if (pipe_map & (1 << pipe)) { 3764 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, MMU_QSCH_SPECIAL_CONFIGr, 3765 pipe, 0, &rval)); 3766 soc_reg_field_set(unit, MMU_QSCH_SPECIAL_CONFIGr, &rval, 3767 ENABLE_THDO_INFOf, voq_fairness_en); 3768 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_QSCH_SPECIAL_CONFIGr, 3769 pipe, 0, rval)); 3770 } 3771 } 3772 3773 return SOC_E_NONE; 3774 } 3775 3776 /*Function: soc_tomahawk3_idb_init_update 3777 *Purpose: IDB init sequence and threhsold configuration 3778 *Param: 3779 * unit: Device unit number 3780 */ 3781 int 3782 soc_tomahawk3_idb_init_update(int unit) 3783 { 3784 soc_port_schedule_state_t *port_schedule_state; 3785 3786 port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t), 3787 "Tomahawk3 soc_port_schedule_state_t"); 3788 if (port_schedule_state == NULL) { 3789 return SOC_E_MEMORY; 3790 } 3791 sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t)); 3792 3793 SOC_IF_ERROR_RETURN(soc_tomahawk3_port_schedule_state_basic_setup(unit, 3794 port_schedule_state)); 3795 3796 SOC_IF_ERROR_RETURN(soc_tomahawk3_idb_init(unit, port_schedule_state)); 3797 3798 sal_free(port_schedule_state); 3799 3800 return SOC_E_NONE; 3801 } 3802 3803 /*Function: soc_tomahawk3_cdport_init 3804 *Purpose: CDPORT init sequence for pm8x50 ports 3805 *Param: 3806 * unit: Device unit number 3807 */ 3808 int 3809 soc_tomahawk3_cdport_init (int unit) 3810 { 3811 soc_port_schedule_state_t *port_schedule_state; 3812 int pipe, pm, pmnum; 3813 soc_info_t *si = &SOC_INFO(unit); 3814 3815 port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t), 3816 "Tomahawk3 soc_port_schedule_state_t"); 3817 if (port_schedule_state == NULL) { 3818 return SOC_E_MEMORY; 3819 } 3820 sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t)); 3821 3822 SOC_IF_ERROR_RETURN(soc_tomahawk3_port_schedule_state_basic_setup 3823 (unit, port_schedule_state)); 3824 3825 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) { 3826 if (!SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 3827 for (pm = 0; pm < _TH3_PBLKS_PER_PIPE; pm++) { 3828 pmnum = pipe * _TH3_PBLKS_PER_PIPE + pm; 3829 /*Set CDPORT_MAC_MODE based on port speed*/ 3830 SOC_IF_ERROR_RETURN(soc_tomahawk3_set_cdmac_port_mode( 3831 unit, &port_schedule_state->out_port_map, pmnum)); 3832 } 3833 } 3834 } 3835 3836 sal_free(port_schedule_state); 3837 return SOC_E_NONE; 3838 } 3839 3840 /*Function: 3841 * soc_tomahawk3_ep_top_init 3842 *Purpose: 3843 * EP to Dev port map 3844 * Initialize cell credits from MMU tpo EDB based on port speed 3845 * Set CT class init 3846 * EDB start xmit count 3847 * EGR_ENABLE.PRT_ENABLE is set 3848 *Params: 3849 * unit: Chip unit number 3850 */ 3851 int 3852 soc_tomahawk3_ep_top_init(int unit) 3853 { 3854 soc_port_schedule_state_t *port_schedule_state; 3855 3856 port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t), 3857 "Tomahawk3 soc_port_schedule_state_t"); 3858 if (port_schedule_state == NULL) { 3859 return SOC_E_MEMORY; 3860 } 3861 sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t)); 3862 3863 SOC_IF_ERROR_RETURN(soc_tomahawk3_port_schedule_state_basic_setup(unit, 3864 port_schedule_state)); 3865 3866 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_init(unit, port_schedule_state)); 3867 3868 sal_free(port_schedule_state); 3869 return SOC_E_NONE; 3870 } 3871 3872 /*Function: 3873 * soc_tomahawk3_slot_pipeline_config 3874 *Purpose: 3875 * Configure slot pipieline latency in EP based on chip latency mode 3876 * and Core to DPP clock frequency ratio 3877 *Params: 3878 * unit: Chip unit number 3879 */ 3880 int 3881 soc_tomahawk3_slot_pipeline_config(int unit) 3882 { 3883 soc_port_schedule_state_t *port_schedule_state; 3884 port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t), 3885 "Tomahawk3 soc_port_schedule_state_t"); 3886 if (port_schedule_state == NULL) { 3887 return SOC_E_MEMORY; 3888 } 3889 sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t)); 3890 3891 SOC_IF_ERROR_RETURN(soc_tomahawk3_port_schedule_state_basic_setup(unit, 3892 port_schedule_state)); 3893 /*Epost slot pipeline config*/ 3894 SOC_IF_ERROR_RETURN( 3895 soc_tomahawk3_ep_set_slot_pipeline_config(unit, port_schedule_state)); 3896 /*Ipost slot pipeline config*/ 3897 SOC_IF_ERROR_RETURN( 3898 soc_tomahawk3_ip_slot_pipeline_config(unit, port_schedule_state)); 3899 3900 sal_free(port_schedule_state); 3901 return SOC_E_NONE; 3902 } 3903 3904 /*Function: 3905 * soc_tomahawk3_enable_ingress_forwarding 3906 *Purpose: 3907 * Enable traffic forwarding to port in IP 3908 *Params: 3909 * unit: Chip unit number 3910 */ 3911 int 3912 soc_tomahawk3_enable_ingress_forwarding (int unit) 3913 { 3914 soc_port_schedule_state_t *port_schedule_state; 3915 port_schedule_state = sal_alloc(sizeof(soc_port_schedule_state_t), 3916 "Tomahawk3 soc_port_schedule_state_t"); 3917 if (port_schedule_state == NULL) { 3918 return SOC_E_MEMORY; 3919 } 3920 sal_memset(port_schedule_state, 0, sizeof(soc_port_schedule_state_t)); 3921 3922 SOC_IF_ERROR_RETURN(soc_tomahawk3_port_schedule_state_basic_setup(unit, 3923 port_schedule_state)); 3924 3925 SOC_IF_ERROR_RETURN 3926 (soc_tomahawk3_en_epc_link_bmap(unit, port_schedule_state)); 3927 SOC_IF_ERROR_RETURN 3928 (soc_tomahawk3_en_dest_port_bmap(unit, port_schedule_state)); 3929 3930 sal_free(port_schedule_state); 3931 return SOC_E_NONE; 3932 } 3933 3934 /* 3935 * Function: _soc_tomahawk3_per_port_speed_encode_program 3936 * Purpose: Initialize cell pointer memory in MMU during init 3937 * Param: unit: device number 3938 * : port: Global device port number 3939 * : port_speed: Port speed in Mbps 3940 */ 3941 STATIC int 3942 _soc_tomahawk3_per_port_speed_encode_program(int unit, int port, 3943 int port_speed) 3944 { 3945 struct { 3946 soc_reg_t ref_reg; 3947 soc_field_t encode_field; 3948 } rf_list[] = { 3949 {MMU_CRB_SRC_PORT_CFGr, PORT_SPEEDf}, 3950 {MMU_EBCTM_EPORT_CT_CFGr, DST_PORT_SPEEDf}, 3951 {MMU_SCB_SOURCE_PORT_CFGr, PORT_SPEEDf}, 3952 {MMU_EBPCC_EPORT_CFGr, DST_PORT_SPEEDf}, 3953 {MMU_EBQS_PORT_CFGr, PORT_SPEEDf}, 3954 {INVALIDr, INVALIDf} 3955 }; 3956 uint32 rval; 3957 int i, special_speed_encode_val = 0, speed_encode_val = 0, oqs_speed_encoding = 0; 3958 soc_reg_t oqs_reg = MMU_OQS_AGER_DST_PORT_MAPr; 3959 3960 /*Retrieve encoding value to be used based on port speed*/ 3961 /* Speed encoding 3962 *0 - Reserved, 3963 *1 - 10G, 3964 *2 - 25G, 3965 *3 - 40G, 3966 *4 - 50G, 3967 *5 - 100G, 3968 *6 - 200G, 3969 *7 - 400G 3970 */ 3971 switch (port_speed) { 3972 case 400000: speed_encode_val = 7; break; 3973 case 200000: speed_encode_val = 6; break; 3974 case 100000: speed_encode_val = 5; break; 3975 case 50000: speed_encode_val = 4; break; 3976 case 40000: speed_encode_val = 3; break; 3977 case 25000: speed_encode_val = 2; break; 3978 case 10000: speed_encode_val = 1; break; 3979 default: speed_encode_val = 0; break; 3980 } 3981 /* SDK-130693: Special configuration needed for ports with 3982 port speed below 100G in SCB */ 3983 switch (port_speed) { 3984 case 400000: special_speed_encode_val = 7; break; 3985 case 200000: special_speed_encode_val = 6; break; 3986 case 100000: special_speed_encode_val = 5; break; 3987 case 50000: special_speed_encode_val = 5; break; 3988 case 40000: special_speed_encode_val = 5; break; 3989 case 25000: special_speed_encode_val = 5; break; 3990 case 10000: special_speed_encode_val = 5; break; 3991 default: special_speed_encode_val = 0; break; 3992 } 3993 for (i = 0; rf_list[i].ref_reg != INVALIDr; i++) { 3994 if (!SOC_REG_IS_VALID(unit, rf_list[i].ref_reg)) { 3995 continue; 3996 } 3997 if ((rf_list[i].ref_reg == MMU_EBCTM_EPORT_CT_CFGr) && 3998 ((IS_MANAGEMENT_PORT(unit, port)) || 3999 (IS_CPU_PORT(unit, port)) || 4000 (IS_LB_PORT(unit, port)))) { 4001 /*Register valid only for non-management front panel ports*/ 4002 continue; 4003 } 4004 SOC_IF_ERROR_RETURN 4005 (soc_reg32_get(unit, rf_list[i].ref_reg, port, 0, &rval)); 4006 if (rf_list[i].ref_reg == MMU_SCB_SOURCE_PORT_CFGr) { 4007 /* SDK-130693: Special configuration needed for ports with 4008 port speed below 100G in SCB */ 4009 soc_reg_field_set(unit, rf_list[i].ref_reg, &rval, 4010 rf_list[i].encode_field, special_speed_encode_val); 4011 } else { 4012 soc_reg_field_set(unit, rf_list[i].ref_reg, &rval, 4013 rf_list[i].encode_field, speed_encode_val); 4014 } 4015 SOC_IF_ERROR_RETURN 4016 (soc_reg32_set(unit, rf_list[i].ref_reg, port, 0, rval)); 4017 } 4018 /*Setup port speed in OQS ager based on 4-speed encoding*/ 4019 /*port_speed encoding - 0:<=50GE, 1:100GE, 2:200GE, 3:400GE*/ 4020 if (port_speed <= 50000) { 4021 oqs_speed_encoding = 0; 4022 } else if (port_speed == 100000) { 4023 oqs_speed_encoding = 1; 4024 } else if (port_speed == 200000) { 4025 oqs_speed_encoding = 2; 4026 } else if (port_speed == 400000) { 4027 oqs_speed_encoding = 3; 4028 } else { 4029 return SOC_E_PARAM; 4030 } 4031 SOC_IF_ERROR_RETURN 4032 (soc_reg32_get(unit, oqs_reg, port, 0, &rval)); 4033 soc_reg_field_set(unit, oqs_reg, &rval, PORT_SPEEDf, oqs_speed_encoding); 4034 SOC_IF_ERROR_RETURN 4035 (soc_reg32_set(unit, oqs_reg, port, 0, rval)); 4036 return SOC_E_NONE; 4037 } 4038 4039 /* 4040 * Function: soc_tomahawk3_tm_port_speed_encoding 4041 * Purpose: Setup port speed encoding in different MMU stages 4042 * Param: unit: device number 4043 */ 4044 int 4045 soc_tomahawk3_tm_port_speed_encoding(int unit) 4046 { 4047 int port, speed; 4048 soc_info_t *si = &SOC_INFO(unit); 4049 int speed_encode; 4050 /* recommended values of ager_limit based on speed encoding*/ 4051 int ager_limit[4] = {4, 4, 3, 2}; 4052 soc_reg_t reg; 4053 soc_field_t field; 4054 int index, cpu_ager_limit; 4055 uint32 rval = 0; 4056 4057 /*Front panel ports*/ 4058 PBMP_PORT_ITER(unit, port) { 4059 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 4060 continue; 4061 } 4062 speed = si->port_speed_max[port]; 4063 SOC_IF_ERROR_RETURN 4064 (_soc_tomahawk3_per_port_speed_encode_program(unit, port, speed)); 4065 } 4066 /*LB ports*/ 4067 #define _TH3_SPL_PORT_SPEED 10000 4068 PBMP_LB_ITER(unit, port) { 4069 SOC_IF_ERROR_RETURN 4070 (_soc_tomahawk3_per_port_speed_encode_program(unit, port, 4071 _TH3_SPL_PORT_SPEED)); 4072 } 4073 /*CPU port*/ 4074 #define _TH3_CPU_PORT_NUM 0 4075 SOC_IF_ERROR_RETURN 4076 (_soc_tomahawk3_per_port_speed_encode_program(unit, _TH3_CPU_PORT_NUM, 4077 _TH3_SPL_PORT_SPEED)); 4078 #undef _TH3_CPU_PORT_NUM 4079 #undef _TH3_SPL_PORT_SPEED 4080 4081 /* Configure OQS ager limit based on port speed encoding. */ 4082 reg = MMU_OQS_AGER_LIMITr; 4083 field = AGER_LIMITf; 4084 /* OQS port_speed encoding - 0:<=50GE, 1:100GE, 2:200GE, 3:400GE*/ 4085 for (speed_encode = 0; speed_encode < 4; speed_encode++) { 4086 /* Program same ager limit for 2 indices mapped to the same speed encode */ 4087 /* indexed by {port_speed[1:0], HP_MMUQ[0]} */ 4088 for (index = (speed_encode * 2); index < ((speed_encode + 1) * 2); 4089 index++) { 4090 rval = 0; 4091 SOC_IF_ERROR_RETURN 4092 (soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval)); 4093 soc_reg_field_set(unit, reg, &rval, field, ager_limit[speed_encode]); 4094 SOC_IF_ERROR_RETURN 4095 (soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval)); 4096 } 4097 } 4098 /* Ager limit config for CPU port */ 4099 index = 8; 4100 rval = 0; 4101 cpu_ager_limit = 4; 4102 SOC_IF_ERROR_RETURN 4103 (soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval)); 4104 soc_reg_field_set(unit, reg, &rval, field, cpu_ager_limit); 4105 SOC_IF_ERROR_RETURN 4106 (soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval)); 4107 4108 return SOC_E_NONE; 4109 } 4110 4111 /* 4112 * Function to Set Parent(L0) for a given L1 queue of the CPU port 4113 * Note: Only child @ L1 level is supported. 4114 * Because only L1 level queues can be attached to different parent (L0.0-L0.9) 4115 * of the CPU port. 4116 */ 4117 int 4118 soc_th3_cosq_cpu_parent_set(int unit, int child_index, int child_level, 4119 int parent_index) 4120 { 4121 if (child_level != SOC_TH3_NODE_LVL_L1) { 4122 /* Only child at L1 are allowed to move */ 4123 return SOC_E_PARAM; 4124 } 4125 soc_tomahawk3_cpu_l1_to_l0_profile_set(unit, parent_index, child_index); 4126 4127 return SOC_E_NONE; 4128 } 4129 4130 int 4131 soc_th3_sched_weight_set(int unit, int port, int level, 4132 int index, int weight, int mc) 4133 { 4134 soc_info_t *si; 4135 soc_mem_t mem = INVALIDm; 4136 uint32 entry[SOC_MAX_MEM_WORDS]; 4137 int pipe, local_mmu_port; 4138 4139 si = &SOC_INFO(unit); 4140 4141 pipe = si->port_pipe[port]; 4142 local_mmu_port = SOC_TH3_MMU_LOCAL_PORT(unit, port); 4143 4144 if (level == SOC_TH3_NODE_LVL_L0) { 4145 mem = MMU_QSCH_L0_WEIGHT_MEMm; 4146 if (IS_CPU_PORT(unit, port)) { 4147 index = TH3_MMU_CPU_MCQ_OFFSET + index; 4148 } else if (IS_LB_PORT(unit, port)) { 4149 index = TH3_MMU_LB_MCQ_OFFSET + index; 4150 } else if (SOC_PBMP_MEMBER(si->management_pbm, port)) { 4151 index = TH3_MMU_MGMT_Q_OFFSET + index; 4152 } else { 4153 index = (local_mmu_port * SOC_TH3_NUM_GP_QUEUES) + index; 4154 } 4155 } else if (level == SOC_TH3_NODE_LVL_L1) { 4156 mem = MMU_QSCH_L1_WEIGHT_MEMm; 4157 4158 if (IS_CPU_PORT(unit, port)) { 4159 index = TH3_MMU_CPU_MCQ_OFFSET + index; 4160 } else if (IS_LB_PORT(unit, port)) { 4161 index = TH3_MMU_LB_MCQ_OFFSET + index; 4162 } else if (SOC_PBMP_MEMBER(si->management_pbm, port)) { 4163 index = TH3_MMU_MGMT_Q_OFFSET + index; 4164 } else { 4165 index = (local_mmu_port * SOC_TH3_NUM_GP_QUEUES) + index; 4166 } 4167 } else { 4168 return SOC_E_PARAM; 4169 } 4170 4171 mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe]; 4172 4173 SOC_IF_ERROR_RETURN 4174 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 4175 soc_mem_field32_set(unit, mem, &entry, WEIGHTf, weight); 4176 SOC_IF_ERROR_RETURN 4177 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &entry)); 4178 4179 return SOC_E_NONE; 4180 } 4181 4182 /* 4183 * Function to Get Parent(L0) for a given L1 queue of the CPU port 4184 * Note: Only child @ L1 level is supported. 4185 * Because only L1 level queues can be attached to different parent (L0.0-L0.9) 4186 * of the CPU port. 4187 */ 4188 int 4189 soc_th3_cosq_cpu_parent_get(int unit, int child_index, int child_level, 4190 int *parent_index) 4191 { 4192 soc_reg_t reg = MMU_QSCH_CPU_L1_TO_L0_MAPPINGr; 4193 uint32 rval = 0; 4194 4195 if (child_level != SOC_TH3_NODE_LVL_L1) { 4196 /* Only child at L1 are allowed to move */ 4197 return SOC_E_PARAM; 4198 } 4199 /* Set the L1 queue's parent to the given L0 node */ 4200 SOC_IF_ERROR_RETURN 4201 (soc_reg32_get(unit, reg, 0, child_index, &rval)); 4202 *parent_index = soc_reg_field_get(unit, reg, rval, SELECTf); 4203 4204 return SOC_E_NONE; 4205 } 4206 4207 /* 4208 * Function to Get Parent(L0) for a given L1 queue of any FP port 4209 * Note: Only child @ L1 level is supported. 4210 * Because only L1 level queues can be attached to different parent (L0.0-L0.11) 4211 * of the FP port. 4212 */ 4213 int 4214 soc_th3_cosq_parent_get(int unit, int port, int child_index, int child_level, 4215 int *parent_index) 4216 { 4217 soc_reg_t reg = MMU_QSCH_PORT_CONFIGr; 4218 uint64 rval_64; 4219 uint32 mapping = 0; 4220 soc_reg_t prof_reg = MMU_MTRO_MMUQ_SCHQ_CFGr; 4221 soc_reg_t map_reg = MMU_MTRO_MMUQ_SCHQ_PROFILEr; 4222 int port_profile = 0; 4223 uint32 rval; 4224 soc_field_t schedq_field[12] = { 4225 SCH_Q_NUM_0f, SCH_Q_NUM_1f, 4226 SCH_Q_NUM_2f, SCH_Q_NUM_3f, 4227 SCH_Q_NUM_4f, SCH_Q_NUM_5f, 4228 SCH_Q_NUM_6f, SCH_Q_NUM_7f, 4229 SCH_Q_NUM_8f, SCH_Q_NUM_9f, 4230 SCH_Q_NUM_10f, SCH_Q_NUM_11f, 4231 }; 4232 4233 4234 if (child_level == SOC_TH3_NODE_LVL_L1) { 4235 /* Set the L1 queue's parent to the given L0 node */ 4236 SOC_IF_ERROR_RETURN 4237 (soc_reg64_get(unit, reg, 0, port, &rval_64)); 4238 mapping = soc_reg64_field32_get(unit, reg, rval_64, L1_TO_L0_MAPPINGf); 4239 4240 if ((mapping & (1 << child_index)) == 0) { 4241 *parent_index = child_index; 4242 } else { 4243 *parent_index = child_index+1; 4244 } 4245 } else if (child_level == SOC_TH3_NODE_LVL_L2) { 4246 /* Retrieve schedq mapped to MMUQ*/ 4247 rval = 0; 4248 SOC_IF_ERROR_RETURN 4249 (soc_reg32_get(unit, prof_reg, port, 0, &rval)); 4250 port_profile = soc_reg_field_get(unit, prof_reg, rval, Q_PROFILE_SELf); 4251 SOC_IF_ERROR_RETURN 4252 (soc_reg64_get(unit, map_reg, REG_PORT_ANY, port_profile, &rval_64)); 4253 *parent_index = soc_reg64_field32_get(unit, map_reg, rval_64, 4254 schedq_field[child_index]); 4255 4256 } else { 4257 return SOC_E_PARAM; 4258 } 4259 4260 return SOC_E_NONE; 4261 } 4262 4263 int 4264 soc_th3_sched_weight_get(int unit, int port, int level, 4265 int index, int *weight, int mc) 4266 { 4267 soc_info_t *si; 4268 soc_mem_t mem = INVALIDm; 4269 uint32 entry[SOC_MAX_MEM_WORDS]; 4270 int pipe, local_mmu_port; 4271 4272 si = &SOC_INFO(unit); 4273 4274 pipe = si->port_pipe[port]; 4275 local_mmu_port = SOC_TH3_MMU_LOCAL_PORT(unit, port); 4276 4277 if (level == SOC_TH3_NODE_LVL_L0) { 4278 mem = MMU_QSCH_L0_WEIGHT_MEMm; 4279 } else if (level == SOC_TH3_NODE_LVL_L1) { 4280 mem = MMU_QSCH_L1_WEIGHT_MEMm; 4281 } else { 4282 return SOC_E_PARAM; 4283 } 4284 4285 if (IS_CPU_PORT(unit, port)) { 4286 index = TH3_MMU_CPU_MCQ_OFFSET + index; 4287 } else if (IS_LB_PORT(unit, port)) { 4288 index = TH3_MMU_LB_MCQ_OFFSET + index; 4289 } else if (SOC_PBMP_MEMBER(si->management_pbm, port)) { 4290 index = TH3_MMU_MGMT_Q_OFFSET + index; 4291 } else { 4292 index = (local_mmu_port * SOC_TH3_NUM_GP_QUEUES) + index; 4293 } 4294 4295 mem = SOC_MEM_UNIQUE_ACC(unit, mem)[pipe]; 4296 SOC_IF_ERROR_RETURN 4297 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, index, &entry)); 4298 *weight = soc_mem_field32_get(unit, mem, &entry, WEIGHTf); 4299 4300 return SOC_E_NONE; 4301 } 4302 4303 int 4304 soc_th3_cosq_sched_mode_get(int unit, soc_port_t port, int level, int index, 4305 soc_th3_sched_mode_e* mode, int* weight, int mc) 4306 { 4307 soc_reg_t reg = INVALIDr; 4308 uint32 wrr_mask; 4309 uint64 rval; 4310 soc_field_t reg_field = INVALIDf; 4311 LOG_INFO(BSL_LS_SOC_COSQ, 4312 (BSL_META_U(unit, 4313 "START: soc_th3_cosq_sched_mode_get Port:%d Level:%d index=%d\n"), 4314 port, level, index)); 4315 4316 /* selection between SP and WxRR is based on weight property. */ 4317 SOC_IF_ERROR_RETURN(soc_th3_sched_weight_get(unit, port, 4318 level, index, weight, mc)); 4319 4320 if (IS_CPU_PORT(unit, port)) { 4321 reg = MMU_QSCH_CPU_PORT_CONFIGr; 4322 } else { 4323 reg = MMU_QSCH_PORT_CONFIGr; 4324 } 4325 if (level == SOC_TH3_NODE_LVL_L1) { 4326 if (IS_CPU_PORT(unit, port)) { 4327 reg_field = SP_L1f; 4328 } else { 4329 reg_field = SP_L0_PARENTf; 4330 } 4331 if (IS_CPU_PORT(unit, port)) { 4332 int parent_index = 0; 4333 SOC_IF_ERROR_RETURN 4334 (soc_th3_cosq_cpu_parent_get(unit, index, SOC_TH3_NODE_LVL_L1, 4335 &parent_index)); 4336 index = parent_index; 4337 } else { 4338 int parent_index = 0; 4339 SOC_IF_ERROR_RETURN 4340 (soc_th3_cosq_parent_get(unit, port, index, SOC_TH3_NODE_LVL_L1, 4341 &parent_index)); 4342 index = parent_index; 4343 } 4344 } else if (level == SOC_TH3_NODE_LVL_L0) { 4345 if (IS_CPU_PORT(unit, port)) { 4346 reg_field = SP_L0f; 4347 } else { 4348 reg_field = SP_L0_CHILDf; 4349 } 4350 } else { 4351 return SOC_E_PARAM; 4352 } 4353 4354 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval)); 4355 wrr_mask = soc_reg64_field32_get(unit, reg, rval, reg_field); 4356 if (wrr_mask & (1 << index)) { 4357 *mode = SOC_TH3_SCHED_MODE_STRICT; 4358 } else { 4359 wrr_mask = soc_reg64_field32_get(unit, reg, rval, ENABLE_WRRf); 4360 if (wrr_mask) { 4361 *mode = SOC_TH3_SCHED_MODE_WRR; 4362 } else { 4363 *mode = SOC_TH3_SCHED_MODE_WERR; 4364 } 4365 4366 } 4367 LOG_INFO(BSL_LS_SOC_COSQ, 4368 (BSL_META_U(unit, 4369 "END: soc_th3_cosq_sched_mode_get Port:%d Level:%d index=%d MODE=%d WT=%d\n"), 4370 port, level, index, *mode, *weight)); 4371 4372 return SOC_E_NONE; 4373 } 4374 4375 int 4376 soc_th3_cosq_sched_mode_set(int unit, soc_port_t port, int level, int index, 4377 soc_th3_sched_mode_e mode, int weight, int mc) 4378 { 4379 soc_reg_t reg = INVALIDr; 4380 uint32 wrr_mask; 4381 uint64 rval; 4382 soc_field_t reg_field = INVALIDf; 4383 4384 LOG_INFO(BSL_LS_SOC_COSQ, 4385 (BSL_META_U(unit, 4386 "START: soc_th3_cosq_sched_mode_set Port:%d Level:%d index=%d MODE=%d WT=%d\n"), 4387 port, level, index, mode, weight)); 4388 4389 /* selection between SP and WxRR is based on weight property. */ 4390 SOC_IF_ERROR_RETURN(soc_th3_sched_weight_set(unit, port, 4391 level, index, weight, mc)); 4392 4393 if (IS_CPU_PORT(unit, port)) { 4394 reg = MMU_QSCH_CPU_PORT_CONFIGr; 4395 } else { 4396 reg = MMU_QSCH_PORT_CONFIGr; 4397 } 4398 4399 if (level == SOC_TH3_NODE_LVL_L0) { 4400 if (IS_CPU_PORT(unit, port)) { 4401 reg_field = SP_L0f; 4402 } else { 4403 reg_field = SP_L0_CHILDf; 4404 } 4405 /* index = 0; */ 4406 } else if (level == SOC_TH3_NODE_LVL_L1) { 4407 if (IS_CPU_PORT(unit, port)) { 4408 reg_field = SP_L1f; 4409 } else { 4410 reg_field = SP_L0_PARENTf; 4411 } 4412 if (IS_CPU_PORT(unit, port)) { 4413 int parent_index = 0; 4414 reg = MMU_QSCH_CPU_PORT_CONFIGr; 4415 SOC_IF_ERROR_RETURN 4416 (soc_th3_cosq_cpu_parent_get(unit, index, SOC_TH3_NODE_LVL_L1, 4417 &parent_index)); 4418 index = parent_index; 4419 } else { 4420 int parent_index = 0; 4421 reg = MMU_QSCH_PORT_CONFIGr; 4422 SOC_IF_ERROR_RETURN 4423 (soc_th3_cosq_parent_get(unit, port, index, SOC_TH3_NODE_LVL_L1, 4424 &parent_index)); 4425 index = parent_index; 4426 } 4427 } else { 4428 return SOC_E_PARAM; 4429 } 4430 4431 LOG_INFO(BSL_LS_SOC_COSQ, 4432 (BSL_META_U(unit, 4433 "END: soc_th3_cosq_sched_mode_set Port:%d Level:%d index=%d MODE=%d WT=%d\n"), 4434 port, level, index, mode, weight)); 4435 4436 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, port, 0, &rval)); 4437 if (mode == SOC_TH3_SCHED_MODE_WRR) { 4438 soc_reg64_field32_set(unit, reg, &rval, ENABLE_WRRf, 1); 4439 wrr_mask = soc_reg64_field32_get(unit, reg, rval, reg_field); 4440 wrr_mask &= ~(1 << index); 4441 soc_reg64_field32_set(unit, reg, &rval, reg_field, wrr_mask); 4442 } else if (mode == SOC_TH3_SCHED_MODE_WERR) { 4443 soc_reg64_field32_set(unit, reg, &rval, ENABLE_WRRf, 0); 4444 wrr_mask = soc_reg64_field32_get(unit, reg, rval, reg_field); 4445 wrr_mask &= ~(1 << index); 4446 soc_reg64_field32_set(unit, reg, &rval, reg_field, wrr_mask); 4447 } else { 4448 wrr_mask = soc_reg64_field32_get(unit, reg, rval, reg_field); 4449 wrr_mask |= (1 << index); 4450 soc_reg64_field32_set(unit, reg, &rval, reg_field, wrr_mask); 4451 } 4452 4453 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, reg, port, 0, rval)); 4454 4455 /* WAR: set port 32 besides CPU reg, 4456 as CPU WRED takes some info from port 32. 4457 if (reg2 != INVALIDr) { 4458 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg2, port, 0, &rval)); 4459 wrr_mask = soc_reg_field_get(unit, reg2, rval, ENABLE_WRRf); 4460 wrr_mask &= ~(1 << index); 4461 wrr_mask |= (fval << index); 4462 soc_reg64_field32_set(unit, reg2, &rval, ENABLE_WRRf, wrr_mask); 4463 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, reg2, port, 0, rval)); 4464 } 4465 Note: Do not need this workaround in TH3? */ 4466 4467 return SOC_E_NONE; 4468 } 4469 4470 4471 /* 4472 *Function: soc_tomahawk3_scb_init 4473 *Purpose: Wrapper for init code 4474 */ 4475 int 4476 soc_tomahawk3_scb_init(int unit) 4477 { 4478 soc_reg_t reg; 4479 uint32 rval; 4480 uint16 dev_id; 4481 uint8 rev_id; 4482 4483 soc_cm_get_id(unit, &dev_id, &rev_id); 4484 4485 /* SDK-130693: Special configuration needed for ports with 4486 port speed below 100G in SCB */ 4487 reg = MMU_SCB_ARBITER_AGER_CFGr; 4488 SOC_IF_ERROR_RETURN 4489 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 4490 soc_reg_field_set(unit, reg, &rval, AGER_LIMIT_50f, 0); 4491 SOC_IF_ERROR_RETURN 4492 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 4493 4494 if (rev_id != BCM56980_A0_REV_ID) { 4495 reg = MMU_SCB_SRAF_FIFO_THRESHr; 4496 SOC_IF_ERROR_RETURN 4497 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 4498 soc_reg_field_set(unit, reg, &rval, THRESHf, 12); 4499 SOC_IF_ERROR_RETURN 4500 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 4501 } 4502 return SOC_E_NONE; 4503 } 4504 4505 /* 4506 *Function: soc_tomahawk3_wred_init 4507 *Purpose: Wrapper for init code 4508 */ 4509 int 4510 soc_tomahawk3_wred_init(int unit) 4511 { 4512 soc_reg_t reg; 4513 uint64 rval; 4514 4515 /* initiate Queue length update from both THDO simultaneously */ 4516 reg = MMU_WRED_CONFIG_READYr; 4517 SOC_IF_ERROR_RETURN 4518 (soc_reg64_get(unit, reg, REG_PORT_ANY, 0, &rval)); 4519 soc_reg64_field32_set(unit, reg, &rval, WRED_READYf, 1); 4520 SOC_IF_ERROR_RETURN 4521 (soc_reg64_set(unit, reg, REG_PORT_ANY, 0, rval)); 4522 4523 return SOC_E_NONE; 4524 } 4525 4526 /* 4527 *Function: soc_tomahawk3_rl_init 4528 *Purpose: Wrapper for init code 4529 */ 4530 int 4531 soc_tomahawk3_rl_init(int unit) 4532 { 4533 uint32 rval; 4534 4535 /* SDK-141834 SWAR to change MMU_RL_CONFIG value */ 4536 SOC_IF_ERROR_RETURN 4537 (soc_reg32_get(unit, MMU_RL_CONFIGr, REG_PORT_ANY, 0, &rval)); 4538 soc_reg_field_set(unit, MMU_RL_CONFIGr, &rval, ITREORDER_LIMITf, 511); 4539 SOC_IF_ERROR_RETURN 4540 (soc_reg32_set(unit, MMU_RL_CONFIGr, REG_PORT_ANY, 0, rval)); 4541 4542 return SOC_E_NONE; 4543 } 4544 4545 /* 4546 * Function: soc_tomahawk3_get_cos_for_mmu_queue 4547 * Purpose: Helper function that returns the cos value for an mmuq 4548 */ 4549 4550 int soc_tomahawk3_get_cos_for_mmu_queue(int unit, int profile, int mmuq) 4551 { 4552 int queue_num; 4553 int cos = -1; 4554 4555 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 4556 if (th3_sched_profile_info[unit][profile][queue_num].mmuq[0] == mmuq) { 4557 cos = th3_sched_profile_info[unit][profile][queue_num].cos; 4558 break; 4559 } 4560 if (th3_sched_profile_info[unit][profile][queue_num].mmuq[1] == mmuq) { 4561 cos = th3_sched_profile_info[unit][profile][queue_num].cos; 4562 break; 4563 } 4564 } 4565 return cos; 4566 4567 } 4568 4569 /* 4570 * Function: soc_tomahawk3_get_fc_only_uc_for_cos 4571 * Purpose: 4572 * Helper function that returns the fc_only_uc for a given {profile, cos} 4573 */ 4574 4575 int 4576 soc_tomahawk3_get_fc_only_uc_for_cos(int unit, int profile, int cos) 4577 { 4578 int queue_num; 4579 int fc_only_uc = 0; 4580 4581 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 4582 if (th3_sched_profile_info[unit][profile][queue_num].cos == cos) { 4583 fc_only_uc = 4584 th3_sched_profile_info[unit][profile][queue_num].fc_is_uc_only; 4585 break; 4586 } 4587 } 4588 return fc_only_uc; 4589 4590 } 4591 4592 /* 4593 * Function: soc_tomahawk3_get_sp_for_cos 4594 * Purpose: 4595 * Helper function that returns the strict priority for a given {profile, cos} 4596 */ 4597 4598 int 4599 soc_tomahawk3_get_sp_for_cos(int unit, int profile, int cos) 4600 { 4601 int queue_num; 4602 int sp = 0; 4603 4604 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 4605 if (th3_sched_profile_info[unit][profile][queue_num].cos == cos) { 4606 sp = 4607 th3_sched_profile_info[unit][profile][queue_num].strict_priority; 4608 break; 4609 } 4610 } 4611 return sp; 4612 4613 } 4614 4615 int soc_tomahawk3_profile_exists(int unit, int profile) 4616 { 4617 int profile_exists = 0; 4618 int queue_num; 4619 4620 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 4621 if (th3_sched_profile_info[unit][profile][queue_num].cos != -1) { 4622 profile_exists = 1; 4623 break; 4624 } 4625 } 4626 return profile_exists; 4627 } 4628 4629 int 4630 soc_tomahawk3_get_sched_profile_max_cos(int unit, int profile) { 4631 int max_cos = 0; 4632 int queue_num, cos; 4633 4634 for (queue_num = 0; queue_num < SOC_TH3_NUM_GP_QUEUES; queue_num++) { 4635 cos = th3_sched_profile_info[unit][profile][queue_num].cos; 4636 if (cos > max_cos) { 4637 max_cos = cos; 4638 } 4639 } 4640 return max_cos; 4641 } 4642 4643 STATIC int 4644 soc_transmit_rqe_flush_packet (int unit, int rqe_num) { 4645 bcm_pkt_t *pkt = NULL; 4646 uint8 *payload; 4647 int rv = SOC_E_NONE; 4648 bcm_port_t dest_port = _TH3_MMU_SPARE_DST_PORT; /* Use spare port as destination */ 4649 4650 /* Create test packet */ 4651 pkt = soc_cm_salloc(unit, sizeof(bcm_pkt_t), "pkt buffer"); 4652 if (pkt == NULL) { 4653 return SOC_E_MEMORY; 4654 } 4655 payload = soc_cm_salloc(unit, 68, 4656 "pkt alloc data"); 4657 if (payload == NULL) { 4658 soc_cm_sfree(unit, pkt); 4659 return BCM_E_FAIL; 4660 } 4661 sal_memset(payload, 1, 68); 4662 BCM_PKT_ONE_BUF_SETUP(pkt, payload, 68); 4663 4664 pkt->flags = BCM_TX_LINKDOWN_TRANSMIT; 4665 pkt->flags2 = BCM_PKT_F2_MC_QUEUE; 4666 pkt->flags |= BCM_PKT_F_ROUTED; 4667 pkt->flags |= BCM_TX_PRIO_INT; 4668 pkt->unit = unit; 4669 pkt->call_back = NULL; 4670 BCM_PKT_TX_LEN_SET(pkt, 68); 4671 pkt->vlan = 1; 4672 pkt->prio_int = rqe_num; 4673 pkt->cos = 0; 4674 pkt->rqe_q_num = rqe_num; 4675 SOC_PBMP_CLEAR(pkt->tx_l3pbmp); 4676 SOC_PBMP_CLEAR(pkt->tx_pbmp); 4677 SOC_PBMP_PORT_ADD(pkt->tx_l3pbmp, dest_port); 4678 SOC_PBMP_PORT_ADD(pkt->tx_pbmp, dest_port); 4679 pkt->dest_port = dest_port; 4680 pkt->dst_gport = dest_port; 4681 4682 /* LB HDR fields for SOBMH packet*/ 4683 pkt->flags2 |= BCM_PKT_F2_CPU_TX_PROC; 4684 pkt->rx_port = _TH3_MMU_SPARE_SRC_PORT; /* Spare port from ITM1*/ 4685 pkt->txprocmh_destination_type = 15; 4686 pkt->txprocmh_destination = dest_port; 4687 pkt->txprocmh_qos_fields_valid = 1; 4688 4689 pkt->pkt_data[0].data[12] = 0x81; 4690 pkt->pkt_data[0].data[13] = 0x00; 4691 pkt->pkt_data[0].data[14] = 0x00; 4692 pkt->pkt_data[0].data[15] = 0x01; 4693 4694 rv = bcm_common_tx(unit, pkt, NULL); 4695 4696 if (payload != NULL) { 4697 soc_cm_sfree(unit, payload); 4698 } 4699 if (pkt != NULL) { 4700 soc_cm_sfree(unit, pkt); 4701 } 4702 4703 return rv; 4704 } 4705 4706 int 4707 soc_tomahawk3_cpu_tx_rqe_queues_for_flush (int unit, int itm) { 4708 int num_rqe_queues; 4709 int rqe_q, i; 4710 int num_packets = 7; /*Transmit 7 packets fro each queue*/ 4711 uint16 dev_id; 4712 uint8 rev_id; 4713 int rv = SOC_E_NONE; 4714 uint32 rd_val, rval, wr_val; 4715 soc_reg_t reg_int_stat = MMU_RQE_INT_STATr; 4716 soc_reg_t reg_int_en = MMU_RQE_INT_ENr; 4717 int invld_dest_en = 0; 4718 int itm_int; 4719 soc_info_t *si = &SOC_INFO(unit); 4720 uint32 itm_map = si->itm_map; 4721 int count = 0; 4722 bcm_pbmp_t link_bmap; 4723 uint32 entry[SOC_MAX_MEM_FIELD_WORDS]; 4724 4725 /* Disable RQE_INVALID_DEST interrupt */ 4726 SOC_IF_ERROR_RETURN( 4727 soc_reg32_rawport_get(unit, reg_int_en, REG_PORT_ANY, 0, &rval)); 4728 invld_dest_en = soc_reg_field_get(unit, reg_int_en, rval, INVALID_DESTf); 4729 wr_val = 0; 4730 soc_reg_field_set(unit, reg_int_en, &rval, INVALID_DESTf, wr_val); 4731 SOC_IF_ERROR_RETURN( 4732 soc_reg32_rawport_set(unit, reg_int_en, REG_PORT_ANY, 0, rval)); 4733 4734 /* Add Spare ports 158 & 98 to IP's EPC_LINK_BMAP */ 4735 soc_mem_lock(unit, EPC_LINK_BMAPm); 4736 rv = soc_mem_read(unit, EPC_LINK_BMAPm, MEM_BLOCK_ANY, 0, entry); 4737 if (rv != SOC_E_NONE) { 4738 soc_mem_unlock(unit, EPC_LINK_BMAPm); 4739 return SOC_E_INTERNAL; 4740 } 4741 soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 4742 &link_bmap); 4743 SOC_PBMP_PORT_ADD(link_bmap, _TH3_MMU_SPARE_DST_PORT); 4744 SOC_PBMP_PORT_ADD(link_bmap, _TH3_MMU_SPARE_SRC_PORT); 4745 soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 4746 &link_bmap); 4747 rv = soc_mem_write(unit, EPC_LINK_BMAPm, MEM_BLOCK_ALL, 0, &entry); 4748 soc_mem_unlock(unit, EPC_LINK_BMAPm); 4749 if (rv != SOC_E_NONE) { 4750 return SOC_E_INTERNAL; 4751 } 4752 4753 /* Add Spare ports 158 & 98 to IP's ING_DEST_PORT_ENABLE */ 4754 soc_mem_lock(unit, ING_DEST_PORT_ENABLEm); 4755 rv = soc_mem_read(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ANY, 4756 0, entry); 4757 if (rv != SOC_E_NONE) { 4758 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 4759 return SOC_E_INTERNAL; 4760 } 4761 soc_mem_pbmp_field_get(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 4762 &link_bmap); 4763 BCM_PBMP_PORT_ADD(link_bmap, _TH3_MMU_SPARE_DST_PORT); 4764 BCM_PBMP_PORT_ADD(link_bmap, _TH3_MMU_SPARE_SRC_PORT); 4765 soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 4766 &link_bmap); 4767 rv = soc_mem_write(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ALL, 0, 4768 &entry); 4769 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 4770 if (rv != SOC_E_NONE) { 4771 return SOC_E_INTERNAL; 4772 } 4773 4774 /* Transmit 7 packets to each RQE queue in use */ 4775 soc_cm_get_id(unit, &dev_id, &rev_id); 4776 if (rev_id == BCM56980_A0_REV_ID) { 4777 num_rqe_queues = _TH3_A0_MMU_NUM_RQE_QUEUES; 4778 } else { 4779 num_rqe_queues = _TH3_MMU_NUM_RQE_QUEUES; 4780 } 4781 for (rqe_q = 0; rqe_q < num_rqe_queues; rqe_q++) { 4782 for (i = 0; i < num_packets; i++) { 4783 SOC_IF_ERROR_RETURN( 4784 soc_transmit_rqe_flush_packet(unit, rqe_q)); 4785 } 4786 } 4787 4788 /* Wait for MMU_RQE_INT_STAT.FLUSH_DONE interrupt to be set */ 4789 while (1) { 4790 SOC_IF_ERROR_RETURN(soc_reg32_rawport_get(unit, reg_int_stat, 4791 itm, 0, &rval)); 4792 rd_val = soc_reg_field_get(unit, reg_int_stat, 4793 rval, FLUSH_DONEf); 4794 if (rd_val == 1) { 4795 break; 4796 } 4797 sal_usleep(1 + (SAL_BOOT_QUICKTURN ? 1 : 0) * EMULATION_FACTOR); 4798 count++; 4799 if (count > 30000) { 4800 LOG_ERROR(BSL_LS_SOC_COMMON, 4801 (BSL_META_U(unit, 4802 "RQE Port Flush : FLUSH_DONE isn't reset even after 30000 " 4803 "iterations\n"))); 4804 return SOC_E_FAIL; 4805 } 4806 } 4807 /* Clear RQE INVALID_DEST INT STAT*/ 4808 wr_val = 1; /*w1tc*/ 4809 for (itm_int = 0; itm_int < NUM_ITM(unit); itm_int++) { 4810 if (itm_map & (1 << itm_int)) { 4811 rval = 0; 4812 soc_reg_field_set(unit, reg_int_stat, &rval, INVALID_DESTf, wr_val); 4813 SOC_IF_ERROR_RETURN( 4814 soc_reg32_rawport_set(unit, reg_int_stat, itm_int, 0, rval)); 4815 } 4816 } 4817 4818 /* Restore RQE INVALID_DEST INT_EN */ 4819 SOC_IF_ERROR_RETURN( 4820 soc_reg32_rawport_get(unit, reg_int_en, REG_PORT_ANY, 0, &rval)); 4821 wr_val = invld_dest_en; 4822 soc_reg_field_set(unit, reg_int_en, &rval, INVALID_DESTf, wr_val); 4823 SOC_IF_ERROR_RETURN( 4824 soc_reg32_rawport_set(unit, reg_int_en, REG_PORT_ANY, 0, rval)); 4825 4826 /* Remove Spare ports 158 & 98 from IP's EPC_LINK_BMAP */ 4827 soc_mem_lock(unit, EPC_LINK_BMAPm); 4828 rv = soc_mem_read(unit, EPC_LINK_BMAPm, MEM_BLOCK_ANY, 0, entry); 4829 if (rv != SOC_E_NONE) { 4830 soc_mem_unlock(unit, EPC_LINK_BMAPm); 4831 return SOC_E_INTERNAL; 4832 } 4833 soc_mem_pbmp_field_get(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 4834 &link_bmap); 4835 BCM_PBMP_PORT_REMOVE(link_bmap, _TH3_MMU_SPARE_DST_PORT); 4836 BCM_PBMP_PORT_REMOVE(link_bmap, _TH3_MMU_SPARE_SRC_PORT); 4837 soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 4838 &link_bmap); 4839 rv = soc_mem_write(unit, EPC_LINK_BMAPm, MEM_BLOCK_ALL, 0, 4840 &entry); 4841 soc_mem_unlock(unit, EPC_LINK_BMAPm); 4842 if (rv != SOC_E_NONE) { 4843 return SOC_E_INTERNAL; 4844 } 4845 4846 /* Remove Spare ports 158 & 98 from IP's ING_DEST_PORT_ENABLE */ 4847 soc_mem_lock(unit, ING_DEST_PORT_ENABLEm); 4848 rv = soc_mem_read(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ANY, 4849 0, entry); 4850 if (rv != SOC_E_NONE) { 4851 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 4852 return SOC_E_INTERNAL; 4853 } 4854 soc_mem_pbmp_field_get(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 4855 &link_bmap); 4856 BCM_PBMP_PORT_REMOVE(link_bmap, _TH3_MMU_SPARE_DST_PORT); 4857 BCM_PBMP_PORT_REMOVE(link_bmap, _TH3_MMU_SPARE_SRC_PORT); 4858 soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, entry, PORT_BITMAPf, 4859 &link_bmap); 4860 rv = soc_mem_write(unit, ING_DEST_PORT_ENABLEm, MEM_BLOCK_ALL, 0, 4861 &entry); 4862 soc_mem_unlock(unit, ING_DEST_PORT_ENABLEm); 4863 if (rv != SOC_E_NONE) { 4864 return SOC_E_INTERNAL; 4865 } 4866 4867 return SOC_E_NONE; 4868 } 4869 4870 int 4871 soc_th3_mmu_enable_non_func_intr(int unit) { 4872 int i; 4873 soc_reg_t loop_reg; 4874 soc_field_t loop_field; 4875 uint32 rval; 4876 struct { 4877 soc_reg_t int_reg; 4878 soc_field_t int_en_field; 4879 } int_rf_list[] = { 4880 {MMU_MTRO_CPU_INT_ENr, CNT_OVERFLOWf}, 4881 {MMU_THDI_CPU_INT_ENr, POOL_COUNTER_OVERFLOWf}, 4882 {MMU_THDI_CPU_INT_ENr, POOL_COUNTER_UNDERFLOWf}, 4883 {MMU_THDO_CPU_INT_ENr, COUNTER_UNDERFLOWf}, 4884 {MMU_THDO_CPU_INT_ENr, SPID_MISMATCHf}, 4885 {MMU_THDR_QE_CPU_INT_ENr, CNT_OVERFLOWf}, 4886 {MMU_THDR_QE_CPU_INT_ENr, CNT_UNDERFLOWf}, 4887 {MMU_EBCTM_CPU_INT_ENr, OVERFLOW_INTR_ENf}, 4888 {MMU_EBCTM_CPU_INT_ENr, UNDERFLOW_INTR_ENf}, 4889 {MMU_EBCFP_CPU_INT_ENr, EB_MISCONFIGUREDf}, 4890 {MMU_EBCFP_CPU_INT_ENr, MTU_VIOLATIONf}, 4891 {MMU_CRB_CPU_INT_ENr, MTU_VIOLATION_INTR_ENf}, 4892 {MMU_CRB_CPU_INT_ENr, INV_SRC_PORT_INTR_ENf}, 4893 {MMU_CRB_CPU_INT_ENr, INV_DST_PORT_INTR_ENf}, 4894 {MMU_RQE_INT_ENr, INVALID_DESTf}, 4895 {MMU_RQE_INT_ENr, CCP_OVERFLOWf}, 4896 {MMU_RQE_INT_ENr, L3_PURGEf}, 4897 {INVALIDr, INVALIDf} 4898 }; 4899 soc_reg_t itm_int_reg = MMU_ITMCFG_CPU_INT_ENr; 4900 soc_reg_t eb_int_reg = MMU_EBCFG_CPU_INT_ENr; 4901 soc_field_t itm_intr_fields[6] = {THDR_INT_ENf, THDO_INT_ENf, THDI_INT_ENf, 4902 RQE_INT_ENf, CRB_INT_ENf, CFAP_INT_ENf}; 4903 soc_field_t eb_intr_fields[3] = {MTRO_INT_ENf, EBCTM_INT_ENf, EBCFP_INT_ENf}; 4904 4905 /* Set Leaf block level interrupt enables*/ 4906 for (i = 0; int_rf_list[i].int_reg != INVALIDr; i++) { 4907 if (!SOC_REG_IS_VALID(unit, int_rf_list[i].int_reg)) { 4908 continue; 4909 } 4910 loop_reg = int_rf_list[i].int_reg; 4911 loop_field = int_rf_list[i].int_en_field; 4912 SOC_IF_ERROR_RETURN 4913 (soc_reg32_get(unit, loop_reg, REG_PORT_ANY, 0, &rval)); 4914 soc_reg_field_set(unit, loop_reg, &rval, loop_field, 1); 4915 SOC_IF_ERROR_RETURN 4916 (soc_reg32_set(unit, loop_reg, REG_PORT_ANY, 0, rval)); 4917 } 4918 4919 /* Set ITM level interrupt enables */ 4920 for (i = 0; i < (sizeof(itm_intr_fields)) / (sizeof(soc_field_t)); i++) { 4921 rval = 0; 4922 SOC_IF_ERROR_RETURN 4923 (soc_reg32_get(unit, itm_int_reg, REG_PORT_ANY, 0, &rval)); 4924 soc_reg_field_set(unit, itm_int_reg, &rval, itm_intr_fields[i], 1); 4925 SOC_IF_ERROR_RETURN 4926 (soc_reg32_set(unit, itm_int_reg, REG_PORT_ANY, 0, rval)); 4927 } 4928 /* Set EB level interrupt enables */ 4929 for (i = 0; i < (sizeof(eb_intr_fields)) / (sizeof(soc_field_t)); i++) { 4930 rval = 0; 4931 SOC_IF_ERROR_RETURN 4932 (soc_reg32_get(unit, eb_int_reg, REG_PORT_ANY, 0, &rval)); 4933 soc_reg_field_set(unit, eb_int_reg, &rval, eb_intr_fields[i], 1); 4934 SOC_IF_ERROR_RETURN 4935 (soc_reg32_set(unit, eb_int_reg, REG_PORT_ANY, 0, rval)); 4936 } 4937 /* All GLB interrupts required are enabled as part of SER init */ 4938 return SOC_E_NONE; 4939 } 4940 4941 STATIC int 4942 soc_th3_clear_itm_int_stat (int unit, int itm, soc_field_t itm_intr_field) 4943 { 4944 uint32 rval = 0; 4945 soc_reg_t itm_intr_reg = MMU_ITMCFG_CPU_INT_STATr; 4946 soc_reg_t glb_intr_reg = MMU_GLBCFG_CPU_INT_STATr; 4947 soc_field_t glb_fields[] = {ITMCFG0_INT_STATf, ITMCFG1_INT_STATf}; 4948 int wr_val = 1; /* w1tc */ 4949 4950 /*Clear ITM level interrupt*/ 4951 rval = 0; 4952 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, itm_intr_reg, itm, 0, &rval)); 4953 soc_reg_field_set(unit, itm_intr_reg, &rval, itm_intr_field, wr_val); 4954 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, itm_intr_reg, itm, 0, rval)); 4955 /*Clear GLB level interrupt*/ 4956 rval = 0; 4957 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, glb_intr_reg, itm, 0, &rval)); 4958 soc_reg_field_set(unit, glb_intr_reg, &rval, glb_fields[itm], wr_val); 4959 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, glb_intr_reg, itm, 0, rval)); 4960 4961 return SOC_E_NONE; 4962 } 4963 4964 STATIC int 4965 soc_th3_clear_eb_int_stat (int unit, int pipe, soc_field_t eb_intr_field) 4966 { 4967 uint32 rval = 0; 4968 soc_reg_t eb_intr_reg = MMU_EBCFG_CPU_INT_STATr; 4969 soc_reg_t glb_intr_reg = MMU_GLBCFG_CPU_INT_STATr; 4970 soc_field_t glb_fields[] = {EBCFG0_INT_STATf, EBCFG1_INT_STATf, 4971 EBCFG2_INT_STATf, EBCFG3_INT_STATf, EBCFG4_INT_STATf, EBCFG5_INT_STATf, 4972 EBCFG6_INT_STATf, EBCFG7_INT_STATf}; 4973 int wr_val = 1; /* w1tc */ 4974 4975 /*Clear EB level interrupt*/ 4976 rval = 0; 4977 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, eb_intr_reg, pipe, 0, &rval)); 4978 soc_reg_field_set(unit, eb_intr_reg, &rval, eb_intr_field, wr_val); 4979 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, eb_intr_reg, pipe, 0, rval)); 4980 /*Clear GLB level interrupt*/ 4981 rval = 0; 4982 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, glb_intr_reg, pipe, 0, &rval)); 4983 soc_reg_field_set(unit, glb_intr_reg, &rval, glb_fields[pipe], wr_val); 4984 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, glb_intr_reg, pipe, 0, rval)); 4985 4986 return SOC_E_NONE; 4987 } 4988 4989 4990 4991 int 4992 soc_th3_process_itm_cfap_int (int unit, int itm, soc_field_t itm_intr_field) { 4993 soc_reg_t block_intr_reg = MMU_CFAP_INT_STATr; 4994 uint64 rval64; 4995 soc_field_t bst_int = BST_TRIG_STATf; 4996 int wr_val = 1; /* w1tc */ 4997 4998 COMPILER_64_ZERO(rval64); 4999 SOC_IF_ERROR_RETURN( 5000 soc_reg64_get(unit, block_intr_reg, itm, 0, &rval64)); 5001 if (soc_reg64_field32_get(unit, block_intr_reg, rval64, bst_int)) { 5002 LOG_VERBOSE(BSL_LS_SOC_COMMON, 5003 (BSL_META_U(unit, "Unit: %0d -- Servicing CFAP" 5004 "BST intr from ITM = %0d \n"), 5005 unit, itm)); 5006 /* Clear BST interrupt*/ 5007 soc_reg64_field32_set(unit, block_intr_reg, &rval64, bst_int, wr_val); 5008 SOC_IF_ERROR_RETURN( 5009 soc_reg64_set(unit, block_intr_reg, itm, 0, rval64)); 5010 /* Clear ITM and GLB level interrupts */ 5011 SOC_IF_ERROR_RETURN( 5012 soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field)); 5013 /* BST callback for stats processing */ 5014 SOC_IF_ERROR_RETURN 5015 (soc_th3_process_mmu_bst(unit, itm, itm_intr_field)); 5016 } 5017 return SOC_E_NONE; 5018 } 5019 5020 int 5021 soc_th3_process_itm_thdi_int (int unit, int itm, soc_field_t itm_intr_field) { 5022 soc_reg_t block_intr_reg = MMU_THDI_CPU_INT_STATr; 5023 uint32 rval = 0, intr_reg_val = 0; 5024 soc_field_t thdi_intr_fields[] = {POOL_COUNTER_UNDERFLOW_STATf, 5025 POOL_COUNTER_OVERFLOW_STATf}; 5026 soc_field_t bst_int = BST_TRIG_STATf; 5027 int wr_val = 1; /* w1tc */ 5028 int i; 5029 5030 SOC_IF_ERROR_RETURN( 5031 soc_reg32_get(unit, block_intr_reg, itm, 0, &intr_reg_val)); 5032 if (soc_reg_field_get(unit, block_intr_reg, intr_reg_val, bst_int)) { 5033 LOG_VERBOSE(BSL_LS_SOC_COMMON, 5034 (BSL_META_U(unit, "Unit: %0d -- Servicing THDI" 5035 "BST intr from ITM = %0d \n"), 5036 unit, itm)); 5037 /* Clear BST interrupt*/ 5038 SOC_IF_ERROR_RETURN( 5039 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5040 soc_reg_field_set(unit, block_intr_reg, &rval, bst_int, wr_val); 5041 SOC_IF_ERROR_RETURN( 5042 soc_reg32_set(unit, block_intr_reg, itm, 0, rval)); 5043 /* Clear ITM and GLB level interrupts */ 5044 SOC_IF_ERROR_RETURN( 5045 soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field)); 5046 /* BST callback for stats processing */ 5047 SOC_IF_ERROR_RETURN 5048 (soc_th3_process_mmu_bst(unit, itm, itm_intr_field)); 5049 } else { 5050 for (i = 0; i < (sizeof(thdi_intr_fields) / sizeof(soc_field_t)); i++) { 5051 SOC_IF_ERROR_RETURN( 5052 soc_reg32_get(unit, block_intr_reg, itm, 0, &intr_reg_val)); 5053 if (!soc_reg_field_get(unit, block_intr_reg, 5054 intr_reg_val, thdi_intr_fields[i])) { 5055 continue; 5056 } 5057 switch(thdi_intr_fields[i]) { 5058 case POOL_COUNTER_UNDERFLOWf: 5059 LOG_ERROR(BSL_LS_SOC_COMMON, 5060 (BSL_META_U(unit, "Unit: %0d -- THDI Pool Counter" 5061 "Underflow intr set for ITM = %0d \n"), 5062 unit, itm)); 5063 break; 5064 case POOL_COUNTER_OVERFLOWf: 5065 LOG_ERROR(BSL_LS_SOC_COMMON, 5066 (BSL_META_U(unit, "Unit: %0d -- THDI Pool Counter" 5067 "Overflow intr set for ITM = %0d \n"), 5068 unit, itm)); 5069 break; 5070 default: 5071 break; 5072 } 5073 /*Clear block(THDI) level interrupt*/ 5074 rval = 0; 5075 SOC_IF_ERROR_RETURN( 5076 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5077 soc_reg_field_set(unit, block_intr_reg, &rval, 5078 thdi_intr_fields[i], wr_val); 5079 SOC_IF_ERROR_RETURN( 5080 soc_reg32_set(unit, block_intr_reg, itm, 0, rval)); 5081 } 5082 /* Clear ITM and GLB level interrupts */ 5083 SOC_IF_ERROR_RETURN( 5084 soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field)); 5085 5086 } 5087 return SOC_E_NONE; 5088 } 5089 5090 int 5091 soc_th3_process_itm_thdo_int (int unit, int itm, soc_field_t itm_intr_field) { 5092 soc_reg_t block_intr_reg = MMU_THDO_CPU_INT_STATr; 5093 soc_reg_t thdo_bst_int_reg = MMU_THDO_BST_CPU_INT_STATr; 5094 uint32 rval = 0; 5095 soc_field_t thdo_intr_fields[] = {COUNTER_UNDERFLOWf, SPID_MISMATCHf}; 5096 soc_field_t bst_int = BSTf; 5097 int wr_val = 1; /* w1tc */ 5098 int i; 5099 5100 SOC_IF_ERROR_RETURN( 5101 soc_reg32_get(unit, thdo_bst_int_reg, itm, 0, &rval)); 5102 if (soc_reg_field_get(unit, thdo_bst_int_reg, rval, bst_int)) { 5103 LOG_VERBOSE(BSL_LS_SOC_COMMON, 5104 (BSL_META_U(unit, "Unit: %0d -- Servicing THDO" 5105 "BST intr from ITM = %0d \n"), 5106 unit, itm)); 5107 /* Clear BST interrupt*/ 5108 soc_reg_field_set(unit, thdo_bst_int_reg, &rval, bst_int, wr_val); 5109 SOC_IF_ERROR_RETURN( 5110 soc_reg32_set(unit, thdo_bst_int_reg, itm, 0, rval)); 5111 /* Clear ITM and GLB level interrupts */ 5112 SOC_IF_ERROR_RETURN( 5113 soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field)); 5114 /* BST callback for stats processing */ 5115 SOC_IF_ERROR_RETURN 5116 (soc_th3_process_mmu_bst(unit, itm, itm_intr_field)); 5117 } else { 5118 for (i = 0; i < (sizeof(thdo_intr_fields) / sizeof(soc_field_t)); i++) { 5119 SOC_IF_ERROR_RETURN( 5120 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5121 if (!soc_reg_field_get(unit, block_intr_reg, 5122 rval, thdo_intr_fields[i])) { 5123 continue; 5124 } 5125 switch(thdo_intr_fields[i]) { 5126 case SPID_MISMATCHf: 5127 LOG_ERROR(BSL_LS_SOC_COMMON, 5128 (BSL_META_U(unit, "Unit: %0d -- SPID Mismatch" 5129 "intr set for ITM = %0d \n"), 5130 unit, itm)); 5131 break; 5132 case COUNTER_UNDERFLOWf: 5133 LOG_ERROR(BSL_LS_SOC_COMMON, 5134 (BSL_META_U(unit, "Unit: %0d -- THDO Counter" 5135 " Underflow intr set for ITM = %0d \n"), 5136 unit, itm)); 5137 5138 break; 5139 default: 5140 break; 5141 } 5142 /*Clear block(THDO) level interrupt*/ 5143 rval = 0; 5144 SOC_IF_ERROR_RETURN( 5145 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5146 soc_reg_field_set(unit, block_intr_reg, &rval, 5147 thdo_intr_fields[i], wr_val); 5148 SOC_IF_ERROR_RETURN( 5149 soc_reg32_set(unit, block_intr_reg, itm, 0, rval)); 5150 } 5151 /* Clear ITM and GLB level interrupts */ 5152 SOC_IF_ERROR_RETURN( 5153 soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field)); 5154 } 5155 5156 return SOC_E_NONE; 5157 } 5158 5159 int 5160 soc_th3_process_itm_thdr_int (int unit, int itm, soc_field_t itm_intr_field) { 5161 soc_reg_t block_intr_reg = MMU_THDR_QE_CPU_INT_STATr; 5162 uint32 rval = 0; 5163 soc_field_t thdr_intr_fields[] = {CNT_UNDERFLOWf, CNT_OVERFLOWf}; 5164 soc_field_t bst_int = BSTf; 5165 int wr_val = 1; /* w1tc */ 5166 int i; 5167 5168 SOC_IF_ERROR_RETURN( 5169 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5170 if (soc_reg_field_get(unit, block_intr_reg, rval, bst_int)) { 5171 LOG_VERBOSE(BSL_LS_SOC_COMMON, 5172 (BSL_META_U(unit, "Unit: %0d -- Servicing THDR QE" 5173 "BST intr from ITM = %0d \n"), 5174 unit, itm)); 5175 /* Clear BST interrupt*/ 5176 soc_reg_field_set(unit, block_intr_reg, &rval, bst_int, wr_val); 5177 SOC_IF_ERROR_RETURN( 5178 soc_reg32_set(unit, block_intr_reg, itm, 0, rval)); 5179 /* Clear ITM and GLB level interrupts */ 5180 SOC_IF_ERROR_RETURN( 5181 soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field)); 5182 /* BST callback for stats processing */ 5183 SOC_IF_ERROR_RETURN 5184 (soc_th3_process_mmu_bst(unit, itm, itm_intr_field)); 5185 } else { 5186 for (i = 0; i < (sizeof(thdr_intr_fields) / sizeof(soc_field_t)); i++) { 5187 SOC_IF_ERROR_RETURN( 5188 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5189 if (!soc_reg_field_get(unit, block_intr_reg, 5190 rval, thdr_intr_fields[i])) { 5191 continue; 5192 } 5193 switch(thdr_intr_fields[i]) { 5194 case CNT_OVERFLOWf: 5195 LOG_ERROR(BSL_LS_SOC_COMMON, 5196 (BSL_META_U(unit, "Unit: %0d -- THDR QE Counter" 5197 " Overflow intr set for ITM = %0d \n"), 5198 unit, itm)); 5199 break; 5200 case CNT_UNDERFLOWf: 5201 LOG_ERROR(BSL_LS_SOC_COMMON, 5202 (BSL_META_U(unit, "Unit: %0d -- THDR QE Counter" 5203 " Underflow intr set for ITM = %0d \n"), 5204 unit, itm)); 5205 5206 break; 5207 default: 5208 break; 5209 } 5210 /*Clear block(THDR QE) level interrupt*/ 5211 rval = 0; 5212 SOC_IF_ERROR_RETURN( 5213 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5214 soc_reg_field_set(unit, block_intr_reg, &rval, 5215 thdr_intr_fields[i], wr_val); 5216 SOC_IF_ERROR_RETURN( 5217 soc_reg32_set(unit, block_intr_reg, itm, 0, rval)); 5218 } 5219 /* Clear ITM and GLB level interrupts */ 5220 SOC_IF_ERROR_RETURN( 5221 soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field)); 5222 } 5223 5224 return SOC_E_NONE; 5225 } 5226 5227 int 5228 soc_th3_process_itm_rqe_int (int unit, int itm, soc_field_t itm_intr_field) { 5229 soc_reg_t block_intr_reg = MMU_RQE_INT_STATr; 5230 uint32 rval = 0; 5231 soc_field_t thdr_intr_fields[] = {INVALID_DESTf, CCP_OVERFLOWf, L3_PURGEf}; 5232 int wr_val = 1; /* w1tc */ 5233 int i; 5234 5235 for (i = 0; i < (sizeof(thdr_intr_fields) / sizeof(soc_field_t)); i++) { 5236 SOC_IF_ERROR_RETURN( 5237 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5238 if (!soc_reg_field_get(unit, block_intr_reg, 5239 rval, thdr_intr_fields[i])) { 5240 continue; 5241 } 5242 switch(thdr_intr_fields[i]) { 5243 case CCP_OVERFLOWf: 5244 LOG_ERROR(BSL_LS_SOC_COMMON, 5245 (BSL_META_U(unit, "Unit: %0d -- Multicast copy count" 5246 " exceeded 1K intr set for ITM = %0d \n"), 5247 unit, itm)); 5248 break; 5249 case INVALID_DESTf: 5250 LOG_ERROR(BSL_LS_SOC_COMMON, 5251 (BSL_META_U(unit, "Unit: %0d -- Invalid destination port" 5252 " in L2/L3 bitmap intr set for ITM = %0d \n"), 5253 unit, itm)); 5254 5255 break; 5256 case L3_PURGEf: 5257 LOG_ERROR(BSL_LS_SOC_COMMON, 5258 (BSL_META_U(unit, "Unit: %0d -- Packet drop due to" 5259 " invalid multicast config intr set for ITM = %0d \n"), 5260 unit, itm)); 5261 5262 break; 5263 default: 5264 break; 5265 } 5266 /*Clear block(RQE) level interrupt*/ 5267 rval = 0; 5268 SOC_IF_ERROR_RETURN( 5269 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5270 soc_reg_field_set(unit, block_intr_reg, &rval, 5271 thdr_intr_fields[i], wr_val); 5272 SOC_IF_ERROR_RETURN( 5273 soc_reg32_set(unit, block_intr_reg, itm, 0, rval)); 5274 } 5275 /* Clear ITM and GLB level interrupts */ 5276 SOC_IF_ERROR_RETURN( 5277 soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field)); 5278 5279 return SOC_E_NONE; 5280 } 5281 5282 int 5283 soc_th3_process_itm_crb_int (int unit, int itm, soc_field_t itm_intr_field) { 5284 soc_reg_t block_intr_reg = MMU_CRB_CPU_INT_STATr; 5285 uint32 rval = 0; 5286 soc_field_t thdr_intr_fields[] = {MTU_VIOLATION_INTR_STATf, 5287 INV_SRC_PORT_INTR_STATf, INV_DST_PORT_INTR_STATf}; 5288 int wr_val = 1; /* w1tc */ 5289 int i; 5290 5291 for (i = 0; i < (sizeof(thdr_intr_fields) / sizeof(soc_field_t)); i++) { 5292 SOC_IF_ERROR_RETURN( 5293 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5294 if (!soc_reg_field_get(unit, block_intr_reg, 5295 rval, thdr_intr_fields[i])) { 5296 continue; 5297 } 5298 switch(thdr_intr_fields[i]) { 5299 case MTU_VIOLATION_INTR_STATf: 5300 LOG_ERROR(BSL_LS_SOC_COMMON, 5301 (BSL_META_U(unit, "Unit: %0d -- MTU violation" 5302 " intr set for ITM = %0d \n"), 5303 unit, itm)); 5304 break; 5305 case INV_SRC_PORT_INTR_STATf: 5306 LOG_ERROR(BSL_LS_SOC_COMMON, 5307 (BSL_META_U(unit, "Unit: %0d -- Invalid source port" 5308 " intr set for ITM = %0d \n"), 5309 unit, itm)); 5310 break; 5311 case INV_DST_PORT_INTR_STATf: 5312 LOG_ERROR(BSL_LS_SOC_COMMON, 5313 (BSL_META_U(unit, "Unit: %0d -- Invalid dest port" 5314 " intr set for ITM = %0d \n"), 5315 unit, itm)); 5316 break; 5317 default: 5318 break; 5319 } 5320 /*Clear block(THDR QE) level interrupt*/ 5321 rval = 0; 5322 SOC_IF_ERROR_RETURN( 5323 soc_reg32_get(unit, block_intr_reg, itm, 0, &rval)); 5324 soc_reg_field_set(unit, block_intr_reg, &rval, 5325 thdr_intr_fields[i], wr_val); 5326 SOC_IF_ERROR_RETURN( 5327 soc_reg32_set(unit, block_intr_reg, itm, 0, rval)); 5328 } 5329 /* Clear ITM and GLB level interrupts */ 5330 SOC_IF_ERROR_RETURN( 5331 soc_th3_clear_itm_int_stat(unit, itm, itm_intr_field)); 5332 5333 return SOC_E_NONE; 5334 } 5335 5336 int 5337 soc_th3_process_eb_ebctm_int (int unit, int pipe, soc_field_t eb_intr_field) { 5338 soc_reg_t block_intr_reg = MMU_EBCTM_CPU_INT_STATr; 5339 uint32 rval = 0; 5340 soc_field_t ebctm_intr_fields[] = {OVERFLOW_INTR_STATf, UNDERFLOW_INTR_STATf}; 5341 int wr_val = 1; /* w1tc */ 5342 int i; 5343 5344 for (i = 0; i < (sizeof(ebctm_intr_fields) / sizeof(soc_field_t)); i++) { 5345 SOC_IF_ERROR_RETURN( 5346 soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval)); 5347 if (!soc_reg_field_get(unit, block_intr_reg, 5348 rval, ebctm_intr_fields[i])) { 5349 continue; 5350 } 5351 switch(ebctm_intr_fields[i]) { 5352 case OVERFLOW_INTR_STATf: 5353 LOG_ERROR(BSL_LS_SOC_COMMON, 5354 (BSL_META_U(unit, "Unit: %0d -- EBCTM counters Overflow" 5355 " intr set for PIPE = %0d \n"), 5356 unit, pipe)); 5357 break; 5358 case UNDERFLOW_INTR_STATf: 5359 LOG_ERROR(BSL_LS_SOC_COMMON, 5360 (BSL_META_U(unit, "Unit: %0d -- EBCTM counters Underflow" 5361 " intr set for PIPE = %0d \n"), 5362 unit, pipe)); 5363 5364 break; 5365 default: 5366 break; 5367 } 5368 /*Clear block(EBCTM) level interrupt*/ 5369 rval = 0; 5370 SOC_IF_ERROR_RETURN( 5371 soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval)); 5372 soc_reg_field_set(unit, block_intr_reg, &rval, 5373 ebctm_intr_fields[i], wr_val); 5374 SOC_IF_ERROR_RETURN( 5375 soc_reg32_set(unit, block_intr_reg, pipe, 0, rval)); 5376 } 5377 /* Clear EB and GLB level interrupts */ 5378 SOC_IF_ERROR_RETURN( 5379 soc_th3_clear_eb_int_stat(unit, pipe, eb_intr_field)); 5380 5381 return SOC_E_NONE; 5382 } 5383 5384 int 5385 soc_th3_process_eb_ebcfp_int (int unit, int pipe, soc_field_t eb_intr_field) { 5386 soc_reg_t block_intr_reg = MMU_EBCFP_CPU_INT_STATr; 5387 uint32 rval = 0; 5388 soc_field_t ebcfp_intr_field = MTU_VIOLATIONf; 5389 int wr_val = 1; /* w1tc */ 5390 5391 SOC_IF_ERROR_RETURN( 5392 soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval)); 5393 if (soc_reg_field_get(unit, block_intr_reg, 5394 rval, ebcfp_intr_field)) { 5395 LOG_ERROR(BSL_LS_SOC_COMMON, 5396 (BSL_META_U(unit, "Unit: %0d -- MTU violation in EB" 5397 " group intr set for PIPE = %0d \n"), 5398 unit, pipe)); 5399 } 5400 /*Clear block(EBCFP) level interrupt*/ 5401 rval = 0; 5402 SOC_IF_ERROR_RETURN( 5403 soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval)); 5404 soc_reg_field_set(unit, block_intr_reg, &rval, 5405 ebcfp_intr_field, wr_val); 5406 SOC_IF_ERROR_RETURN( 5407 soc_reg32_set(unit, block_intr_reg, pipe, 0, rval)); 5408 /* Clear EB and GLB level interrupts */ 5409 SOC_IF_ERROR_RETURN( 5410 soc_th3_clear_eb_int_stat(unit, pipe, eb_intr_field)); 5411 5412 return SOC_E_NONE; 5413 } 5414 5415 int 5416 soc_th3_process_eb_mtro_int (int unit, int pipe, soc_field_t eb_intr_field) { 5417 soc_reg_t block_intr_reg = MMU_MTRO_CPU_INT_STATr; 5418 uint32 rval = 0; 5419 soc_field_t mtro_intr_field = CNT_OVERFLOWf; 5420 int wr_val = 1; /* w1tc */ 5421 5422 if (soc_reg_field_get(unit, block_intr_reg, rval, mtro_intr_field)) { 5423 SOC_IF_ERROR_RETURN( 5424 soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval)); 5425 LOG_ERROR(BSL_LS_SOC_COMMON, 5426 (BSL_META_U(unit, "Unit: %0d -- Counter overflow in MTRO" 5427 " intr set for PIPE = %0d \n"), 5428 unit, pipe)); 5429 /*Clear block(MTRO) level interrupt*/ 5430 rval = 0; 5431 SOC_IF_ERROR_RETURN( 5432 soc_reg32_get(unit, block_intr_reg, pipe, 0, &rval)); 5433 soc_reg_field_set(unit, block_intr_reg, &rval, 5434 mtro_intr_field, wr_val); 5435 SOC_IF_ERROR_RETURN( 5436 soc_reg32_set(unit, block_intr_reg, pipe, 0, rval)); 5437 /* Clear EB and GLB level interrupts */ 5438 SOC_IF_ERROR_RETURN( 5439 soc_th3_clear_eb_int_stat(unit, pipe, eb_intr_field)); 5440 } 5441 5442 return SOC_E_NONE; 5443 } 5444 5445 #endif /* BCM_TOMAHAWK3_SUPPORT */